1

Moment.js has a handy formats (l, L, ll, LL, lll, LLL, llll and LLLL) for formatting a date in the current locale.

The problem is that this formats date including the day. For example moment('1986-02-05').format('LL') will be output as February 5, 1986.

The reason why this doesn't work for me is that I only want to display the day, only the month. In English that would be February 1896.

Is there a way of formatting only month and year according to a locale? If not with momentjs, with any other library. I'd also take a link to a list of the strings that I could pass to .format for common locales.

VincenzoC
  • 30,117
  • 12
  • 90
  • 112
miguel.camba
  • 1,777
  • 1
  • 14
  • 19

2 Answers2

0

Please refer bellow code for required format, it will work :

moment.locale('en');
var date = moment(new Date());
console.log(date.format('MMMM YYYY'));
0

See momentjs format() docs for a list of tokens that you can use to show date and time.

In your case, the relevant tokens are MMM for month name and YYYY for the year. Don't forget to load each locale you need to use, as described here.

You can use locale() function to change the locale of the given moment instance and moment.locale if you need you can change locale globally.


EDIT:

There is no built-in method to get the localized input you are looking for, but you can use moment localeData and longDateFormat to get localized format for LL (Month name, day of month, year) and then manipulate to strip the day of month part. The following snippet work for many locale, but it doesn't show the expected output for each locale (some fails: es, eu, lt, ...).

My suggestion is to define a subset of supported locales and manually define format for edge cases.

function getMonthYear(value){
  moment.locale(value);
  
  // Get locale data
  var localeData = moment.localeData();
  var format = localeData.longDateFormat('LL');
  
  // Manage custom cases
  if( value === 'br'){
    format = 'MMMM YYYY';
  }
  if( value === 'en-ca'){
    format = 'MMMM, YYYY';
  }
  // if( value === ...) possible other cases
  
  // Check locale format and strip day from the first part
  if( format.match(/^D/g) ){
    format = format.replace(/^D\./, '').replace(/^D/, '');
  }
  format = format.trim();

  return moment('1986-02-05').format(format);
}

['af' , 'ar-dz', 'ar-kw', 'ar-ly', 'ar-ma', 'ar-sa', 'ar-tn', 'ar', 'az', 'be', 'bg', 'bn', 'bo', 'br', 'bs', 'ca', 'cs', 'cv', 'cy', 'da', 'de-at', 'de-ch', 'de', 'dv', 'el', 'en-au', 'en-ca', 'en-gb', 'en-ie', 'en-nz', 'eo', 'es-do', 'es', 'et', 'eu', 'fa', 'fi', 'fo', 'fr-ca', 'fr-ch', 'fr', 'fy', 'gd', 'gl', 'gom-latn', 'he', 'hi', 'hr', 'hu', 'hy-am', 'id', 'is', 'it', 'ja', 'jv', 'ka', 'kk', 'km', 'kn', 'ko', 'ky', 'lb', 'lo', 'lt', 'lv', 'me', 'mi', 'mk', 'ml', 'mr', 'ms-my', 'ms', 'my', 'nb', 'ne', 'nl-be', 'nl', 'nn', 'pa-in', 'pl', 'pt-br', 'pt', 'ro', 'ru', 'sd', 'se', 'si', 'sk', 'sl', 'sq', 'sr-cyrl', 'sr', 'ss', 'sv', 'sw', 'ta', 'te', 'tet', 'th', 'tl-ph', 'tlh', 'tr', 'tzl', 'tzm-latn', 'tzm', 'uk', 'ur', 'uz-latn', 'uz', 'vi', 'x-pseudo', 'yo', 'zh-cn', 'zh-hk', 'zh-tw'].forEach(localeName => {
  console.log(
    localeName + ':',
    getMonthYear(localeName));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment-with-locales.min.js"></script>

You can find similar question here and here


The following script creates and displays a Map with the number of occurences for each LL string. As you can see there are 68 occurences of D MMMM YYYY (targeted by the regex of the previous snippet) and few other formats covered by the previous getMonthYear. This may help you define a list of unsupported case and define a custom workaround

let formatMap = new Map();

['af' , 'ar-dz', 'ar-kw', 'ar-ly', 'ar-ma', 'ar-sa', 'ar-tn', 'ar', 'az', 'be', 'bg', 'bn', 'bo', 'br', 'bs', 'ca', 'cs', 'cv', 'cy', 'da', 'de-at', 'de-ch', 'de', 'dv', 'el', 'en-au', 'en-ca', 'en-gb', 'en-ie', 'en-nz', 'eo', 'es-do', 'es', 'et', 'eu', 'fa', 'fi', 'fo', 'fr-ca', 'fr-ch', 'fr', 'fy', 'gd', 'gl', 'gom-latn', 'he', 'hi', 'hr', 'hu', 'hy-am', 'id', 'is', 'it', 'ja', 'jv', 'ka', 'kk', 'km', 'kn', 'ko', 'ky', 'lb', 'lo', 'lt', 'lv', 'me', 'mi', 'mk', 'ml', 'mr', 'ms-my', 'ms', 'my', 'nb', 'ne', 'nl-be', 'nl', 'nn', 'pa-in', 'pl', 'pt-br', 'pt', 'ro', 'ru', 'sd', 'se', 'si', 'sk', 'sl', 'sq', 'sr-cyrl', 'sr', 'ss', 'sv', 'sw', 'ta', 'te', 'tet', 'th', 'tl-ph', 'tlh', 'tr', 'tzl', 'tzm-latn', 'tzm', 'uk', 'ur', 'uz-latn', 'uz', 'vi', 'x-pseudo', 'yo', 'zh-cn', 'zh-hk', 'zh-tw'].forEach(localeName => {
  var format =  moment.localeData(localeName).longDateFormat('LL');
  
  if( formatMap.has(format) ){
    let val = formatMap.get(format);
    formatMap.set(format, val+1);
  } else {
    formatMap.set(format, 1);
  }
  
});

console.log(formatMap);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment-with-locales.min.js"></script>
VincenzoC
  • 30,117
  • 12
  • 90
  • 112
  • This will not work as you are enforcing a specific order (MMM YYYY) but different languages have different conventions for this. In English "February 2015" when translated to chinese should be `2015年2月`. As you see, the month-year order is inversed and that is why I just can't use a fixed M/Y format, it has to be per-locale. – miguel.camba Jul 24 '17 at 13:05
  • @miguel.camba I've edited my answer to provide an updated solution that I think is closer to what you are asking. – VincenzoC Jul 24 '17 at 22:11
  • I guess that it could work if I manually inspect all the languages and find the exceptions. I was hoping for an authoritative source for that, but it is indeed a last option. – miguel.camba Jul 26 '17 at 14:49
  • @miguel.camba you are right, as I stated in the answer _There is no built-in method to get the localized input you are looking for_, I've added a map showing the number of occurences for each `LL` string in order to help you _manually inspect all the languages and find the exceptions_. At the beginning I posted my answer only because I misinterpreted your question, otherwise I would simply had posted the similar (linked) question in comments. I'm trying to provide all info and workarounds in order to help you. – VincenzoC Jul 26 '17 at 15:39
  • With your script I've manually found the exceptions that are not MMM YYYY and hardcoded them into my core, so I guess I can consider it correct. They are just 8. – miguel.camba Aug 01 '17 at 15:39