← Read

Tech · · 7 min read

The first day of the week, without a lookup table

Intl.Locale's info methods are Baseline as of July 2026. What getWeekInfo(), getTextInfo() and getCalendars() return, with real values across Asia-Pacific locales.

Every date picker has to answer one question before it can draw a single row: which day does the week start on? JavaScript now answers it without a hand-maintained map of countries:

new Intl.Locale("en-AU").getWeekInfo();  // { firstDay: 1, weekend: [6, 7] }
new Intl.Locale("ja-JP").getWeekInfo();  // { firstDay: 7, weekend: [6, 7] }
new Intl.Locale("en-IN").getWeekInfo();  // { firstDay: 7, weekend: [7] }

Days are numbered as in ISO 8601: 1 is Monday and 7 is Sunday. Australia starts the week on Monday, Japan and India on Sunday, and India's weekend is a single day.

These methods are part of the Intl Locale Info API, which reached Stage 4 at TC39 in November 2025, was folded into the 13th edition of ECMA-402 in June 2026, and became Baseline newly available on 21 July 2026 when Firefox 153 shipped it.

github.com ↗TC39 proposal-intl-locale-infoThe proposal repository, with the design history and the dropped parts of the original scope. Source: TC39

The seven methods

Each one is a method on an Intl.Locale instance, and each returns data the browser already carries for formatting.

MethodReturns
getWeekInfo(){ firstDay, weekend } — the first weekday, and which days are the weekend
getTextInfo(){ direction } — "ltr" or "rtl"
getCalendars()Calendar identifiers used in the locale, preferred one first
getTimeZones()IANA time zone identifiers in common use in the region, sorted
getNumberingSystems()Numbering system identifiers, such as latn or arab
getHourCycles()Hour cycle identifiers, such as h12 or h23
getCollations()Sort order identifiers available for the locale

Two shapes are worth memorising exactly, because the conformance suite pins them down: getWeekInfo() returns an object whose only own properties are firstDay and weekend, and getTextInfo() returns an object whose only own property is direction.

If you remember a third minimalDays property, you're remembering an earlier draft. Implementations that shipped the first version of this API exposed it, but it is not part of the standard return value — test262 asserts the own keys are exactly firstDay and weekend. Don't build week-numbering logic on it.

What the values look like across Asia-Pacific

The data comes from CLDR, the same source browsers use for every other Intl decision. Values below were read from ICU 78.2, through the accessor form described later in this article, and the mix is more varied than a single "Sunday or Monday" switch would suggest.

LocaleFirst dayWeekendPreferred calendarsHour cycle
en-AUMondaySat, Sungregoryh12
en-NZMondaySat, Sungregoryh12
zh-CNMondaySat, Sungregory, chineseh23
ja-JPSundaySat, Sungregory, japaneseh23
ko-KRSundaySat, Sungregory, dangih12
zh-TWSundaySat, Sungregory, roc, chineseh12
en-SGSundaySat, Sungregory, chineseh12
id-IDSundaySat, Sungregory, islamic and two variantsh23
th-THSundaySat, Sunbuddhist, gregoryh23
en-INSundaySun onlygregory, indianh12

Three of these will break an interface that assumes otherwise:

  • India's weekend is one day. weekend: [7] means a "weekend" column pair, a Saturday-and-Sunday greyed-out rule, or an availability calculation that blocks two days is wrong for en-IN and hi-IN.
  • Mainland China starts the week on Monday; Taiwan starts on Sunday. Same language, different firstDay. Region matters, not script.
  • Thailand's preferred calendar isn't Gregorian. getCalendars() returns buddhist first for th-TH, which is why a Thai user may expect the year 2569 where your UI shows 2026. The API tells you the preference; honouring it is a separate decision.

A month grid that gets the order right

getWeekInfo() gives you the rotation; Intl.DateTimeFormat gives you the labels. One function covers both, plus which columns to mark as weekend:

