如何按照用户的语言区域格式化日期

使用 JavaScript 根据每个用户的区域习惯显示日期

简介

日期在世界各地的显示方式不同。美国人将 2025 年 3 月 15 日写作 3/15/2025,而欧洲人将同一日期写作 15/03/2025,日本用户则期望看到 2025/3/15。当您硬编码日期格式时,就假设了所有用户都遵循相同的惯例。

以不熟悉的格式显示日期会引起混淆。看到 3/15/2025 而期望 15/03/2025 的用户必须停下来解读日期是指 3 月 15 日还是不可能存在的第 15 个月。这种认知负担会在应用程序中的每个日期上累积。

JavaScript 提供了 Intl.DateTimeFormat API 来自动处理日期格式化。本课程将解释为什么日期格式因文化而异、API 的工作原理以及如何为任何区域正确格式化日期。

为什么日期格式因地区而异

不同地区发展了不同的日期书写惯例。这些惯例反映了历史实践、教育体系和文化偏好。没有一种格式是通用的。

在美国,日期遵循月-日-年模式。2025 年 3 月 15 日写作 3/15/2025

在包括英国、德国、法国和西班牙在内的大多数欧洲国家,日期遵循日-月-年模式。同一日期写作 15/03/2025

在日本、中国和韩国,日期遵循年-月-日模式。日期写作 2025/3/15

不同地区还使用不同的分隔符。美国人使用斜杠,德国人使用句点,有些地区使用连字符或空格。

月份名称也因语言而异。3 月在英语中是 "March",在德语中是 "März",在法语中是 "mars",在西班牙语中是 "marzo",在日语中是 "3月"。

当您显示日期时,需要匹配用户对组件顺序和具体格式惯例的期望。

使用 Intl.DateTimeFormat 格式化日期

Intl.DateTimeFormat 构造函数创建一个日期格式化器,应用特定语言环境的约定。将语言环境标识符作为第一个参数传递,然后使用 format() 方法传入一个 Date 对象。

const formatter = new Intl.DateTimeFormat('en-US');
const date = new Date('2025-03-15');
console.log(formatter.format(date));
// 输出: "3/15/2025"

这会创建一个适用于美式英语的格式化器,使用斜杠分隔的月-日-年模式。format() 方法将 Date 对象转换为具有适当格式的字符串。

Date 构造函数接受一个 ISO 8601 日期字符串,例如 2025-03-15。这会创建一个表示 2025 年 3 月 15 日午夜 UTC 的 Date 对象。格式化器随后将其转换为特定语言环境的字符串。

为不同语言环境格式化相同日期

通过更改传递给构造函数的语言环境标识符,可以为不同的语言环境格式化相同的日期。

const date = new Date('2025-03-15');

const usFormatter = new Intl.DateTimeFormat('en-US');
console.log(usFormatter.format(date));
// 输出: "3/15/2025"

const gbFormatter = new Intl.DateTimeFormat('en-GB');
console.log(gbFormatter.format(date));
// 输出: "15/03/2025"

const deFormatter = new Intl.DateTimeFormat('de-DE');
console.log(deFormatter.format(date));
// 输出: "15.3.2025"

const jpFormatter = new Intl.DateTimeFormat('ja-JP');
console.log(jpFormatter.format(date));
// 输出: "2025/3/15"

每个格式化器应用不同的约定。美式格式化器使用斜杠分隔的月-日-年模式。英式格式化器使用斜杠分隔的日-月-年模式。德式格式化器使用句点分隔的日-月-年模式。日式格式化器使用斜杠分隔的年-月-日模式。

您无需了解每种语言环境使用的模式或分隔符。API 会根据语言环境标识符自动处理这些细节。

为用户的语言环境格式化日期

与硬编码特定语言环境不同,您可以使用浏览器提供的用户首选语言。navigator.language 属性返回用户的首选语言。

const userLocale = navigator.language;
const formatter = new Intl.DateTimeFormat(userLocale);
const date = new Date('2025-03-15');

console.log(formatter.format(date));
// 输出因用户的语言环境而异
// 对于 en-US: "3/15/2025"
// 对于 en-GB: "15/03/2025"
// 对于 de-DE: "15.3.2025"
// 对于 ja-JP: "2025/3/15"

这种方法根据每个用户的期望显示日期,而无需用户手动选择语言环境。浏览器提供语言偏好,Intl API 应用适当的格式化约定。

您还可以传递整个首选语言数组以启用回退行为。

