display day and month, without a year according to locale
Asked Answered
P

5

5

Is there any better way for getting only day and month from a date including location appropriate separator?

I have a solution that gets separator first:

 function getDateSep() {
   var temp = moment().format('L');
   var locale = moment().locale;
   var datesep = temp.substring(5, 6);
   return datesep;
}

and then builds the date like this:

var sep = function getDateSep()
var date = date.format('D' + sep + 'M'+ sep)

Is there a solution that builds the whole date dynamically?

The result I want to achieve would be like: 31.01 (dd.mm) 31/01 (dd/mm) 01.31 (mm.dd) 01/31 (mm/dd) etc

Propagate answered 24/2, 2017 at 11:15 Comment(8)
What's your expected output? Please provide an example.Goldsworthy
I need day and month in localized format, my current one doesn't achieve that. I only get the localized separator.Propagate
See hereParasang
@Parasang awesome! Exactly what I needed. Weird, never got it as a search result.Propagate
Possible duplicate of moment get date formatted on localeParasang
@Jane Doe The thing with localization is that the formatting is very different across different locales. You can play around with the different locales yourself on Moment's homepage at the bottom: momentjs.com Notice how some of them put the date first, some put the month first, some put the year first, and the Asian languages use Unicode characters. They also use different separators. VincenzoC's links works...until you come across a date that puts the year first. Even en-CA will trigger it.Goldsworthy
@DanielT. citing from the linked answer: I'm not sure that it will work for each locale I'm happy that you find a corner case in which that solution does not work. Anyway I think that it's easy to update the suggested solution to make it work also for locales like en-CAParasang
And then it will break for East Asian languages, and if you fix it there, it will break for Arabic, and then for Hindi, etc. My point is, it's much better to manually create the locale format for every locale you think you will use, rather than trying to use a regex as a catch-all.Goldsworthy
P
4

As stated in the linked question: One way to do what you need is getting localized longDateFormat and then remove the year part with a regular expression.

Daniel T. highlighted in comments that the solution will not work in locales like en-CA, so I'm going to provide an updated solution that takes in account some other locales that starts with year part.

Probably there are some other locales the are not convered with /.YYYY/ and /YYYY./ RegExp, if you need to support every locale you can target them with ad hoc condition, as I made for ar-ly in the following snippet.

Here a code sample the shows possible output in various locales:

