How do you format a datetime to am/pm, without periods, when using date-fns version 2.x?

Viewed 10944

Version 2.x of the excellent date package date-fns only has these built-in am/pm formats.

date-fns am pm formats

How can I format the lower case am/pm without the periods?

2 Answers

-- For datefns versions older than 2.23.0 --

Quick solution

Use aaaaa'm':

format(new Date(), "YYYY-MM-DD hh:mm aaaaa'm'")

Explanation: @GollyJer found a really clever way to work around this limitation. We can use aaaaa to yield a (for AM) or p (for PM) according to the documentation. Then we just follow it with the escaped character m, which is 'm', resulting in am or pm.

Note: this may result in a wrong output if you allow any kind of locale switching, because AM and PM may be different depending on the language.

Other ways

Nonetheless, for these versions, there's no native¹ way of doing this, as per documentation and source code reviewing, because the formatting is dependent on the locale configuration as shown in the source code (_lib/format/formatters/index.js):

// AM or PM
a: function(date, token, localize) {
  var hours = date.getUTCHours()
  var dayPeriodEnumValue = hours / 12 >= 1 ? 'pm' : 'am'

  switch (token) {
    case 'a':
    case 'aa':
    case 'aaa':
      return localize.dayPeriod(dayPeriodEnumValue, {
        width: 'abbreviated',
        context: 'formatting'
  })
  // ...

1: by native, I mean a straightforward native API formatter.

You can add a new locale to customize the strings though. This would imply changing this specific part (based on locale/en-US/_lib/localize/index.js):

var formattingDayPeriodValues = {
    // ...
    abbreviated: {
        am: 'AM',
        pm: 'PM',
        // ...
    }
    // ...
}

It's sad this new version doesn't have a straightforward way of customizing the default locales, or even just a simple way to apply a monkey-patch. Creating a new locale isn't elegant at all and replacing a.m. with am manually after the call to format isn't either.

Versions 1.x.x and 2.0.0 (alpha/beta)

For these versions, just use the a format. Example:

console.log(dateFns.format(new Date(), 'YYYY-MM-DD hh:mm a'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.30.1/date_fns.min.js"></script>
<!-- or: https://cdnjs.cloudflare.com/ajax/libs/date-fns/2.0.0-alpha0/date_fns.min.js -->

You can check for yourself in the source code the way it works:

var meridiemLowercase = [
    'am',
    'pm'
];

var formatters = {
    // ...
    'a': function (date) {
        return date.getHours() / 12 >= 1 ? meridiemLowercase[1] : meridiemLowercase[0];
    },
    // ...
}
Related