Jekyll
Jekyll

Reputation: 563

Locale and specific date format with Moment.js

I am using Moment.js in my project and formatting dates as follows:

var locale = window.navigator.userLanguage || window.navigator.language;
moment.locale(locale);
someDate.format("L");

It works well but sometimes I need show a date without a year. I can't use something like someDate.format("MM/DD") because in some languages it should be someDate.format("DD/MM"). I need something like L,LL,LLL but without the year.

What can I do?

LTS : 'h:mm:ss A',
LT : 'h:mm A',
L : 'MM/DD/YYYY',
LL : 'MMMM D, YYYY',
LLL : 'MMMM D, YYYY LT',
LLLL : 'dddd, MMMM D, YYYY LT'

Upvotes: 46

Views: 60049

Answers (4)

cjbarth
cjbarth

Reputation: 4469

One option might be to use the CLDR data and get a hold of the Gregorian data and look up main.{locale}.dates.calendars.gregorian.dateTimeFormats.availableFormats. The one you probably want is Md.

I might suggest that you use the Globalize library to make this all easier. You'll note that if you set the date format you want as a skeleton, the library can do all the localization for you.

For example:

.dateFormatter({ skeleton: "GyMMMd" })( new Date() )
// > "Nov 30, 2010 AD"

Upvotes: 0

Emilie
Emilie

Reputation: 681

The library doesn't make it easy to add new formats because they are validated against a regex that we cannot override (var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;).

However, we can override the format function in order to transform our new format into tokens that Moment recognizes.

For example, let's add a new custom format called "LMD". First we need to define it for every locale we want to use:

moment.updateLocale('en', {
   longDateFormat: {
       LMD: 'MMMM D'
   }
});

moment.updateLocale('fr', {
    longDateFormat: {
        LMD: 'D MMMM'
    }
});

Then we override the original format function and transform the inputString ("LMD") into the real tokens we previously defined. After that we just call the original function and let Moment do its job as usual:

var originalMomentFormat = moment.prototype.format;
moment.prototype.format = function (inputString) {
    if (inputString === 'LMD') { // check for your custom types here. maybe use constants or whatever
        inputString = moment.localeData().longDateFormat(inputString);
    }
    return originalMomentFormat.apply(this, [inputString]);
};

Example usage:

moment(someDate).format('LMD');

Upvotes: 1

MegaCasper
MegaCasper

Reputation: 1958

As far as I understand, you can change the date format(without year) for specific languages using MomentJS properties https://momentjs.com/docs/#/customization/long-date-formats/

Example:

moment.updateLocale('en', {
  longDateFormat: {
    LLL: "MMMM Do, LT", // Oct 6th, 4:27 PM
  }
});

moment.updateLocale('ru', {
  longDateFormat: {
    LLL : 'D MMMM, HH:mm', // 6 окт., 16:27
  }
});

Upvotes: 7

S McCrohan
S McCrohan

Reputation: 6693

Okay. This is a little awful, but you knew it was going to be.

First, you can access the actual format string for (for instance) 'L':

var formatL = moment.localeData().longDateFormat('L');

Next, you can perform some surgery on it with judicious regex replacement:

var formatYearlessL = formatL.replace(/Y/g,'').replace(/^\W|\W$|\W\W/,'');

(Which is to say: Remove YYYY, plus the orphaned separator left by its removal)

Then you can use your new format string in a moment format call:

someDate.format(formatYearlessL);

This necessarily makes some assumptions:

  • The order of the month + day numeric format for a locale matches the order for the year + month + day format for that locale, with the year removed.
  • The short form uses separators only between month and day (no leading / trailing separators).
  • The separator for a short numeric date format is always non-alphanumeric.
  • The format consists of numeric elements and separators, rather than a sentence-form format with articles (see RGPT's comment below about Spanish and Portugese, which will also apply to long formats in some other languages).

On a quick review of locale/*.js, these assumptions hold true for every locale file I examined, but there may be some locales that violate them. (ETA: a comment below points out that a German short date format violates the second assumption)

As an additional important caveat, this is likely to be fragile. It is entirely possible that a future version of moment.js will change the location of the data currently in longDateFormat...

Upvotes: 32

Related Questions