How to get a list of month names in javascript using Intl
Asked Answered
A

5

17

How can I get a list of all long month names using the ECMAScript Internationalization API?

For example, if the user's locale is en-US, I'd like to get the following:

["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
Antlion answered 10/11, 2017 at 23:12 Comment(0)
H
14

My solution in 2021 with es6 Syntax

/**
 * Return list of months
 * 🌍 localeName   : name of local, f.e. en-GB, default es-MX
 *  βœ… monthFormat : short, numeric, long (Default)
 */
function monthsForLocale(localeName = 'es-MX', monthFormat = 'long') {
  const format = new Intl
     .DateTimeFormat(localeName, {month: monthFormat}).format;
  return [...Array(12).keys()]
    .map((m) => format(new Date(Date.UTC(2021, (m+1)%12))));
}


// πŸ”Ž Testing:

// ['enero', ..., 'noviembre','diciembre' ]
console.log(monthsForLocale());

// ['1', '2',  '3', '4',  '5', '6',  '7', '8',  '9', '10', '11', '12']
console.log(monthsForLocale('en-GB', 'numeric'));

// ['Jan', 'Feb','Mar', 'Apr', 'May','Jun', 'Jul', 'Aug','Sep', 'Oct', 'Nov','Dec' ]    
console.log(monthsForLocale('en-GB', 'short'));

// ['1月',  '2月', '3月',  '4月',  '5月','6月',  '7月',  '8月','9月',  '10月', '11月', '12月']
console.log(monthsForLocale('ja-JP', 'short'));
Hubblebubble answered 14/3, 2021 at 16:32 Comment(0)
A
6

This should do it:

function getMonthsForLocale(locale) {
    var format = new Intl.DateTimeFormat(locale, { month: 'long' })
    var months = []
    for (var month = 0; month < 12; month++) {
        var testDate = new Date(Date.UTC(2000, month, 1, 0, 0, 0));
        months.push(format.format(testDate))
    }
    return months;
}
Abstractionism answered 10/11, 2017 at 23:23 Comment(4)
Creating a date in UTC then using it to create another date in you local timezone might shift the months order in the final array. – Precinct
This does not work for Safari. The code creates the following result: (Array (12) 0 "January" 1 "February" 2 "March" 3 "March" 4 "April" 5 "May" 6 "June" 7 "July" 8 "August" 9 "September" 10 "October" 11 "December"). Note the duplicate "March" values and the absence of "November" – Assibilate
follow up from the above... safari has a bug in DateTimeFormat #56243141. So this answer 'should' work, but in practice it does not as of now – Assibilate
The problem with this and all similar solutions is that the month format is not required to be supported and will map to an implementation-defined format (as seen on Safari, as year+month or month+day are supported formats that could be chosen instead). Probably using formatToParts and extracting the month value from the month+year format is a way around this. – Sonorous
A
4

To make this work on Safari as well, we need to offset by an additional day (Dates in Safari appear off by one using Intl.DateTimeFormat with en-US locale). This works in our usecase because we are just getting the month names, so it does not matter if we generate the string from the 1st or the 2nd of the month.

const SAFARI_OFFSET_FIX = 1;
const getMonthsForLocale = (locale = navigator.language) => {
  const format = new Intl.DateTimeFormat(locale, { month: 'long' });
  const months = [];
  for (let month = 0; month < 12; month++) {
    const testDate = new Date(0, month, 1 + SAFARI_OFFSET_FIX, 0, 0, 0);
    months.push(format.format(testDate));
  }
  return months;
};
Assibilate answered 9/10, 2020 at 20:11 Comment(0)
B
3

Combining the best of the answers above, plus my own small improvements.

Usually people want a list of months to start with January, not December. Switching from new Date(Date.UTC(2021, m))) to simply new Date(2021, m)) resolves this, as it creates a date in the user's own locale.

/**
 * Get a list of the 12 months of the year as strings, according to specified locale and format
 * @typedef {Object} Options
 * @property {string} [locale=navigator.language] : name of locale, e.g. en-GB, defaults to 
 *   the user's own locale
 * @property {string} [monthFormat="long"] : "short", "numeric", or "long" (default)
 *
 * @param {Options} [options] : input options
 * @return {string[]} : an array of 12 strings, the months of the year in the requested format
 */
function getAllMonths({ locale = navigator.language, format = "long"} = {}) {
  const applyFormat = new Intl.DateTimeFormat(locale, { month: format }).format;
  return [...Array(12).keys()].map((m) => applyFormat(new Date(2021, m)));
}

// Testing in en-US locale
console.log(getAllMonths());
// ["January", "February", ... "December"]
console.log(getAllMonths({ format: "numeric" }));
// ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]
console.log(getAllMonths({ format: "short" }));
// ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"]
console.log(getAllMonths({ locale: "es-mx" }));
// ["enero", "febrero", ... "diciembre"]
console.log(getAllMonths({ locale: "ja-JP", format: "short" }));
// ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
Bellicose answered 26/1, 2022 at 20:24 Comment(0)
H
0

Similar to the others, but setting the timezone. No more adding one or worrying about locale of the browser.

Add a timezone attribute to the format DateTimeFormat options to lock the timezone property to UTC.

const getMonths = (language) => {
  const monthIndexes = [...Array(12).keys()]
  const options = {
    month: 'long',
    timeZone: 'UTC', // Add this
  }
  const applyFormat = new Intl.DateTimeFormat(language, options).format;
  return monthIndexes.map((m) => applyFormat(new Date(Date.UTC(0, m))));
}
getMonths('en')
// (12)Β ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']

getMonths('zh')
// (12)Β ['δΈ€ζœˆ', '二月', 'δΈ‰ζœˆ', 'ε››ζœˆ', 'δΊ”ζœˆ', 'ε…­ζœˆ', 'δΈƒζœˆ', 'ε…«ζœˆ', '九月', '十月', 'εδΈ€ζœˆ', '十二月']
Hashum answered 2/7, 2024 at 23:59 Comment(0)

© 2022 - 2025 β€” McMap. All rights reserved.