Intl.DateTimeFormat构造函数需显式传入locale和options才可控,否则依赖环境设置导致不一致;例如new Intl.DateTimeFormat('zh-CN', {year:'numeric',month:'long',day:'numeric'})格式化日期为“2024年5月20日”。

Intl.DateTimeFormat 构造函数的基本用法
直接 new Intl.DateTimeFormat() 就能拿到本地默认格式的日期字符串,但实际项目中几乎不会这么用——它依赖运行环境的区域设置,跨浏览器或服务端(Node.js)输出不一致。
必须显式传入 locale 和 options 才可控。比如想固定输出中文简体的“2024年5月20日”,就得写:
new Intl.DateTimeFormat('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric'
}).format(new Date('2024-05-20')) // → "2024年5月20日"
-
locale推荐用字符串如'zh-CN'、'en-US',避免传undefined或空字符串,否则部分旧版 Safari 会抛RangeError -
options中的year/month/day是必选其一的,全不设会返回空字符串 - 不要用
weekday: 'long'搭配era: 'short'这类非常规组合,某些 Android WebView 会静默失败
处理时区偏移和 UTC 时间
默认情况下 Intl.DateTimeFormat 使用宿主系统的时区,不是 UTC。要显示 UTC 时间,必须在 options 中明确指定 timeZone: 'UTC',而不是靠 toUTCString() 预处理时间对象。
常见错误是先调 date.toISOString().slice(0, 10) 截字符串,这丢掉了时区语义,且无法响应 locale 变化。
立即学习“前端免费学习笔记(深入)”;
- 显示东八区时间:用
timeZone: 'Asia/Shanghai',别用timeZone: '+0800'(非法值,Chrome 会 fallback 到系统时区) - 服务端渲染(SSR)时若用 Node.js,需确认 ICU 数据是否完整;Ubuntu 默认安装可能缺
full-icu,导致timeZone识别失败并静默退化为本地时区 -
hour12: true在en-US下生效,在zh-CN下无效(中文默认 24 小时制),不能靠它强制切换
格式化时间部分(小时/分钟/秒)的陷阱
单独格式化时间容易漏掉 hourCycle 参数,导致 AM/PM 显示异常。例如在 en-US 下没设 hour12: true,会输出 24 小时制的 “14:30”,而非 “2:30 PM”。
更隐蔽的问题是 minute 和 second 的粒度控制:设 minute: 'numeric' 但不设 hour,结果是只有分钟数(如 “30”),这通常不是你想要的。
- 要输出带 AM/PM 的时间,必须同时设
hour12: true和hour: 'numeric',仅前者不够 -
second: '2-digit'会补零('07'),而'numeric'不补('7'),注意 UI 对齐需求 - 在 iOS 15.4 之前的 WebKit 中,
fractionalSecondDigits: 3会被忽略,返回整秒,别依赖毫秒级精度
性能与复用:别每次 format 都 new 实例
频繁调用 new Intl.DateTimeFormat(...).format(date) 会触发重复初始化,尤其在循环或 React 渲染中,实测比复用实例慢 3–5 倍。
正确做法是把格式器缓存为常量或模块级变量,特别是当 locale 和 options 固定时。
- React 中可在模块顶层定义:
const zhDateFormatter = new Intl.DateTimeFormat('zh-CN', { dateStyle: 'medium' }) - 如果需要动态 locale,用 Map 缓存不同 locale 的实例,键为
${locale}-${JSON.stringify(options)}字符串 - Vite / Webpack 打包时,
Intl.DateTimeFormat不会被 tree-shake,但也不用担心体积——它是引擎内置 API,不增加 bundle 大小
最易被忽略的是构造时的 locale 兼容性:传 'zh' 可能在某些系统上 fallback 到英文,而 'zh-Hans' 或 'zh-CN' 更稳妥;另外,服务端 Node.js 版本低于 18.17 时,timeZone 选项对非 IANA 名称(如 'GMT+8')支持不完整。



















