toisostring() 输出 utc 时间,直接截前十位得到的是 utc 日期。如果业务日期以北京时间为准,用 intl.datetimeformat 显式指定 asia/shanghai 后再提取年月日。

复现北京时间凌晨跨日
把带有 +08:00 的时间字符串交给 Date。
const instant = new Date('2026-10-23T00:30:00+08:00');
console.log(instant.toISOString());
console.log(instant.toISOString().slice(0, 10));
结果分别为 2026-10-22T16:30:00.000Z 和 2026-10-22。时间点相同,所属日期随时区改变。
立即学习“Java免费学习笔记(深入)”;
按业务时区生成稳定的日期键
使用 formatToParts 获取年月日,避免依赖浏览器默认分隔符。
function businessDate(instant, timeZone = 'Asia/Shanghai') {
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: 'gregory', numberingSystem: 'latn', timeZone,
year: 'numeric', month: '2-digit', day: '2-digit',
});
const parts = Object.fromEntries(
formatter.formatToParts(instant).map(({ type, value }) => [type, value]),
);
return [parts.year.padStart(4, '0'), parts.month, parts.day].join('-');
}
console.log(businessDate(new Date('2026-10-23T00:30:00+08:00')));结果是 2026-10-23。同一份数据用统一的业务时区生成分组键。
验证业务日切换的边界
把下面代码放在 businessDate 函数后运行。
const before = new Date('2026-10-22T15:59:59Z');
const after = new Date('2026-10-22T16:00:00Z');
console.assert(businessDate(before) === '2026-10-22');
console.assert(businessDate(after) === '2026-10-23');
console.assert(businessDate(after, 'UTC') === '2026-10-22');三条断言都应通过。只有年月日的字段可以直接保存日期文本,有明确时间点的字段应携带时区或偏移量。


















