date-fns 把季度显示为第三季度,zh-CN 解析却报 Invalid Date
date-fns 4.4.0 的 zh-CN 格式化输出季,季度解析匹配却仍期待刻。交换值带上年份和数字季度,解析结果是季度起点。
用 date-fns 把第三季度格式化成“第三季度”,再用同一个 zh-CN locale 和 QQQQ 解析,却得到 Invalid Date。若普通数字日期可以正常解析,要检查季度名称的格式化表和匹配表是否一致。
在正式 date-fns 4.4.0 中,zh-CN 的 QQQ 输出“第三季”,QQQQ 输出“第三季度”;对应的解析匹配仍期待“第三刻”和“第三刻钟”。因此,展示文本原样回传,也可能无法通过同一个库的解析入口。这不是把月份从零开始计数就能修好的问题。
失败发生在中文季度文本匹配
季度本身仍是 1 到 4。这里不一致的是 abbreviated、wide 两种文本宽度:localize 生成“季”,match 却没有接受相同写法。更换 referenceDate 不会让匹配器突然认识这个文本。
referenceDate 仍然有实际作用。文本只有季度而没有年份时,年份取自 referenceDate;季度解析会把日期落到该季度第一天的零点。它不能恢复原来的具体日期和时间。
先核对实际生效的 locale 确实为 zh-CN、token 为 QQQ 或 QQQQ,并保留输入文本。QQ 的数字季度、完整的普通日期,或根本没有传 locale,是不同的检查分支。不要因为 zh-HK、zh-TW 在这组输入上表现正常,就全局替换应用的语言配置;那会影响其他日期文案。
展示中文,保存结构化季度
如果表单允许调整数据协议,显示给用户的中文名称可以继续保留,提交时使用独立的年份、季度字段,或双方明确约定的机器文本。下面把带年份的数字季度文本作为交换格式,避开有问题的中文名称匹配:
import { format, parse, isValid } from 'date-fns';
import { zhCN } from 'date-fns/locale';
const date = new Date(2024, 6, 1);
const label = format(date, 'QQQQ', { locale: zhCN });
const stored = format(date, "yyyy-'Q'Q");
const startOfQuarter = parse(
stored,
"yyyy-'Q'Q",
new Date(2000, 0, 1),
);
if (!isValid(startOfQuarter)) {
throw new RangeError('季度数据无效');
}
label 用于展示,stored 才是这里约定的交换值。解析结果表示该年该季度的起点,不是把 date 原有的日期和时间完整恢复。代码使用普通本地 Date;跨时区统计仍需沿应用原来的时区和季度定义处理。
已有接口只接收中文名称时,可以在这个明确的输入入口,对允许的四个季度名称做完整匹配,再转换成约定的季度数;其他输入应被拒绝。不要把所有“季”字替换成“刻”,那会把错误的语言映射变成长期数据协议,也容易误改完整句子或其他字段。
截至 2026 年 10 月 24 日,当前正式 4.4.0 的两张表仍有上述差异。采用后续依赖更新时,应在实际安装包上核对本地化与匹配两侧,并保留兼容性样本,不仅看安装命令是否成功。
校验应覆盖四个季度、QQQ 与 QQQQ、明确年份、缺省年份及非法文本。对于已有持久化数据,先核对存的是显示名称还是机器值;修正输入协议前保留旧值,避免把一次解析失败转换成错误年份或默认当前季度。


