如何使用 JavaScript date-fns 库在特定时区格式化日期/时间

Posted

技术标签:

【中文标题】如何使用 JavaScript date-fns 库在特定时区格式化日期/时间【英文标题】:How to format date/time in a specific timezone with the JavaScript date-fns library 【发布时间】:2018-01-22 21:57:24 【问题描述】:

有没有办法使用date-fns 库在指定时区格式化/输出日期?我可以很容易地格式化日期:

format(
  new Date(),
  'MM/DD/YYYY'
)

我可以指定一个语言环境(来自他们的文档):

var eoLocale = require('date-fns/locale/eo')
var result = format(
  new Date(2014, 6, 2),
  'Do [de] MMMM YYYY',
  locale: eoLocale
)

如何指定时区?

【问题讨论】:

documentation for formatting 中似乎没有任何用于指定时区的标记,仅用于格式化它(“Z”或“ZZ”)。我希望“语言环境”不被用作“语言”的同义词。 是的 RobG,我在格式文档中没有看到任何关于时区的信息。正在考虑有另一种方法来处理 date-fns 中的时区,或者它没有记录,因为这似乎是一个非常重要的功能...... 时区支持并非微不足道,有大量的区域,它们的偏移量和适用日期有很多变化,特别是自从 20 世纪夏令时开始流行以来。仅 Moment.js 时区支持的完整数据压缩后为 26kb。哦,IANA dataset 超过 300kb。 【参考方案1】:

版本 2 拯救了这一天!

  const  startOfDay, endOfDay, format  = require('date-fns') // or use imports
  const  enGb  = require('date-fns/locale/en-GB') // or use imports

  const fromDate = startOfDay(new Date('02-Aug-2001'))
  const toDate = endOfDay(new Date('02-Aug-2001'))
  const from = format(fromDate, 'dd-MMM-yyyy HH:mm:ss',  locale: enGb )
  const to = format(toDate, 'dd-MMM-yyyy HH:mm:ss',  locale: enGb )
  console.log(from) // 02-Aug-2001 00:00:00
  console.log(to) // 02-Aug-2001 23:59:59

https://date-fns.org/v2.21.1/docs/format // 官方文档

https://www.npmjs.com/package/date-fns-tz#user-content-format // 更易于阅读的文档(注意不需要安装 date-fns-tz)

【讨论】:

【参考方案2】:

恐怕您将不得不等待time zone support in date-fns 直到2.0 版本发布。时区支持has not been finished,并且很可能只添加到新版本中,预计解析和格式化会得到改进。

与此同时,您必须访问其他允许在任意时区格式化的库。例如Moment.js 或Day.js:

// Print "06/01/2014 8:00:00 PM GMT-0400 (EDT)"

moment('2014-06-02T00:00:00.000Z')
  .tz('America/New_York')
  .format('MM/DD/YYYY h:mm:ss A [GMT]ZZ (z)')

dayjs('2014-06-02T00:00:00.000Z')
  .format('MM/DD/YYYY h:mm:ss A [GMT]ZZ (z)',
           timeZone: 'America/New_York' )

可运行代码 sn-p 将结果插入 html

// Initialise day.js extensions
dayjs.extend(dayjs_plugin_timeZone)

// Prepare the canvas
const output = document.getElementById('output')
output.innerHTML = 'Expected:  06/01/2014 8:00:00 PM GMT-0400 (EDT)\n'


// Print "06/01/2014 8:00:00 PM GMT-0400 (EDT)"

const date1 = moment('2014-06-02T00:00:00.000Z')
  .tz('America/New_York')
  .format('MM/DD/YYYY h:mm:ss A [GMT]ZZ (z)')
output.innerHTML += `Moment.js: $date1\n`

const date2 = dayjs('2014-06-02T00:00:00.000Z')
  .format('MM/DD/YYYY h:mm:ss A [GMT]ZZ (z)',
           timeZone: 'America/New_York' )
output.innerHTML += `Date.js:   $date2\n`
<script src="https://unpkg.com/moment@2.24.0/min/moment-with-locales.min.js"></script>
<script src="https://unpkg.com/moment-timezone@0.5.25/builds/moment-timezone-with-data.min.js"></script>

<script src="https://unpkg.com/timezone-support@1.8.1/dist/lookup-convert.umd.js"></script>
<script src="https://unpkg.com/timezone-support@1.8.1/dist/data.umd.js"></script>
<script src="https://unpkg.com/dayjs-ext@2.2.0/dayjs.min.js"></script>
<script src="https://unpkg.com/dayjs-ext@2.2.0/plugin/timeZone.js"></script>

<pre id="output"></pre>

【讨论】:

我不相信你的第二个例子是正确的。 @JoeTidee,在my jsfiddle example 试试看,它确实有效。请注意,我使用my fork of day.js 直到官方支持时区。

以上是关于如何使用 JavaScript date-fns 库在特定时区格式化日期/时间的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript日期库之date-fn.js

如何在 VueJS 中使用 Date-FNS?

如何使用 date-fns 格式化日期?

如何使用 date-fns 找到一周中最近的一天

如何在 Vue 3 项目中显示使用 date-fns 格式的 Firestore 时间戳字段?

使用 date-fns 2.x 版时,如何将日期时间格式化为 am/pm,不带句点?