As of a special project, there were mentioned that the Date should always as yyyy-MM-dd HH:mm:ss format. But there should have a timezone potential risk while the program were running on the place globally. Especially under the BaaS or FaaS AKA Serverless environment.

I’d researched some resources such as BCP47, rfc3339 about the DateTimeFormat. Those specifications It’s not easier to scope and use that options for me. So sad so bad.

As of the Moment.js was under LTS situation, here’s a pure simple way to do the formatting date and time with locale, just using the build-in Date and Intl.DateTimeFormat classes.

Generally, the en-GB locale which was dd/MM/yyyy, HH:mm:ss format and it’s similar to yyyy-MM-dd HH:mm:ss. Here’s just need put the source in that particular order. Codes below:

v1 版

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var localeDateTime = thing => new Intl.DateTimeFormat(
    'en-GB',
    {
        dateStyle:'short',
        timeStyle:'medium',
        timeZone: 'Asia/Shanghai',
    }
).format(new Date(thing)).replace(
    /^(\d{2})\/(\d{2})\/(\d{4}),\s(.*)$/,
    (_, dd, MM, yyyy, partialTime) => `${yyyy}-${MM}-${dd} ${partialTime}`
)

v2 版

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var localeDateTime = thing => new Intl.DateTimeFormat(
    'en-GB',
    {
        dateStyle:'short',
        timeStyle:'medium',
        timeZone: 'Asia/Shanghai',
    }
).format(new Date(thing)).replace(
    /^(\d{2})\/(\d{2})\/(\d{4}),\s(\d{2}):(\d{2}):(\d{2})$/,
    (_, dd, MM, yyyy, HH, mm, ss) => `${yyyy}-${MM}-${dd} ${HH}:${mm}:${ss}`
)

As of the ES2018 RegExp named capture groups(since nodejs v10.8.0) available, the codes should more readable with v3:

v3 版

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var localeDateTime = (thing, timeZone = 'Asia/Shanghai') => new Intl.DateTimeFormat(
    'en-GB',
    {
        dateStyle:'short',
        timeStyle:'medium',
        timeZone,
    }
).format(new Date(thing)).replace(
    /^(?<dd>\d{2})\/(?<MM>\d{2})\/(?<yyyy>\d{4}),\s(?<HH>\d{2}):(?<mm>\d{2}):(?<ss>\d{2})$/,
    '$<yyyy>-$<MM>-$<dd> $<HH>:$<mm>:$<ss>'
)

v4 版

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var localeDateTime = (thing = Date.now(), timeZone = 'Asia/Shanghai') => Intl.DateTimeFormat.call(
    null,
    'en-GB',
    {
        dateStyle:'short',
        timeStyle:'medium',
        timeZone,
    }
).format(new Date(thing)).replace(
    /^(?<dd>\d{2})\/(?<MM>\d{2})\/(?<yyyy>\d{4}),\s(?<HH>\d{2}):(?<mm>\d{2}):(?<ss>\d{2})$/,
    '$<yyyy>-$<MM>-$<dd> $<HH>:$<mm>:$<ss>'
)

v5 版本

Notes: NodeJS v10.15.3,v12.18.0,v14.5.0 had strange behavior on Intl.DateTimeFormat, see hourCycle:h23 comments below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var localeDateTime = (when = Date.now(), timeZone = 'Asia/Shanghai') {

    // short `when` like `Aug 9, 1995` is dependend on the `TZ` env
    process.env.TZ = timeZone

    let data = new Intl.DateTimeFormat(
      'en',
      {
        calendar: 'gregory', hourCycle: 'h11',
        year: 'numeric', month: '2-digit', day: '2-digit',
        hour: 'numeric', minute: '2-digit', second: '2-digit',
        timeZone,
      }
    ).formatToParts(
      new Date(when)
    ).filter(({type}) => type != 'literal').reduce(
      (des, {type, value}) => (des[type.toLowerCase()] = value.toUpperCase(), des),
      {}
    )

    // hourCycle:h23 fix(12 AM to 0, 12 PM to 0)
    data.hour = data.hour == '12' ? `0` : data.hour

    if (data.dayperiod == 'PM') {
      // hourCycle:h23 add(1 PM to 13)
      data.hour = `${12 + data.hour * 1}`
    } else if (data.dayperiod == 'AM') {
      // hourCycle:h23 fix(2-digit)
      data.hour = data.hour.length > 1 ? data.hour : `0${data.hour}`
    }

    return `${data.year}-${data.month}-${data.day} ${data.hour}:${data.minute}:${data.second}`
  }

Usage samples:

1
console.info(localeDateTime())
1
'2020-09-20 08:38:54'
1
console.info(localeDateTime(1600538598726))
1
'2020-09-20 02:03:18'
1
console.info(localeDateTime('January 1, 1970, 00:00:00 UTC'))
1
'1970-01-01 08:00:00'
1
console.info(localeDateTime(Date.now(), 'UTC'))
1
'2020-09-20 00:39:01'
1
console.info(localeDateTime('2019-01-01'))
1
'2019-01-01 08:00:00'
1
console.info(localeDateTime('2020-11-11 00:00'))
1
'2020-11-11 00:00:00'
1
console.info(localeDateTime('Aug 9, 1995'))
1
'1995-08-09 00:00:00'
1
console.info(localeDateTime(Date.UTC(2012, 11, 20, 3, 0, 0), 'America/Los_Angeles'))
1
'2012-12-19 19:00:00'

Ok~ It’s enough.