function changeLang(value){
  moment.locale(value);
  
  // Get locale data
  var localeData = moment.localeData();
  var format = localeData.longDateFormat('L');
  
  // Manage custom cases
  if( value === "ar-ly"){
    format = 'D/\u200FM';
  }
  // if( value === ...) possible othter cases
  
  // Check locale format and strip year
  if( format.match(/.YYYY/g) ){
    format = format.replace(/.YYYY/, '');
  }
  if( format.match(/YYYY./g) ){
    format = format.replace(/YYYY./, '');
  }

  var res = moment().format(format);
  
  $("#result").html(res);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js"></script>

<select onchange="changeLang(value)">
  <option value="en">EN</option>
  <option value="en-CA">en-CA (Canada)</option>
  <option value="eo">eo (Esperanto)</option>
  <option value="de">DE</option>
  <option value="it">IT</option>
  <option value="hu">hu (Hungarian)</option>
  <option value="ja">ja (Japanese)</option>
  <option value="lv">lv (Latvian)</option>
  <option value="fr">FR</option>
  <option value="zh-hk">zh-hk - Chinese (Hong Kong)</option>
  <option value="ar-ly">ar-ly - Arabic (Lybia)</option>
</select>

<div id="result"></div>
Parasang answered 24/2, 2017 at 20:5 Comment(1)
thanks! With this edit it seems to work with most of the locales we use. I also agree, that regex might not be the best solution to catch year, but seems like there is nothing better atm.Propagate
A
17

Have you considered using Date#toLocaleDateString instead of momentjs?

It takes a JS Date object and options to output a locale date in the format you specify.

Example:

var date = new Date();
var options = { day: 'numeric', month: 'short' };

console.log(date.toLocaleDateString('en-GB', options));
// outputs: Feb 24

var numeric = { day: 'numeric', month: 'numeric' };

console.log(date.toLocaleDateString('en-GB', numeric));
// outputs: 24/02

As pointed out in the comments, it's worth ensuring that your targeted platforms support the toLocaleDateString approach above with options. For instance, this approach isn't currently supported by Android webview as detailed here for toLocaleDateString's Browser_compatibility.

Accident answered 24/2, 2017 at 11:35 Comment(6)
If you use undefined for the language, it will adopt the default language of the browser.Barstow
@RobG: thanks for pointing out typos and language code error.Accident
as I understood, you need to know the locale to pass to the function plus it still has a year part which has to be removed after splitting.Propagate
It can be used in a variety of ways. My answer provides a ways to create a string of MMM DD or DD/MM which can me manipulated as desired.Accident
This answer is correct except if you target Android webview. According to browser compatibility (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…) Date.toLocaleDateString ignore arguments on Android webview.Callis
@VictorDias: thanks for pointing this out. I'll add a caveat to my answerAccident
P
4

As stated in the linked question: One way to do what you need is getting localized longDateFormat and then remove the year part with a regular expression.

Daniel T. highlighted in comments that the solution will not work in locales like en-CA, so I'm going to provide an updated solution that takes in account some other locales that starts with year part.

Probably there are some other locales the are not convered with /.YYYY/ and /YYYY./ RegExp, if you need to support every locale you can target them with ad hoc condition, as I made for ar-ly in the following snippet.

Here a code sample the shows possible output in various locales:

function changeLang(value){
  moment.locale(value);
  
  // Get locale data
  var localeData = moment.localeData();
  var format = localeData.longDateFormat('L');
  
  // Manage custom cases
  if( value === "ar-ly"){
    format = 'D/\u200FM';
  }
  // if( value === ...) possible othter cases
  
  // Check locale format and strip year
  if( format.match(/.YYYY/g) ){
    format = format.replace(/.YYYY/, '');
  }
  if( format.match(/YYYY./g) ){
    format = format.replace(/YYYY./, '');
  }

  var res = moment().format(format);
  
  $("#result").html(res);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js"></script>

<select onchange="changeLang(value)">
  <option value="en">EN</option>
  <option value="en-CA">en-CA (Canada)</option>
  <option value="eo">eo (Esperanto)</option>
  <option value="de">DE</option>
  <option value="it">IT</option>
  <option value="hu">hu (Hungarian)</option>
  <option value="ja">ja (Japanese)</option>
  <option value="lv">lv (Latvian)</option>
  <option value="fr">FR</option>
  <option value="zh-hk">zh-hk - Chinese (Hong Kong)</option>
  <option value="ar-ly">ar-ly - Arabic (Lybia)</option>
</select>

<div id="result"></div>
Parasang answered 24/2, 2017 at 20:5 Comment(1)
thanks! With this edit it seems to work with most of the locales we use. I also agree, that regex might not be the best solution to catch year, but seems like there is nothing better atm.Propagate
T
3

While the accepted answer does the job by manipulating the pre-defined localized formats Moment provides, there's another way that Moment allows you to extend its localized configuration that may be more suitable in some situations.

If you open up one of the localization files in the npm module, like /moment/locale/de.js, you'll see a list of localized date formats that looks like this:

longDateFormat : {
    LT: 'HH:mm',
    LTS: 'HH:mm:ss',
    L : 'DD.MM.YYYY',
    LL : 'D. MMMM YYYY',
    LLL : 'D. MMMM YYYY HH:mm',
    LLLL : 'dddd, D. MMMM YYYY HH:mm'
},

This will give you a good starting point and clue at how to localize for each locale you support. For example, German places the day with a period before the month, where in English, The month comes before the day.

You can then copy and tweak the format you want, by extending the configuration at initialization:

// Update configs with custom date formats per language after
// moment locales are loaded (LMD is a custom format here)
moment.updateLocale('en', { longDateFormat: { LMD: 'MMMM D' } });
moment.updateLocale('de', { longDateFormat: { LMD: 'D. MMMM' } });
// repeat with culturally-correct formatting for other locales you support

function changeLang(value){
  moment.locale(value);
  
  // Retrieve stored custom format
  var format = moment.localeData().longDateFormat('LMD');
  var res = moment().format(format);
  
  $("#result").html(res);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js"></script>

<select onchange="changeLang(value)">
  <option value="en">EN</option>
  <option value="de">DE</option>
</select>

<div id="result"></div>

You could also forego extending the configuration, and keep your custom formats in a custom data structure something like this:

var MOMENT_FORMATS = {
  LMD: {
    en: 'MMMM D',
    de: 'D. MMMM'
  }
};
moment().format(MOMENT_FORMATS.LMD[moment.locale()])
Thorbert answered 26/10, 2018 at 22:13 Comment(1)
Actually the most correct answer, this one is how moment expects you to handle this cases, not with weird formattingsRosamariarosamond
C
1

You can try the regex below and check if it works for you.I tried with different locale it was working as expeted

dateFormat.replace(/Y/ig, '  ').replace(/^\W{1,}|\W{1,}$|\W{3,3}/, '');
Chassepot answered 13/9, 2019 at 7:2 Comment(0)
C
1

For Jquery usage, I have used the following way to show the date (+ hh:mm) without year:

var timeOptions = {hourCycle: 'h23', hour: '2-digit', minute:'2 digit'};

var dateOptions = { day: 'numeric', month: 'numeric' };
...

<td>${one.Date.toDate().toLocaleDateString('en-CA', dateOptions)} ${one.Date.toDate().toLocaleTimeString( [],  timeOptions)}</td>

... Output will be like this structure -> MM-dd hh:mm (12-22 13:25)

Caseate answered 9/2, 2023 at 1:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.