【问题标题】:Formatted dates in Node/JavaScript to UTC将 Node/JavaScript 中的格式化日期转换为 UTC
【发布时间】:2021-01-02 06:07:58
【问题描述】:

我正在使用 Node/Express 服务器在将日期发送到浏览器之前对其进行格式化。我拥有的日期以 UTC 格式保存在数据库中,例如:

2020-09-15 11:52:22.000

我现在想在不更改的情况下格式化此日期并将其发送到浏览器,因此无论节点服务器在哪里,也无论浏览器在哪里,它总是显示这个 UTC 日期。查看此日期的人将来自美国、英国、欧盟,但我希望他们都看到相同的 UTC 日期。

我在英国,我正在使用date-fns,我目前正在本地运行 Node。我的应用程序已经使用了date-fns,我不想只为这个任务添加另一个日期/时间依赖项。

如果我这样做:

const d = format(new Date('2020-09-15 11:52:22.000'), 'dd MMM yyyy HH:mm:ss')

我得到:15 Sep 2020 12:52:22...这是我当地时间(英国,英国夏令时)的日期。

如果有一件事让我感到困惑,那就是日期和时间! :-)

在 Node 中,如何获取 2020-09-15 11:52:22.000 并将其格式化以获取 15 Sep 2020 11:52:22 ..?

【问题讨论】:

标签: javascript node.js date date-fns


【解决方案1】:

你的问题是:

new Date('2020-09-15 11:52:22.000')

强烈建议不要对不支持的格式使用内置解析器。它依赖于实现,并且通常在不同的实现中返回不同的结果。

此外,字符串没有时区,因此应视为本地。因此,即使解析正确,它也会代表具有不同偏移量的每个地点的不同时刻。

Date-fns 有一个功能强大的parser,所以你应该使用它而不是内置的 paser。如果您希望时间戳被视为 UTC,最简单的方法是添加尾随“Z”和时区标记以进行解析。

要支持输出时区,您必须包含date-fns-tz。以下是您可以在npm.runkit 运行的一些代码。格式部分出现以产生正确的结果,但是如果将时区标记添加到格式字符串(即“X”或“XX”),它会显示本地时区偏移量,而不是应用的偏移量到字符串以便正确显示偏移量,您必须手动添加它(我认为这是 date-fns-tz 中的错误)。

const dateFns = require("date-fns");
const { zonedTimeToUtc, utcToZonedTime, format } = require('date-fns-tz');

let timestamp = '2020-09-15 11:52:22.000';
let tz = 'Z';
let date = dateFns.parse(timestamp + tz, 'yyyy-MM-dd HH:mm:ss.SSSX', new Date()); 
// Show timestamp was parsed as UTC
console.log(date.toISOString()); // 2020-09-15T11:52:22.000Z

// Produce UTC output - need to set timezone first
let utcDate = utcToZonedTime(date, 'UTC');
// Manually add timezone to formatted string
console.log(format(utcDate, 'd MMM yyyy HH:mm \'UTC\'', 'UTC')); // 15 Sep 2020 11:52 UTC

请注意,utcToZonedTime(date, 'UTC') 实际上创建了一个由指定偏移量修改的新日期,并将其分配给 utcDate,我认为这是一个真正的组合。它现在只有在你知道它是如何被修改的时候才有用,你不知道它实际上应该代表什么时间。在这种情况下,可能很清楚,因为我们使用的是 UTC,但其他偏移量问题更大。

如果初始时间戳采用 ECMAScript 支持的格式,例如:与toISOString产生的相同:2020-09-15T11:52:22.000Z。

【讨论】:

  • 谢谢@RobG...我正在使用date-fns 2.14.0,而您的示例使用的是1.28.5。看起来事情已经改变了。 parse() 现在想要第三个参数。但是,我想要做的是 format 我拥有的日期。看起来 format() 会转换为本地时间,即使您传入的是 UTC 日期对象。呸呸呸
  • 我这里有一个日期对象,当打印到控制台时显示:2020-09-15T13:44:46.000Z,这是 UTC。 isDate() 在此返回 true。当我将它传递给format() 时,得到15 Sep 2020 14:44:46...!这不再是 UTC,而是 BST(+1 小时)!
  • @StephenLast — 更新了当前版本的 date-fns 代码和更好的解释。对不起之前的垃圾,我不应该在赶时间的情况下发布......
【解决方案2】:

你可以试试(我的时区是 +2 GTM)

  1. 解析日期以获取 UTC 字符串
const parsedDate = parse('2020-09-15 11:52:22.000', 'yyyy-MM-dd HH:mm:ss.SSS', new Date()).toUTCString(); 
// Tue, 15 Sep 2020 09:52:22 GMT
// or simply 
// new Date('2020-09-15 11:52:22.000').toUTCString();
    
// format a new date starting from UTC format 
// new Date(parsedDate) --> Tue Sep 15 2020 11:52:22 GMT+0200
const date = format(new Date(parsedDate), 'dd MMM yyyy HH:mm:ss');

格式中的新日期(parsedDate)会将UTC重新转换为您的时区

【讨论】:

    【解决方案3】:

    你应该使用https://momentjs.com/

    例如:

    moment().format('Do MMMM YYYY, h:mm:ss');
    

    【讨论】:

    • 谢谢!但我想使用原生 JavaScript 或 date-fns,而不是 moment 来实现这一点。我的项目已经将date-fns 作为依赖项,并且它在其他任何地方都使用过。我不想添加新的依赖项,尤其是像moment 这样大的依赖项,只是为了这个非常小的任务。
    • 看起来时刻即将结束:momentjs.com/docs/#/-project-status
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 2015-06-06
    • 1970-01-01
    相关资源
    最近更新 更多