Moment-timezone: Setting locale does not work

Created on 2 Jul 2018  路  4Comments  路  Source: moment/moment-timezone

We are building an application where we utilize both moment and moment-timezone. Setting up locale globally with moment.locale() works great, but for some reason moment-timezone seems to always use 'en' as locale and thus e.g. date formatting is not what we want it to be.

The following Gist made by someone else illustrates the problem: https://gist.github.com/spstratis/fa853f9750a095d4acd0d1196a285be9

How do I specify locale for moment-timezone in order to get localized date and time formats?

Most helpful comment

We also have this issue.

This is quite an ugly workaround, because both moment and moment-timezone will be in the project, but moment-timezone package depends on moment, so I guess anyways they both will exists.

The idea is to apply a localization to moment and then to use it for moment-timezone

~~~js
// import both in a module which sets localization up
// everywhere else it can be just import moment from 'moment-timezone';
import momentTZ from 'moment-timezone';
import moment from 'moment';

// in the config function
function useLocale(name: string) {
// import locale as you do normally
// smth like require('moment/locale/en-gb') will happen down the lines
importLocale(name);
moment.locale(name); // apply it to moment
// eslint-disable-next-line no-underscore-dangle (in case eslint is also used ;) )
momentTZ.defineLocale(name, moment.localeData()._config); // copy locale to moment-timezone
momentTZ.locale(name); // apply it to moment-timezone
},

~~~

There should be a better way, but this is the first pass on fixing this.

All 4 comments

Hello there, I am having a similar issue when trying to use both moment and moment-timezone.
When I do:

import moment from 'moment-timezone';
import esLocale from 'moment/locale/es';

// ... other imports

moment.locale('es', esLocale);
moment.tz.setDefault('America/Costa_Rica');

Later in my code, if I import moment from moment-timezone the locale is set to English but if I import it from moment the locale will be fine. Note, however that when I console.log the value of moment._locale (when imported from moment-timezone) it will print this:

{
   "_calendar":{
      "sameDay":"[Today at] LT",
      "nextDay":"[Tomorrow at] LT",
      "nextWeek":"dddd [at] LT",
      "lastDay":"[Yesterday at] LT",
      "lastWeek":"[Last] dddd [at] LT",
      "sameElse":"L"
   },
   "_longDateFormat":{
      "LTS":"h:mm:ss A",
      "LT":"h:mm A",
      "L":"MM/DD/YYYY",
      "LL":"MMMM D, YYYY",
      "LLL":"MMMM D, YYYY h:mm A",
      "LLLL":"dddd, MMMM D, YYYY h:mm A"
   },
   "_invalidDate":"Invalid date",
   "_ordinal":"%d",
   "_dayOfMonthOrdinalParse":{

   },
   "_relativeTime":{
      "future":"in %s",
      "past":"%s ago",
      "s":"a few seconds",
      "ss":"%d seconds",
      "m":"a minute",
      "mm":"%d minutes",
      "h":"an hour",
      "hh":"%d hours",
      "d":"a day",
      "dd":"%d days",
      "M":"a month",
      "MM":"%d months",
      "y":"a year",
      "yy":"%d years"
   },
   "_months":[
      "January",
      "February",
      "March",
      "April",
      "May",
      "June",
      "July",
      "August",
      "September",
      "October",
      "November",
      "December"
   ],
   "_monthsShort":[
      "Jan",
      "Feb",
      "Mar",
      "Apr",
      "May",
      "Jun",
      "Jul",
      "Aug",
      "Sep",
      "Oct",
      "Nov",
      "Dec"
   ],
   "_week":{
      "dow":0,
      "doy":6
   },
   "_weekdays":[
      "Sunday",
      "Monday",
      "Tuesday",
      "Wednesday",
      "Thursday",
      "Friday",
      "Saturday"
   ],
   "_weekdaysMin":[
      "Su",
      "Mo",
      "Tu",
      "We",
      "Th",
      "Fr",
      "Sa"
   ],
   "_weekdaysShort":[
      "Sun",
      "Mon",
      "Tue",
      "Wed",
      "Thu",
      "Fri",
      "Sat"
   ],
   "_meridiemParse":{

   },
   "_abbr":"es",
   "_config":{
      "calendar":{
         "sameDay":"[Today at] LT",
         "nextDay":"[Tomorrow at] LT",
         "nextWeek":"dddd [at] LT",
         "lastDay":"[Yesterday at] LT",
         "lastWeek":"[Last] dddd [at] LT",
         "sameElse":"L"
      },
      "longDateFormat":{
         "LTS":"h:mm:ss A",
         "LT":"h:mm A",
         "L":"MM/DD/YYYY",
         "LL":"MMMM D, YYYY",
         "LLL":"MMMM D, YYYY h:mm A",
         "LLLL":"dddd, MMMM D, YYYY h:mm A"
      },
      "invalidDate":"Invalid date",
      "ordinal":"%d",
      "dayOfMonthOrdinalParse":{

      },
      "relativeTime":{
         "future":"in %s",
         "past":"%s ago",
         "s":"a few seconds",
         "ss":"%d seconds",
         "m":"a minute",
         "mm":"%d minutes",
         "h":"an hour",
         "hh":"%d hours",
         "d":"a day",
         "dd":"%d days",
         "M":"a month",
         "MM":"%d months",
         "y":"a year",
         "yy":"%d years"
      },
      "months":[
         "January",
         "February",
         "March",
         "April",
         "May",
         "June",
         "July",
         "August",
         "September",
         "October",
         "November",
         "December"
      ],
      "monthsShort":[
         "Jan",
         "Feb",
         "Mar",
         "Apr",
         "May",
         "Jun",
         "Jul",
         "Aug",
         "Sep",
         "Oct",
         "Nov",
         "Dec"
      ],
      "week":{
         "dow":0,
         "doy":6
      },
      "weekdays":[
         "Sunday",
         "Monday",
         "Tuesday",
         "Wednesday",
         "Thursday",
         "Friday",
         "Saturday"
      ],
      "weekdaysMin":[
         "Su",
         "Mo",
         "Tu",
         "We",
         "Th",
         "Fr",
         "Sa"
      ],
      "weekdaysShort":[
         "Sun",
         "Mon",
         "Tue",
         "Wed",
         "Thu",
         "Fri",
         "Sat"
      ],
      "meridiemParse":{

      },
      "abbr":"es"
   },
   "_dayOfMonthOrdinalParseLenient":{

   }
}