function weekdayHeaders(locale) {
  const { firstDay, weekend } = new Intl.Locale(locale).getWeekInfo();
  const fmt = new Intl.DateTimeFormat(locale, { weekday: "short", timeZone: "UTC" });

  return Array.from({ length: 7 }, (_, i) => {
    const iso = ((firstDay - 1 + i) % 7) + 1;   // 1 = Monday … 7 = Sunday
    const date = new Date(Date.UTC(2026, 5, iso)); // 1 June 2026 was a Monday
    return { iso, label: fmt.format(date), isWeekend: weekend.includes(iso) };
  });
}

Picking a month whose 1st falls on a Monday means ISO day n is simply the nth of that month, so no date arithmetic is needed. Run against CLDR data, the labels and weekend flags come out as:

en-AU   Mon Tue Wed Thu Fri Sat* Sun*
en-IN   Sun* Mon Tue Wed Thu Fri Sat
ja-JP   日* 月 火 水 木 金 土*
zh-CN   周一 周二 周三 周四 周五 周六* 周日*

Never hardcode the weekday labels themselves. Intl.DateTimeFormat with weekday: "short" or "narrow" produces the right ones, in the right script, for free.

What it won't tell you

The API reports locale conventions, not business rules. It has nothing to say about:

  • Public holidays. No browser API exposes them. That stays your data problem, and it is a per-country, per-year problem.
  • Working days. A weekend is a locale convention; a hospital roster or a trading calendar is not.
  • Week numbering. With minimalDays gone from the standard, the rule for which week is week 1 is not available here.
  • The user's preference. This is locale data, not user settings. Someone in Tokyo who wants Monday-first still needs a preference of their own.

The API shipped twice, so feature-detect

The first version of this feature exposed getters — locale.weekInfo, locale.textInfo, locale.calendars — and shipped in Chrome 99 (March 2022) and Safari 15.4. The committee then changed the design to methods, which is what the standard specifies and what Firefox implemented directly. Both forms exist in the wild, and Node 22 still ships the accessor form.

Detect the method, then the accessor, then fall back:

function weekInfo(locale, fallback = { firstDay: 1, weekend: [6, 7] }) {
  const l = new Intl.Locale(locale);
  if (typeof l.getWeekInfo === "function") return l.getWeekInfo();
  if (l.weekInfo) return l.weekInfo;          // older accessor form
  return fallback;
}

Choose the fallback for your actual audience rather than copying en-US. Also note that getTimeZones() needs a region to answer: new Intl.Locale("en") has no country attached, and there is no list of time zones "in common use" for a bare language, so guard that call.

Browser support

BrowserMethods sinceReleased
Safari1718 September 2023
Chrome13015 October 2024
Edge13017 October 2024
Firefox15321 July 2026

Firefox was last, which set the Baseline keystone date. Firefox 153 is also the current ESR at the time of writing, which matters if you support long-term-support Firefox in managed environments. Support data from @mdn/browser-compat-data 8.1.1.

One more caveat that applies at every support level: these values are CLDR data shipped inside the browser's ICU build. They are stable in practice, not immutable — CLDR revises region data between releases. Read them at runtime, and don't assert exact values in tests you need to stay green.

FAQ

Is firstDay 1 Monday or Sunday?

Monday. The numbering follows ISO 8601, so 1 is Monday and 7 is Sunday. Locales that start the week on Sunday, such as ja-JP and en-US, report firstDay: 7.

How do I get the user's own locale rather than a fixed one?

new Intl.Locale(navigator.language) for the browser's preferred locale, or read new Intl.DateTimeFormat().resolvedOptions().locale for the one Intl actually resolved to.

Does getCalendars() mean I should switch my UI to that calendar?

No. It tells you which calendars the locale uses and which is preferred. Whether to render the Buddhist or Japanese calendar is a product decision — but it explains why some users expect a different year.

Can I use it today without a fallback?

Not safely. It is Baseline newly available rather than widely available, so visitors on older Firefox or older Safari will not have the methods. The detection above is a handful of lines.

Sources

More to read