Search code examples
javascriptdateinternationalizationintl

JavaScript Intl/BCP 47: How to use ISO date format `yyyy-mm-dd` for German locales instead of `dd.mm.yyyy`?


Germany uses two different date formats:

  • modern (not used very often, ISO-8601): 2022-01-31
  • classical (used by most Germans): 31.01.2022

JavaScript's Intl API uses the "classical" date format for locale de-DE:

// This prints out: 31.01.2022
console.log(new Intl.DateTimeFormat('de-DE', {
  year: 'numeric',
  month: '2-digit',
  day: '2-digit'
}).format(new Date(2022, 0, 31)));

Please find here the demo: » Demo

Is it somehow possible to use the "modern" (= ISO-8601) date format with Intl by just extending the locale in the example above ('de-DE...')? Using the locale de-DE-u-ca-iso8601 for example is not working.

BTW: Using Date.prototype.toISOString is NOT an option.
[Edit] It's also NOT an option to just use a locale for a different country.

[Edit] I hoped to find a answer somewhere here or here, but have not found a solution there.

[Edit] You can configure the time format by the locale string:
en-GB (shows 24 hour time format)
en-GB-u-hc-h12 (shows 12 hour time format, adding am/pm)
... so I hoped something similar to this would also be possible with 'dd.mm.yyyy' vs 'yyyy-mm-dd'.


Solution

  • Use en-CA as locale.

    Afaik there is no specific locale to format into the 'modern' (iso) date string.

    Either split and reorder the date string, use formatToParts instead of format or split the result of Date.toISOString may be other ideas.

    Note (nov 2023): I have created a small library (es-date-fiddler) that may be useful.

    // 1. locale 'en-CA' (not an option as per comment)
    console.log(new Intl.DateTimeFormat(`en-CA`, {
        year: `numeric`, month: `2-digit`, day: `2-digit`})
      .format(new Date(2022, 0, 31)));
    
    // 2. split and reorder the result
    console.log(new Intl.DateTimeFormat(`de-DE`, {
        year: `numeric`, month: `2-digit`, day: `2-digit`})
      .format(new Date(2022, 0, 31))
      .split(`.`)
      .reverse()
      .join(`-`) );
    
    
    // 3. use formatToParts
    const reformatGerman = new Intl.DateTimeFormat(`de-DE`, {
        year: 'numeric', month: '2-digit', day: '2-digit'})
      .formatToParts(new Date(2022, 0, 31))
      .filter( v => ~[`year`, `month`, `day`].indexOf(v.type) ) 
      .reduce( (acc, val) => ({...acc, [val.type]: val.value}), {} );
    console.log(`${
      reformatGerman.year}-${
      reformatGerman.month}-${
      reformatGerman.day}`);
    
    // 4. truncate the result of `toISOString()`
    console.log(new Date(Date.UTC(2022, 0, 31))
      .toISOString().split(`T`)[0]);