Note the abbr = es at the bottom that indicates that moment-timezone is aware of the global change in the locale but for some reason it just does not uses the settings for the specified locale

We also have this issue.

This is quite an ugly workaround, because both moment and moment-timezone will be in the project, but moment-timezone package depends on moment, so I guess anyways they both will exists.

The idea is to apply a localization to moment and then to use it for moment-timezone

~~~js
// import both in a module which sets localization up
// everywhere else it can be just import moment from 'moment-timezone';
import momentTZ from 'moment-timezone';
import moment from 'moment';

// in the config function
function useLocale(name: string) {
// import locale as you do normally
// smth like require('moment/locale/en-gb') will happen down the lines
importLocale(name);
moment.locale(name); // apply it to moment
// eslint-disable-next-line no-underscore-dangle (in case eslint is also used ;) )
momentTZ.defineLocale(name, moment.localeData()._config); // copy locale to moment-timezone
momentTZ.locale(name); // apply it to moment-timezone
},

~~~

There should be a better way, but this is the first pass on fixing this.

I came up with a fix for this issue.
https://github.com/kylejacobbutler/moment-timezone-locale

I experienced this issue myself using Typescript and enhanced the solution written by @zubko to copy over all locales into the separate moment instance that lives within moment-timezone for some module loading versions.

import baseMoment from "moment";
import mtz from "moment-timezone";

// Import all supported locales here
import "moment/locale/sv";
import "moment/locale/nb";
import "moment/locale/fi";
// etc

const copyLocaleData = (source: typeof baseMoment, dest: typeof mtz) => {
  // Need to copy over all locale config to the copy of moment that lives in moment-timezone
  // https://github.com/moment/moment-timezone/issues/647
  const installedLocales = dest.locales();
  for (const locale of source.locales()) {
    if (!installedLocales.includes(locale)) {
      const localeData = source.localeData(locale);
      const localeSpec: mtz.LocaleSpecification = (localeData as any)._config;
      dest.defineLocale(locale, localeSpec);
    }
  }
};

copyLocaleData(baseMoment, mtz);

// Re-export so that users don鈥檛 need to know the actual import library we use
export { mtz as momentCreator };

Then I just import momentCreator and use it with both locale data and timezone support. No other file should import moment themselves.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

guidsen picture guidsen  路  4Comments

SathyaChenniappan picture SathyaChenniappan  路  4Comments

garryyao picture garryyao  路  4Comments

palindrom615 picture palindrom615  路  4Comments

rama41222 picture rama41222  路  3Comments