JavaScript 中的 Intl.DateTimeFormat 与日期时间本地化格式化
描述
Intl.DateTimeFormat 是 JavaScript 国际化 API(Intl)的一部分,用于根据特定的语言和地区(locale)以及自定义的格式选项,来格式化和解析日期和时间。它解决了在不同语言和文化环境中,日期和时间显示格式差异的问题,例如年月日顺序、星期/月份名称、日历类型、时区表示等。掌握它能让你开发出适应全球用户的 Web 应用。
解题过程/原理讲解
第一步:基本概念与创建实例
Intl.DateTimeFormat 是一个构造函数。你可以通过 new 操作符来创建一个格式化器实例。创建时可以传入两个参数:
- locales(可选):一个字符串或字符串数组,指定要使用的语言和地区。例如
'en-US'、'zh-CN'、['de-DE', 'en-GB']。如果未提供或提供undefined,将使用运行环境的默认区域设置。 - options(可选):一个配置对象,用于控制格式化输出的详细信息,如日期各部分是否显示、格式风格、日历类型、时区等。
// 创建一个针对美国英语的简单格式化器
const usFormatter = new Intl.DateTimeFormat('en-US');
// 创建一个针对简体中文,并指定部分选项的格式化器
const cnFormatter = new Intl.DateTimeFormat('zh-CN', { weekday: 'long' });
第二步:核心方法 format()
创建格式化器实例后,其主要作用就是通过 format() 方法将一个 Date 对象格式化为符合该区域设置的字符串。
const date = new Date('2023-11-05T14:48:00Z'); // 创建一个特定的日期对象
console.log(usFormatter.format(date)); // 输出(在en-US区域下): "11/5/2023"
console.log(cnFormatter.format(date)); // 输出(在zh-CN区域下,且只显示星期): "星期日"
注意:format() 方法在内部会先调用其参数(如果是一个 Date 对象)的 toISOString() 方法以确保处理一个有效日期。但更关键的是,格式化过程考虑了以下两点:
- 时区转换:默认情况下,
Intl.DateTimeFormat使用运行环境的本地时区来显示时间。上面的例子中,输入是 UTC 时间 14:48,输出会根据你电脑的时区进行调整。例如,如果你在东八区,usFormatter.format(date)可能显示 "11/5/2023, 10:48 PM" 这样的结果(如果默认包含了时间部分)。 - 区域格式化规则:数字、名称、顺序等都遵循传入的
locales参数。
第三步:格式化选项详解
options 对象提供了细粒度控制。主要属性可分为以下几类:
A. 日期部件与样式
可以分别为年、月、日、星期、时、分、秒、时区等部件指定是否显示以及显示风格。
weekday: 星期,可选值'narrow'(如 "S")、'short'(如 "Sun")、'long'(如 "Sunday")。era: 纪元,可选值'narrow'、'short'、'long'。如 "BC"、"AD"。year: 年,可选值'numeric'(如 "2023")、'2-digit'(如 "23")。month: 月,可选值'numeric'(如 "11")、'2-digit'(如 "11")、'short'(如 "Nov")、'long'(如 "November")、'narrow'(如 "N")。day: 日,可选值'numeric'(如 "5")、'2-digit'(如 "05")。hour: 时,可选值'numeric'(如 "14")、'2-digit'(如 "14")。minute: 分,可选值'numeric'、'2-digit'。second: 秒,可选值'numeric'、'2-digit'。timeZoneName: 时区名,可选值'short'(如 "GMT+8")、'long'(如 "China Standard Time")、'shortOffset'、'longOffset'等。
const date = new Date('2023-11-05T14:48:00Z');
const formatter = new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: '2-digit',
weekday: 'short',
hour: '2-digit',
minute: '2-digit',
timeZoneName: 'short'
});
console.log(formatter.format(date)); // 例如: "Sun, November 05, 2023, 10:48 PM GMT+8"
B. 整体格式化风格
dateStyle 和 timeStyle 属性提供预设的常见格式,比单独设置每个部件更方便。可选值为 'full'、'long'、'medium'、'short'。
- 注意:
dateStyle和timeStyle不能与上面单独设置的部件属性(如hour、month等)同时使用。
const date = new Date();
console.log(new Intl.DateTimeFormat('zh-CN', { dateStyle: 'full', timeStyle: 'long' }).format(date));
// 输出示例: "2023年11月5日星期日 中国标准时间 22:48:00"
console.log(new Intl.DateTimeFormat('en-GB', { dateStyle: 'short', timeStyle: 'short' }).format(date));
// 输出示例: "05/11/2023, 22:48"
C. 时区、日历、编号系统
timeZone: 明确指定时区,如'Asia/Shanghai'、'America/New_York'、'UTC'。不指定则使用运行环境的时区。calendar: 指定日历类型,如'gregory'(公历)、'chinese'(农历)等。需要运行时环境支持。numberingSystem: 指定数字编号系统,如'arab'(阿拉伯数字)、'hanidec'(中文十进制数字)等。这会影响日期中数字的显示。
const date = new Date();
const formatter = new Intl.DateTimeFormat('zh-CN-u-ca-chinese', { // 使用中文区域和农历日历
timeZone: 'Asia/Shanghai',
year: 'numeric',
month: 'long',
day: 'numeric',
calendar: 'chinese'
});
console.log(formatter.format(date)); // 输出农历日期
第四步:获取格式化结果的详细信息 formatToParts()
format() 返回一个拼接好的字符串。如果你需要获取格式化后每个部分的详细信息(如“年”、“月”、“日”等文本片段),以便进行进一步处理或自定义渲染,可以使用 formatToParts() 方法。它返回一个对象数组,每个对象包含 type (类型,如 'year'、'month'、'literal') 和 value (该部分的字符串值)。
const date = new Date('2023-11-05');
const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
const parts = formatter.formatToParts(date);
console.log(parts);
// 输出类似:
// [
// { type: 'month', value: 'November' },
// { type: 'literal', value: ' ' },
// { type: 'day', value: '5' },
// { type: 'literal', value: ', ' },
// { type: 'year', value: '2023' }
// ]
第五步:查询区域设置支持的功能
通过静态方法 Intl.DateTimeFormat.supportedLocalesOf() 可以查询当前运行环境是否支持传入的区域设置。它返回一个经过筛选的、支持的区域设置数组。
const locales = ['zh-CN', 'en-US', 'de-DE', 'xx-YY']; // 假设'xx-YY'不被支持
const supported = Intl.DateTimeFormat.supportedLocalesOf(locales);
console.log(supported); // 输出: ["zh-CN", "en-US", "de-DE"]
总结
Intl.DateTimeFormat 的核心步骤是:
- 创建实例:通过
new Intl.DateTimeFormat(locales, options)构造一个格式化器,定义目标区域和格式规则。 - 格式化:调用实例的
format(date)方法,传入Date对象,得到本地化的日期时间字符串。底层会根据options和locales进行时区转换、名称本地化、格式编排。 - 高级控制:通过
formatToParts()获取结构化部件,或通过supportedLocalesOf()检查兼容性。
它使得日期时间的国际化展示变得标准化和简单,无需手动拼接字符串或处理复杂的地区差异规则。