17

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?

GollyJer
  • 23,857
  • 16
  • 106
  • 174

2 Answers2

21

-- 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];
    },
    // ...
}
GollyJer
  • 23,857
  • 16
  • 106
  • 174
Toribio
  • 3,963
  • 3
  • 34
  • 48
  • Thanks for the answer. I didn't even realize version 2 is fairly new. I've updated the question to reflect the new version which doesn't have the formatting from your answer with 1.x. – GollyJer Mar 18 '20 at 03:35
  • @GollyJer Edited the answer. Version 2 was also news for me. It seems to be working the same way so I don't know what the deal with the documentation is. `a` for `am`, `aa` for `a.m.` and `A` for `AM` etc... Edit: I now see there's a 2.11.0 version but not available on CDN, I'll check it out and get back to you. – Toribio Mar 18 '20 at 04:05
  • 1
    I found a way to do this with 2.1+. Can you update your answer and I'll accept it. Thanks. `format(new Date(), "YYYY-MM-DD hh:mm aaaaa'm'")` – GollyJer Mar 18 '20 at 22:54
  • It doesn't like capital A for AM. – Marcie Jun 02 '23 at 18:37
10

You can now use the aaa pattern for that case (v.2.23.0).

enter image description here

Source: https://date-fns.org/v2.23.0/docs/format

Brunno Vodola Martins
  • 1,582
  • 2
  • 15
  • 17