如何在 Next.js(Pages Router)v16 中为不同地区格式化日期
以地区特定的格式显示日期
问题
日期没有统一的书写格式。例如,10/12/2025 在美国表示 10 月 12 日,而在英国则表示 12 月 10 日。写作 "Oct 12, 2025" 假设了英文月份名称和特定的排列顺序。每个地区对日期格式都有自己的习惯,包括各部分的顺序、分隔符,以及月份是用文字还是数字表示。
如果只用单一格式显示日期,应用程序会让非该地区的用户感到陌生。用户可能会误解日期,或觉得难以阅读。对某些用户清晰明了的日期格式,对其他用户可能会造成困惑或歧义。
解决方案
根据用户的 locale 格式化日期,将日期值转换为符合地区规则的字符串,包括顺序、分隔符和月份名称。浏览器的 Intl.DateTimeFormat API 可以根据 locale 和可选的格式化参数,自动处理地区相关的日期格式规则。
react-intl 提供了封装该 API 的组件和 hooks,并与应用的 locale 上下文集成。通过将日期值和格式化选项传递给这些工具,日期会以用户语言和地区习惯的方式清晰自然地显示。
步骤
1. 使用 FormattedDate 创建日期格式化组件
FormattedDate 组件接受日期值和符合 Intl.DateTimeFormatOptions 的格式化选项。可以创建一个组件,以所需的详细程度显示日期。
import { FormattedDate } from "react-intl";
interface EventDateProps {
date: Date;
}
export function EventDate({ date }: EventDateProps) {
return (
<time dateTime={date.toISOString()}>
<FormattedDate value={date} year="numeric" month="long" day="numeric" />
</time>
);
}
FormattedDate 会从 IntlProvider 上下文中读取 locale,并相应地格式化日期。例如,en-US 会显示 "October 12, 2025",而 en-GB 会显示 "12 October 2025"。
2. 使用 useIntl 以命令式方式格式化日期
在无法使用 React 组件的场景(如设置文本属性)下,可以通过 useIntl hook 获取 formatDate 方法来格式化日期。
import { useIntl } from "react-intl";
interface ArticleImageProps {
src: string;
publishedAt: Date;
}
export function ArticleImage({ src, publishedAt }: ArticleImageProps) {
const intl = useIntl();
const formattedDate = intl.formatDate(publishedAt, {
year: "numeric",
month: "short",
day: "numeric",
});
return <img src={src} alt={`Article published on ${formattedDate}`} />;
}
formatDate 方法会返回格式化后的日期字符串,并接受符合 DateTimeFormatOptions 的选项。此方法适用于属性、服务端代码或对性能要求较高的场景。
3. 通过标准选项调整格式化细节
可以通过指定 year、month、day 和 weekday 等选项,并设置为 "numeric"、"2-digit"、"long"、"short" 或 "narrow" 等值,来控制日期各部分的显示方式。
import { FormattedDate } from "react-intl";
export function FullEventDate({ date }: { date: Date }) {
return (
<FormattedDate
value={date}
weekday="long"
year="numeric"
month="long"
day="numeric"
/>
);
}
export function CompactDate({ date }: { date: Date }) {
return (
<FormattedDate value={date} year="2-digit" month="2-digit" day="2-digit" />
);
}
FullEventDate 组件在 en-US 下会渲染为 "Monday, October 12, 2025",在 de-DE 下会渲染为 "Montag, 12. Oktober 2025"。CompactDate 组件则会生成适合表格或紧凑布局的简短数字格式。
4. 创建可复用的日期格式化辅助函数
为了在多个页面中保持日期格式一致,可以创建一个封装常用格式化模式的辅助函数。
import { useIntl } from "react-intl";
export function useDateFormatters() {
const intl = useIntl();
return {
formatShortDate: (date: Date) =>
intl.formatDate(date, {
year: "numeric",
month: "short",
day: "numeric",
}),
formatLongDate: (date: Date) =>
intl.formatDate(date, {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
}),
formatMonthYear: (date: Date) =>
intl.formatDate(date, {
year: "numeric",
month: "long",
}),
};
}
在任意页面组件中导入并使用该 hook,即可无需重复配置选项地实现一致的日期格式化。
5. 在页面组件中使用辅助函数
在 Next.js 页面中应用日期格式化辅助函数,以展示符合本地化的日期。
import { GetStaticProps } from "next";
import { useDateFormatters } from "../lib/useDateFormatters";
interface Post {
title: string;
publishedAt: string;
content: string;
}
interface BlogPostPageProps {
post: Post;
}
export default function BlogPostPage({ post }: BlogPostPageProps) {
const { formatLongDate } = useDateFormatters();
const publishedDate = new Date(post.publishedAt);
return (
<article>
<h1>{post.title}</h1>
<p>Published: {formatLongDate(publishedDate)}</p>
<div>{post.content}</div>
</article>
);
}
export const getStaticProps: GetStaticProps = async () => {
const post = {
title: "Understanding Internationalization",
publishedAt: "2025-10-12T00:00:00Z",
content: "Content here...",
};
return {
props: { post },
};
};
页面会以用户本地格式显示发布日期,使各地区读者能够一目了然地理解日期信息。