const formatter = new Intl.DateTimeFormat(navigator.languages);
const date = new Date('2025-03-15');
console.log(formatter.format(date));

API 使用数组中支持的第一个语言环境。这在用户的首选语言不可用时提供了更好的回退处理。

理解 API 的格式化功能

Intl.DateTimeFormat API 用于格式化 JavaScript 的 Date 对象。Date 对象表示一个特定的时间点,包括日期、时间和时区信息。

当您格式化一个 Date 对象时,API 会根据区域设置的约定将其转换为字符串。默认情况下,API 仅格式化日期部分并忽略时间部分。

const formatter = new Intl.DateTimeFormat('en-US');

const dateWithTime = new Date('2025-03-15T14:30:00');
console.log(formatter.format(dateWithTime));
// 输出: "3/15/2025"

Date 对象包含时间信息,但默认的格式化器会忽略它。在后续课程中,我们将介绍如何同时格式化日期和时间,或仅格式化时间。

创建可格式化的日期

您可以通过多种方式创建 Date 对象。最可靠的方法是使用 ISO 8601 日期字符串。

const date1 = new Date('2025-03-15');
const date2 = new Date('2025-12-31');
const date3 = new Date('2025-01-01');

const formatter = new Intl.DateTimeFormat('en-US');

console.log(formatter.format(date1));
// 输出: "3/15/2025"

console.log(formatter.format(date2));
// 输出: "12/31/2025"

console.log(formatter.format(date3));
// 输出: "1/1/2025"

ISO 8601 字符串使用 YYYY-MM-DD 格式。这种格式明确且在所有区域设置和时区中都能一致工作。

从时间戳格式化日期

您还可以通过 Unix 时间戳创建 Date 对象。Unix 时间戳表示自 1970 年 1 月 1 日 UTC 起的毫秒数。

const timestamp = 1710489600000; // 2025 年 3 月 15 日
const date = new Date(timestamp);

const formatter = new Intl.DateTimeFormat('en-US');
console.log(formatter.format(date));
// 输出: "3/15/2025"

当您从 API、数据库或其他以数字表示日期的系统接收时间戳时,这种方法非常有用。

您还可以直接将时间戳传递给 format() 方法,而无需先创建 Date 对象。

const formatter = new Intl.DateTimeFormat('en-US');
const timestamp = 1710489600000;

console.log(formatter.format(timestamp));
// 输出: "3/15/2025"

该 API 同时接受 Date 对象和时间戳。根据您的代码需求选择适合的方式。

格式化当前日期

要格式化当前日期,可以创建一个不带参数的 Date 对象。这将创建一个表示当前时刻的 Date 对象。

const formatter = new Intl.DateTimeFormat('en-US');
const now = new Date();

console.log(formatter.format(now));
// 输出: "10/15/2025"(或运行时的当前日期)

您也可以直接传递 Date.now(),它会返回当前时间戳(以数字形式)。

const formatter = new Intl.DateTimeFormat('en-US');

console.log(formatter.format(Date.now()));
// 输出: "10/15/2025"(或运行时的当前日期)

这两种方法的结果是相同的。

为性能重用格式化器

创建一个新的 Intl.DateTimeFormat 实例需要加载区域设置数据并处理选项。当您需要使用相同的区域设置和设置格式化多个日期时,可以创建一次格式化器并重复使用它。

const formatter = new Intl.DateTimeFormat('en-US');

const dates = [
  new Date('2025-01-01'),
  new Date('2025-06-15'),
  new Date('2025-12-31')
];

dates.forEach(date => {
  console.log(formatter.format(date));
});
// 输出:
// "1/1/2025"
// "6/15/2025"
// "12/31/2025"

这种方法比为每个日期创建一个新的格式化器更高效。当需要格式化包含数百或数千个日期的数组时,性能差异会变得显著。

在模板中格式化日期

您可以在任何向用户显示日期的地方使用 Intl.DateTimeFormat。这包括将格式化的日期插入到 HTML 模板中、在表格中显示日期或在用户界面中显示时间戳。

const formatter = new Intl.DateTimeFormat(navigator.language);

const publishedDate = new Date('2025-03-15');
const updatedDate = new Date('2025-04-20');

document.getElementById('published').textContent = formatter.format(publishedDate);
document.getElementById('updated').textContent = formatter.format(updatedDate);

格式化后的字符串与其他字符串值一样。您可以将它们插入到文本内容、属性或任何其他显示信息给用户的上下文中。