如何在 TanStack Start v1 中为不同的区域设置格式化日期

以区域特定的格式显示日期

问题

日期没有通用的显示格式。序列 10/12/2025 在美国表示 10 月 12 日,但在英国则表示 12 月 10 日。书写 "Oct 12, 2025" 假定了英语月份名称和特定的排序规则。每个地区对日期格式都有自己的期望,包括日、月、年的顺序,分隔符的选择,以及月份名称是全拼还是缩写。当应用程序以单一固定格式显示日期时,对于大多数地区的用户来说,这种格式显得陌生且令人困惑。

用户期望日期以他们日常使用和学习的格式显示。对一个受众来说看起来自然的日期格式,对另一个受众可能是模糊或令人不适的。如果没有基于区域的格式化,日期会成为一种摩擦点,削弱用户体验,使应用程序显得不够专业。

解决方案

根据用户的区域设置格式化日期,将日期值转换为符合区域惯例的字符串,包括顺序、分隔符和月份名称。React-intl 提供了格式化函数和组件,这些工具利用浏览器内置的国际化 API 自动应用每个区域的正确规则。通过将日期值和可选的格式化选项传递给这些工具,应用程序可以生成既清晰又符合用户语言和地区习惯的输出。

这种方法确保了日期的正确显示,而无需手动为每个区域实现格式化逻辑。格式化会根据用户的区域设置进行调整,使日期一目了然,减少认知负担。

步骤

1. 使用 useIntl 钩子创建一个格式化日期的组件

使用 useIntl 钩子访问 formatDate 方法,该方法将日期值转换为符合区域设置的字符串。

import { useIntl } from "react-intl";

export function EventDate({ date }: { date: Date }) {
  const intl = useIntl();

  return (
    <time dateTime={date.toISOString()}>
      {intl.formatDate(date, {
        year: "numeric",
        month: "long",
        day: "numeric",
      })}
    </time>
  );
}

formatDate 方法根据区域设置应用日期显示的约定。选项对象控制日期的哪些部分显示以及它们的详细程度。格式化的字符串会根据组件树中更高层的 IntlProvider 提供的区域设置进行适配。

2. 使用预定义选项以特定样式格式化日期

通过传递不同的选项组合来控制日期格式样式,例如简短的数字日期或详细的描述性日期。

import { useIntl } from "react-intl";

export function ArticleMetadata({ publishedAt }: { publishedAt: Date }) {
  const intl = useIntl();

  const shortDate = intl.formatDate(publishedAt, {
    year: "numeric",
    month: "short",
    day: "numeric",
  });

  const longDate = intl.formatDate(publishedAt, {
    year: "numeric",
    month: "long",
    day: "numeric",
    weekday: "long",
  });

  return (
    <div>
      <p>发布于: {shortDate}</p>
      <p>完整日期: {longDate}</p>
    </div>
  );
}

month 选项接受的值包括 numeric2-digitshortlongnarrowweekday 选项会添加星期几。每个区域设置会根据其自身的约定解释这些选项,确保输出符合用户的期望。

3. 使用 FormattedDate 组件进行声明式格式化

使用 FormattedDate 组件以声明式方式渲染日期,该组件接受与 formatDate 方法相同的格式化选项。

import { FormattedDate } from "react-intl";

export function OrderSummary({ orderDate }: { orderDate: Date }) {
  return (
    <div>
      <h2>订单下单日期</h2>
      <FormattedDate
        value={orderDate}
        year="numeric"
        month="long"
        day="numeric"
      />
    </div>
  );
}

FormattedDate 组件默认以 React 片段的形式渲染格式化日期。它使用来自 IntlProvider 上下文的区域设置,并应用与命令式 API 相同的格式化规则。当格式化日期是组件树中该部分唯一需要的内容时,这种方法非常适用。

4. 格式化包含时间信息的日期

通过添加小时和分钟选项,可以在单个格式化字符串中同时显示日期和时间。

import { useIntl } from "react-intl";

export function AppointmentCard({ scheduledAt }: { scheduledAt: Date }) {
  const intl = useIntl();

  return (
    <div>
      <p>
        计划时间:{" "}
        {intl.formatDate(scheduledAt, {
          year: "numeric",
          month: "short",
          day: "numeric",
          hour: "numeric",
          minute: "2-digit",
        })}
      </p>
    </div>
  );
}

添加 hourminute 选项会生成一个包含日期和时间的组合字符串。具体使用 12 小时制还是 24 小时制,以及如何分隔日期和时间部分,取决于所使用的区域设置。这确保了时间戳的格式与区域显示习惯保持一致。