month: 'numeric'和'2-digit'输出数字(如3、03),非名称;需用'long'/'short'/'narrow'显示名称;中文需numberingsystem: 'hanidec'才得“三月”;'narrow'兼容性差;format()必须传date实例,且month参数为0索引。

month: 'numeric' 和 month: '2-digit' 都只输出数字,不是名称
很多人以为 month 选项能直接控制“几月”还是“几月几日”,结果发现设成 'numeric' 或 '2-digit' 输出的是 3 或 03,根本不是“三月”或“Mar”。这是因为这两个值明确表示「数字形式」,和月份名称完全无关。
要显示名称,必须用 'long'、'short' 或 'narrow' —— 它们才是专为文本设计的值。
-
'long':输出完整月份名,如'March'(en-US)、'三月'(zh-CN) -
'short':缩写,如'Mar'、'3月' -
'narrow':极简单字母/字,如'M'、'3'(注意:中文里通常仍是'3',不是字)
locale 和 numberingSystem 共同决定中文是否显示“三月”而非“3月”
中文环境下,Intl.DateTimeFormat('zh-CN', { month: 'short' }) 默认输出 '3月',不是 '三月'。这不是 bug,而是默认使用阿拉伯数字编号系统(numberingSystem: 'latn')。
想强制用汉字数字,得显式指定 numberingSystem: 'hanidec':
new Intl.DateTimeFormat('zh-CN', {
month: 'long',
numberingSystem: 'hanidec'
}).format(new Date(2024, 2)) // → '三月'
但要注意:'hanidec' 在部分浏览器(如旧版 Safari)支持不稳;且 'narrow' 模式下即使设了 hanidec,仍可能回退为数字。
month: 'narrow' 在不同 locale 下行为差异大,慎用于 UI 显示
'narrow' 看似省空间,实际兼容性最差。英文 locale 下它可能返回单字母('J', 'F'),但这些字母在不同语言里未必唯一(比如 'M' 可能是 March / May / June 的首字母)。
中文 locale 下,'narrow' 基本等价于 'numeric',返回 '1'~'12',无法区分“一月”和“十一月”——因为汉字单字缩写无通用规范。
- 别用
'narrow'做可交互的月份选择器标签 - 若真需极简,优先用
'short'+ CSS 控制宽度,更可控 - 测试时务必覆盖目标 locale,不能只看 en-US
格式化结果依赖完整日期对象,单独传 month 不生效
常见错误是试图只传一个数字月份给 format():
const fmt = new Intl.DateTimeFormat('ja-JP', { month: 'long' });
fmt.format(3); // ❌ 报错或返回无效字符串
Intl.DateTimeFormat.prototype.format() 只接受 Date 实例(或时间戳毫秒数)。月份值必须嵌在日期中:
fmt.format(new Date(2024, 2, 1)); // ✅ '3月'(注意:month 是 0-indexed)
如果只有月份数字(如后端返回 3),必须手动构造日期对象,且注意 new Date(year, monthIndex) 中 monthIndex 是从 0 开始的 —— 直接传 3 会变成四月。
'zh-cn' 可能降级为默认 locale),以及 numberingSystem 的隐式 fallback 行为。别假设“设了就一定生效”,尤其在混合多语言的 SSR 场景中。










