Get Localized Month and Weekday Names in JavaScript

To list localized month or weekday names, format a reference date with Intl.DateTimeFormat(locale, { month }) (or weekday) across the range β€” no hard-coded English arrays. Part of Locale-Sensitive Date Comparison and Sorting.

Why this scenario is tricky

Getting localized month and weekday names is a task where the wrong instinct β€” keeping an array of names in your code β€” is exactly what causes bugs and blocks internationalization. A hard-coded ['January', 'February', …] is English-only, and worse, it tempts you to index into it with a zero-based month while some other code uses one-based, reintroducing off-by-one errors. The correct source of names is the platform's internationalization data, which knows every locale's month and weekday names, their abbreviations, and their grammatical forms, and stays current as that data is updated.

Intl.DateTimeFormat is that source: format a date with { month: 'long' } (or 'short', 'narrow') and it returns the month's name in the requested locale and width, and the same with { weekday: 'long' } for weekday names. The subtlety is that to enumerate all twelve months or seven weekdays you format a representative date for each, and you must pin the time zone so the representative date does not slip to an adjacent day in some zone β€” which is the one trap in an otherwise clean approach.

Hard-coded ['January', ...] arrays are English-only and drift from the locale's real names (some locales capitalize differently or use distinct standalone forms). Generating them from Intl gives correct names for any locale and any width.

Generate names, don't hard-code themEnglish arrays are wrong elsewhereGenerate names, don't hard-code them['Jan','Feb',...] literalEnglish onlyIntl month formatterany locale, any widthFormat a reference date per month/weekday to get localized names.

Minimal working solution

To list the month names, format day 1 of each month with a { month: 'long', timeZone: 'UTC' } formatter: Array.from({ length: 12 }, (_, m) => fmt.format(new Date(Date.UTC(2024, m, 1)))) yields the localized names in order. Pinning timeZone: 'UTC' and constructing the representative dates with Date.UTC is essential β€” without it, midnight on the 1st could render as the last day of the previous month in a negative-offset zone, shifting a name. The same pattern with { weekday: 'short' } over seven consecutive days gives weekday names in whatever width you request.

Choosing the width ('long', 'short', 'narrow') matters because they serve different UI slots: full names for a dropdown, short for a compact calendar header, narrow for a dense grid. Note that 'narrow' names are not guaranteed unique β€” several weekdays may share a single letter in some locales β€” so use narrow only where space forces it and uniqueness is not required. Requesting the width you actually need from Intl is cleaner than truncating a long name yourself, which would break for locales whose abbreviations are not simple prefixes.

const fmt = new Intl.DateTimeFormat('fr-FR', { month: 'long', timeZone: 'UTC' });
const months = Array.from({ length: 12 }, (_, m) =>
  fmt.format(new Date(Date.UTC(2024, m, 1)))); // ['janvier', 'fΓ©vrier', ...]

Month namesFormat each month of a reference yearMonth namesm = 0..11Intl monthlonglocalizednames

Full production version

A production helper takes the locale and the desired width and returns the ordered arrays of month and weekday names, caching the results because the names for a given locale and width never change within a session. Building them once per locale avoids repeatedly formatting the same representative dates, which matters if a calendar re-renders often. Because the names come from Intl, adding a language requires no code change β€” the same helper produces Japanese, Arabic, or Finnish names on request, and it respects locale conventions your own table would miss.

Two production details are worth handling. First, weekday order is itself locale-sensitive for display β€” some locales start the week on Sunday, others Monday or Saturday β€” so if you are building a calendar header, order the weekday names according to the locale's first day rather than always starting at Monday. Second, for right-to-left locales the names come out correctly but your layout must accommodate RTL; the name data is fine, the presentation is your responsibility. Keeping name generation in one Intl-backed helper means every locale-specific subtlety of the names is handled centrally, leaving only layout to the UI.

// Weekday names, starting Monday, in the 'short' width.
const fmt = new Intl.DateTimeFormat('de-DE', { weekday: 'short', timeZone: 'UTC' });
// 2024-01-01 is a Monday.
const days = Array.from({ length: 7 }, (_, i) => fmt.format(new Date(Date.UTC(2024, 0, 1 + i))));

Weekday namesWalk seven days from a known MondayWeekday namesi = 0..6Intl weekdayfrom Mondaynames

Verification snippet

Month & Weekday Names assertionsKey cases assert correctlyAssertions that prove the edge casefr-FR month 0'janvier'de-DE weekday short'Mo','Di',...narrow widthsingle lettersno hard-coded arraytrue

Common pitfalls

Month & Weekday Names pitfallsCommon mistakes and their fixesWrongRight['January',...] literalEnglish onlyIntl month/weekday formatlocalized namesassume week starts Sundaywrong for many localespick the width optionnarrow/short/long

Frequently Asked Questions

How do I get month names in the user's language?

Format a reference date for each month with Intl.DateTimeFormat(locale, { month: 'long', timeZone: 'UTC' }). Looping January through December yields the localized names, and switching 'long' to 'short' or 'narrow' changes the width.

How do I get weekday names starting on Monday?

Format seven consecutive days beginning from a date you know is a Monday (2024-01-01) with { weekday: 'short' }. Because you control the starting day, you can order the array Monday-first or Sunday-first as your UI needs.

How do I get localized month and weekday names in JavaScript?

Use Intl.DateTimeFormat with { month: 'long' } or { weekday: 'long' } (or 'short'/'narrow') and format a representative date for each. For months: Array.from({ length: 12 }, (_, m) => fmt.format(new Date(Date.UTC(2024, m, 1)))). Pin timeZone: 'UTC' and build the dates with Date.UTC so none slips to an adjacent day in a negative-offset zone. This returns the names in the requested locale and width from the platform's data.

Why not keep an array of month names in my code?

Because a hard-coded array is English-only and blocks internationalization, and indexing into it invites zero-based-versus-one-based month bugs. Intl.DateTimeFormat sources names from the platform's locale data, which covers every language's month and weekday names, their abbreviations, and grammatical forms, and stays current as the data updates β€” so the same code produces correct names in any locale with no table to maintain.

Why pin the time zone when generating month or weekday names?

Because you enumerate names by formatting a representative date for each month or weekday, and without a pinned zone, midnight on the 1st can render as the previous day in a negative-offset zone, shifting a name by one. Setting timeZone: 'UTC' and constructing the dates with Date.UTC keeps each representative date on the intended calendar day so the enumerated names are correct and stable.

Are narrow month or weekday names always unique?

No. Narrow names β€” a single letter for weekdays in many locales β€” can collide, so several weekdays may share the same character (for example T for Tuesday and Thursday in English). Use narrow only where space forces it and uniqueness is not required, such as a dense calendar grid where position disambiguates. For anything that must be unambiguous on its own, request the short or long width instead.

How do I order weekday names by the locale's first day of the week?

Generate the seven weekday names, then rotate the array so it starts on the locale's first day rather than always Monday. Some locales begin the week on Sunday, others Monday or Saturday, and a calendar header should follow that convention. Determine the first day from locale data or configuration and reorder the names accordingly, keeping the name generation itself in one Intl-backed helper.