TL;DR: new Intl.Locale("en-GB").getWeekInfo() tells you the week starts on Monday and the weekend is Saturday and Sunday. With Firefox 153, the whole Intl.Locale info family is Baseline Newly available, so you can delete that hand-rolled "first day of week" table.
The line nobody wants to touch
Every date picker has it somewhere.
const FIRST_DAY = 0; // Sunday. Probably. Ask product.
Then a user in London opens the calendar and the week starts on the wrong day. Someone adds if (locale === "en-GB") ..., then a lookup table, then a ticket about Israel, where the weekend is Friday and Saturday. The table grows. Nobody is sure where the data came from.
The browser already ships that data. It has been sitting in the Unicode CLDR tables that power Intl.DateTimeFormat all along. Now there is a standard way to ask for it.
What it is
Intl.Locale has seven get methods that answer "how does this locale do things?":
| Method | What you get back |
|---|---|
getWeekInfo() |
{ firstDay, weekend } |
getHourCycles() |
Hour cycles such as ["h12"] or ["h23"]
|
getTextInfo() |
{ direction: "ltr" } or { direction: "rtl" }
|
getTimeZones() |
IANA time zones for the locale's region |
getCalendars() |
Calendars in use, most preferred first |
getCollations() |
Sort orders in use |
getNumberingSystems() |
Digit systems in use |
They came from the TC39 Intl Locale Info proposal, which is now Stage 4 and part of ECMA-402.
A minimal example
for (const tag of ["en-US", "en-GB", "he-IL", "ar-AF", "fa-IR"]) {
console.log(tag, new Intl.Locale(tag).getWeekInfo());
}
Run in Node 24.11:
en-US { firstDay: 7, weekend: [ 6, 7 ] }
en-GB { firstDay: 1, weekend: [ 6, 7 ] }
he-IL { firstDay: 7, weekend: [ 5, 6 ] }
ar-AF { firstDay: 6, weekend: [ 4, 5 ] }
fa-IR { firstDay: 6, weekend: [ 5 ] }
Days are numbered 1 for Monday through 7 for Sunday. Notice fa-IR: a one-day weekend. Your two-element array assumption just left the chat.
The siblings work the same way:
new Intl.Locale("en-US").getHourCycles(); // ["h12"]
new Intl.Locale("en-GB").getHourCycles(); // ["h23"]
new Intl.Locale("ar").getTextInfo(); // { direction: "rtl" }
new Intl.Locale("th-TH").getCalendars(); // ["buddhist", "gregory"]
A realistic example: a calendar header
Here is a week header that starts on the right day and marks the weekend, with no lookup table. The day labels are in English so the output stays readable here; drop the second argument to get them in the user's language.
// firstDay and weekend use 1 = Monday ... 7 = Sunday.
// Date#getDay() uses 0 = Sunday ... 6 = Saturday.
const isoDay = (date) => date.getDay() || 7;
function weekHeader(tag, labels = tag) {
const locale = new Intl.Locale(tag);
const { firstDay, weekend } = locale.getWeekInfo();
const fmt = new Intl.DateTimeFormat(labels, { weekday: "short", timeZone: "UTC" });
// 2024-01-01 was a Monday, so day n (1-7) is January n.
return Array.from({ length: 7 }, (_, i) => {
const day = ((firstDay - 1 + i) % 7) + 1;
const label = fmt.format(new Date(Date.UTC(2024, 0, day)));
return weekend.includes(day) ? `[${label}]` : label;
}).join(" ");
}
function isWeekend(date, tag) {
return new Intl.Locale(tag).getWeekInfo().weekend.includes(isoDay(date));
}
for (const tag of ["en-US", "en-GB", "he-IL", "fa-IR"]) {
console.log(tag.padEnd(6), weekHeader(tag, "en"));
}
const friday = new Date(2026, 9, 23); // October 23, 2026
console.log(friday.toDateString(), "en-US:", isWeekend(friday, "en-US"), "he-IL:", isWeekend(friday, "he-IL"));
Output from Node 24.11:
en-US [Sun] Mon Tue Wed Thu Fri [Sat]
en-GB Mon Tue Wed Thu Fri [Sat] [Sun]
he-IL Sun Mon Tue Wed Thu [Fri] [Sat]
fa-IR Sat Sun Mon Tue Wed Thu [Fri]
Fri Oct 23 2026 en-US: false he-IL: true
Same Friday, two answers. Both correct.
The same idea fixes time pickers: getHourCycles()[0] tells you whether to show an AM/PM toggle (h12) or a 0 to 23 clock (h23), and getTextInfo().direction tells you which way to lay out the arrows.
Can I use it?
Yes. The feature is Baseline Newly available since July 21, 2026, when Firefox 153 shipped all seven methods. Chrome and Edge have had the method form since 130, and Safari since 17. Node has it from 24.0.
Older Chrome (99 to 129) and Safari 15.4 to 16 exposed the same data as getters named weekInfo, hourCycles and so on. If you need those users, feature-detect:
const weekInfo = (locale) => locale.getWeekInfo?.() ?? locale.weekInfo;
Gotchas
Days are ISO, not
getDay().firstDayuses 1 for Monday and 7 for Sunday, whileDate#getDay()uses 0 for Sunday. Convert withdate.getDay() || 7, or enjoy a calendar that is off by one only on Sundays.minimalDaysis gone. MDN'sgetWeekInfo()page still shows aminimalDaysproperty, but it was dropped from the proposal. MDN's own compat data says Chrome removed it in 136, and Node 24.11 does not return it. Do not build week numbering on it.The weekend is not always two days, or a Saturday.
fa-IRreturns[5], andar-AFreturns[4, 5]. Useweekend.includes(day), neverday >= 6.getTimeZones()needs a region.new Intl.Locale("en-AU").getTimeZones()returned 12 zones in Node, butnew Intl.Locale("en").getTimeZones()returnedundefined. Handle the missing case.Unicode extensions win. In Node,
new Intl.Locale("en-US-u-fw-mon").getWeekInfo().firstDayis1, anden-US-u-hc-h23gives["h23"]. That is handy for a "week starts on" user setting, but it means the result is not always the region default.Each call returns a new object.
locale.getWeekInfo() === locale.getWeekInfo()isfalse. That is exactly why the spec moved from getters to methods, so cache the result if you call it in a render loop.
Wrap-up
The week-start table in your codebase was always a guess about data the browser already had. Find your FIRST_DAY constant, swap it for getWeekInfo(), and let CLDR take the tickets.
Sources
- MDN: Intl.Locale.prototype.getWeekInfo()
- MDN: Intl.Locale.prototype.getHourCycles()
- MDN: Firefox 153 release notes for developers
- web.dev: July 2026 Baseline monthly digest
- web-features: intl-locale-info status
- MDN browser-compat-data: Intl.Locale
- TC39: Intl Locale Info proposal
This article was written with the help of AI and checked against the sources above.
Top comments (0)