Skip to content
文档使用指南日期和时间

日期和时间格式化

想看视频吗?

日期和时间的格式在不同地区差异很大(例如,en-US 中是 “Apr 24, 2023”,而 uk-UA 中是 “24 квіт. 2023 р.”)。通过使用 next-intl 的格式化功能,您可以在 Next.js 应用中自动处理国际化差异。

格式化日期和时间

您可以使用从 useFormatter 钩子返回的 dateTime 函数格式化不属于消息的纯日期:

import {useFormatter} from 'next-intl';
 
function Component() {
  const format = useFormatter();
  const dateTime = new Date('2020-11-20T10:36:01.516Z');
 
  // 渲染结果为 "Nov 20, 2020"
  format.dateTime(dateTime, {
    year: 'numeric',
    month: 'short',
    day: 'numeric'
  });
 
  // 渲染结果为 "11:36 AM"
  format.dateTime(dateTime, {hour: 'numeric', minute: 'numeric'});
}

查看 MDN 上关于 DateTimeFormat 的文档了解可以传递给 dateTime 函数的更多选项,或者尝试 交互式探索器 来体验 Intl.DateTimeFormat

如果您配置了全局格式,可以通过将名称作为第二个参数传递来引用它们:

// 使用全局格式
format.dateTime(dateTime, 'short');
 
// 可选覆盖部分选项
format.dateTime(dateTime, 'short', {year: 'numeric'});
我应该如何存储和解析日期和时区?

您应确保日期是完整的 ISO 8601 字符串,例如 2020-11-20T10:36:01.516Z

由于 next-intl 只负责格式化日期,您可以在前端通过 Date 构造函数解析后进行格式化。

更多学习:

格式化相对时间

您可以使用 relativeTime 函数格式化不属于消息的纯日期:

import {useFormatter} from 'next-intl';
 
function Component() {
  const format = useFormatter();
  const dateTime = new Date('2020-11-20T08:30:00.000Z');
 
  // 一个参考时间点
  const now = new Date('2020-11-20T10:36:00.000Z');
 
  // 这将渲染为 "2 hours ago"
  format.relativeTime(dateTime, now);
}

注意,数值会被四舍五入,例如经过 126 分钟,会返回 “2 hours ago”。

更多学习:

useNow 钩子

由于传入 now 是常见模式,next-intl 提供了一个便捷钩子来获取当前日期时间:

import {useNow, useFormatter} from 'next-intl';
 
function FormattedDate({date}) {
  const now = useNow();
  const format = useFormatter();
 
  format.relativeTime(date, now);
}

与在组件中直接调用 new Date() 相比,useNow 有以下优势:

  1. 在客户端重新渲染时返回的值一致。
  2. 可以可选使用 updateInterval 持续更新数值。
  3. 数值可以可选从全局值初始化。默认情况下,useNow 会使用当前时间。

updateInterval 参数

如果希望相对时间随时间更新,可以使用 useNow 钩子实现:

import {useNow, useFormatter} from 'next-intl';
 
function Component() {
  // 初始使用全局的 now 值 …
  const now = useNow({
    // … 并且每 10 秒更新一次
    updateInterval: 1000 * 10
  });
 
  const format = useFormatter();
  const dateTime = new Date('2020-11-20T10:36:01.516Z');
 
  // 渲染例如 "2 hours ago" 并持续更新
  format.relativeTime(dateTime, now);
}

自定义单位

默认情况下,relativeTime 会基于传入的日期和 now 之间的差异自动选择单位,比如 “3 seconds” 或者 “5 days”。

如果想使用特定单位,可以通过第二个参数传递选项:

import {useFormatter} from 'next-intl';
 
function Component() {
  const format = useFormatter();
  const dateTime = new Date('2020-03-20T08:30:00.000Z');
  const now = new Date('2020-11-22T10:36:00.000Z');
 
  // 渲染 "247 days ago"
  format.relativeTime(dateTime, {now, unit: 'day'});
}

格式化日期和时间范围

您可以使用 dateTimeRange 函数格式化日期和时间区间:

import {useFormatter} from 'next-intl';
 
function Component() {
  const format = useFormatter();
  const dateTimeA = new Date('2020-11-20T08:30:00.000Z');
  const dateTimeB = new Date('2021-01-24T08:30:00.000Z');
 
  // 渲染 "Nov 20, 2020 – Jan 24, 2021"
  format.dateTimeRange(dateTimeA, dateTimeB, {
    year: 'numeric',
    month: 'short',
    day: 'numeric'
  });
}

如果您配置了全局格式,可以通过第三个参数传入格式名称来引用它们:

// 使用全局格式
format.dateTimeRange(dateTimeA, dateTimeB, 'short');
 
// 可选覆盖部分选项
format.dateTimeRange(dateTimeA, dateTimeB, 'short', {year: 'numeric'});

消息中的日期和时间

日期和时间可以通过 ICU 语法嵌入消息中。

en.json
{
  "ordered": "Ordered on {orderDate, date, medium}"
}

默认支持的格式包括:fulllongmediumshort

💡

如果您与翻译人员合作,使用支持 ICU 日期时间语法的编辑器会非常有帮助(例如 Crowdin 编辑器)。

您也可以使用日期骨架自定义格式:

en.json
{
  // 渲染例如 "Ordered on Jul 9, 2024"
  "ordered": "Ordered on {orderDate, date, ::yyyyMMMd}"
}

注意前导的 :: 表示应使用骨架格式。

支持的 ICU 格式如下:

符号含义模式示例
G纪元设计ator(包含日期)G
GGGG
GGGGG
7/9/2024 AD
7/9/2024 Anno Domini
7/9/2024 A
yy
yy
yyyy
2024
24
2024
M月份(年内)M
MM
MMM
MMMM
MMMMM
7
07
Jul
July
J
d月内日期d
dd
9
09
E星期几E
EEEE
EEEEE
Tue
Tuesday
T
h小时(1-12)h
hh
9 AM
09 AM
K小时(0-11)K
KK
0 AM (12 AM 使用 h)
00 AM
H小时(0-23)HH09
k小时(1-24)kk24(使用 H 时为 00)
m分钟(如果包含秒数则为两位)m
mmss
6
06:03
s秒数(如果包含分钟则为两位)s
mmss
3
06:03
z时区z
zzzz
GMT+2
Central European Summer Time

模式可以互相组合,例如 yyyyMMMd 会输出 “Jul 9, 2024”。

自定义日期和时间格式

想在消息中使用自定义格式,可以基于 DateTimeFormat 选项 提供格式化器并通过名称引用。

en.json
{
  "ordered": "Ordered on {orderDate, date, short}"
}
t(
  'ordered',
  {orderDate: new Date('2020-11-20T10:36:01.516Z')},
  {
    dateTime: {
      short: {
        day: 'numeric',
        month: 'short',
        year: 'numeric'
      }
    }
  }
);
💡

若要在多个组件间复用日期和时间格式,可以配置 全局格式