如何在 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 选项接受的值包括 numeric、2-digit、short、long 和 narrow。weekday 选项会添加星期几。每个区域设置会根据其自身的约定解释这些选项,确保输出符合用户的期望。
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>
);
}
添加 hour 和 minute 选项会生成一个包含日期和时间的组合字符串。具体使用 12 小时制还是 24 小时制,以及如何分隔日期和时间部分,取决于所使用的区域设置。这确保了时间戳的格式与区域显示习惯保持一致。