写过前端的都以为全球化只是翻译——今天两个 JS API 把日历首日这件事彻底原生化了
做国际化产品,日历组件几乎人手一个。但你有没有被这些细节卡过:周日还是周一作为一周起始?沙特的周末是周五和周六,不是周六和周日;文莱的周末是周五和周日,中间夹着周六上班。
这些数据以前要么硬编码,要么引入 moment.js / date-fns / date-fns-tz 整一套库来兜着。现在,两个原生 JS API 全部搞定。
问题:全球化日历数据的获取一直是痛点
做多地区日历时,你需要知道:
- 一周从哪天开始(firstDay)
- 哪些天是周末(weekend,不一定是连续的)
- 一个月第一周最少需要几天(minimalDays,ISO 8601 用)
历史上:
moment.js/date-fns/js-joda需要引入库date-fns-tz单独处理时区- 硬编码 Map 容易出错,不同地区规则差异超出预期(英国 en-GB 是周一,阿拉伯地区是周六,布隆迪 en-BN 是周五+周日不是周六)
解决方案:Intl.Locale weekInfo
两个 API 同源,选 getWeekInfo() 更规范:
// 一行代码获取任意地区的周信息
const locale = new Intl.Locale('en-GB');
const { firstDay, weekend, minimalDays } = locale.getWeekInfo();
console.log(firstDay); // 1 (周一)
console.log(weekend); // [6, 7] (周六、周日)
console.log(minimalDays); // 4 (ISO 8601 要求第一周至少4天)
实战示例——根据用户 locale 渲染日历组件:
function getCalendarConfig(localeTag) {
const { firstDay, weekend, minimalDays } = new Intl.Locale(localeTag).getWeekInfo();
return {
weekStart: firstDay, // 1=周一 ... 7=周日
weekendDays: new Set(weekend), // [5, 6] 沙特这种不连续也能用
isoWeekMinDays: minimalDays,
};
}
// 中国用户
console.log(getCalendarConfig('zh-CN'));
// { weekStart: 1, weekendDays: Set { 6, 7 }, isoWeekMinDays: 1 }
// 英国用户
console.log(getCalendarConfig('en-GB'));
// { weekStart: 1, weekendDays: Set { 6, 7 }, isoWeekMinDays: 4 }
// 沙特阿拉伯
console.log(getCalendarConfig('ar-SA'));
// { weekStart: 6, weekendDays: Set { 5, 6 }, isoWeekMinDays: 1 }
// 文莱——周末不连续!周五和周日,中间夹着周六
console.log(getCalendarConfig('ms-BN'));
// { weekStart: 7, weekendDays: Set { 5, 7 }, isoWeekMinDays: 1 }
配合 Intl.DateTimeFormat 做完整国际化日期
function formatWeekdayHeaders(localeTag) {
const { firstDay } = new Intl.Locale(localeTag).getWeekInfo();
const formatter = new Intl.DateTimeFormat(localeTag, { weekday: 'short' });
const days = [];
for (let i = 0; i < 7; i++) {
const dayIndex = (firstDay - 1 + i) % 7;
const date = new Date(2026, 0, 5 + dayIndex); // 2026-01-05 是周一
days.push(formatter.format(date));
}
return days;
}
console.log(formatWeekdayHeaders('zh-CN'));
// ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
console.log(formatWeekdayHeaders('en-US'));
// ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] // 美国从周日开始
兼容性与 API 选择
- Chrome 130+ / Firefox 130+ / Safari 17+ 推荐用
getWeekInfo()方法 - 老版本用
locale.weekInfo访问器属性(行为相同但返回同一引用) - 两者返回结构完全一致:
{ firstDay, weekend, minimalDays }
结论
Intl.Locale 的 weekInfo 接口让全球化日历数据彻底原生化,不再需要任何第三方库,也不需要维护一份不断膨胀的地区规则 Map。两个属性搞定所有场景,包括那些你以为只有 JS 库才知道的不规则周末。
下一步
- 打开浏览器控制台跑一下
new Intl.Locale('ar-SA').getWeekInfo(),看看沙特周末是哪两天 - 把现有日历组件的
weekStart逻辑从硬编码 Map 替换成这个 API - 顺手看一下
Intl.Locale还有哪些 getter 可以用——hourCycle、calendar、numberingSystem,一个对象全拿回来
评论区
0 条评论
登录后可评论。