使用date-fns正确解析UTC日期的方法

13

我有一个日志文件,其中包含一些时间戳

2020-12-03 08:30:00
2020-12-03 08:40:00
...

我从日志提供程序的文档中得知时间戳是以协调世界时(UTC)编写的(虽然没有使用ISO格式)

现在我想要使用date-fns来解析它们:

const toParse = "2020-12-03 08:40:00"
parse(toParse, 'yyyy-MM-dd HH:mm:ss', new Date()).toISOString()

因为我的电脑时区是UTC+1,所以这是我看到的:

> "2020-12-03T07:40:00Z"

预期结果:

> "2020-12-03T08:40:00Z".

以下是我目前使用的技巧,用于告诉date-fns将时间解析为UTC:

const toParse = "2020-12-03 08:40:00"
parse(toParse + '+00', 'yyyy-MM-dd HH:mm:ss' + 'X', new Date()).toISOString()

正如预期的那样,

> "2020-12-03T08:40:00Z".

有没有使用date-fns的适当方法来做到这一点?寻找一个与moment的moment.utc()相等的方法。


你可能想看一下 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat 你知道要调整存储的日期到你所在的时区需要偏移量。Date-fns-tz 支持 Intl.DateTimeFormat。 - WildWilyWilly
1
无论如何,您都应该指示日期时间值所属的时区。您可以简化您的hack:parseIso(toParse+'Z').toISOString() - Anatoly
1
如果将“2020-12-03 08:40:00”解析为UTC +1,则Z时间为07:40:00Z,而不是09:40。 :-) - RobG
3个回答

13

我不知道“适当”是什么意思,但您可以使用zonedTimeToUtc将时间戳视为具有任何偏移量或时区(包括 UTC)。

// Setup
var {parse} = require('date-fns');
var {zonedTimeToUtc} = require('date-fns-tz');

// Parse an ISO 8601 timestamp recognised by date-fns
let loc = 'UTC';
let s1   = '2020-12-03 08:30:00';
let utcDate =  zonedTimeToUtc(s1, loc);

// Show UTC ISO 8601 timestamp
console.log(utcDate.toISOString()); // "2020-12-03T08:30:00.000Z"

// Parse non–standard format yyyyMMdd
let s2 = '20210119';
let fIn = 'yyyyMMdd';
let d = zonedTimeToUtc(parse(s2, fIn, new Date()), loc);
console.log(d.toISOString()); // "2021-01-19T00:00:00.000Z"```

您可以在npm.runkit.com/date-fns上进行测试。


谢谢,这就是我想要的!然而你的代码没有利用 fIn(幸运的是,在这个例子中它会在UTC解析,但日志可能有一个不太友好的格式)。zonedTimeToUtc(parse(s, fIn, new Date()), loc); 可行。 - Yann Pellegrini
@YannP——是的,如果格式不是date-fns所识别的格式,则需要添加parse。我认为始终需要传递一个日期到parse的要求是一个难以理解的设计决策。 - RobG
完全同意。我不得不在我的拉取请求中添加一条注释,以解释为什么它是“必要的”... - Yann Pellegrini

5

我认为您正在寻找parseJSON,它支持许多格式(但不允许您指定源格式)。

将UTC时间中的完整ISO日期字符串转换为JavaScript Date实例,这是在JSON中传输日期的典型格式。

import { parseJSON } from 'date-fns';
const utcDate = parseJSON('2020-12-03 08:40:00');

// Thu Dec 03 2020 19:40:00 GMT+1100 (Australian Eastern Daylight Time)

是的,来自 date-fnsparseJSON 终于起作用了!我从 SQLite 中获取了 UTC 时间格式的日期字符串,但没有明确的时区信息。使用 date-fnsparse 或原生 JS 的 Date 解析这些日期字符串会导致修改后的日期,因为它们假定了非 UTC 时区。 - strarsis
这应该是被接受的答案,不需要使用date-fns-tz... - Sander van den Akker
是的,但如果您只有日期格式,您不能使用parseJSON('2020-12-03') - phil

2
使用parse和zonedTimeToUtc的示例
 it('should parse polish date', async () => {
    expect.assertions(1)
    const dateWithoutTime = '29 gru 2003'

    const parsed = parse(dateWithoutTime, 'd LLL yyyy', new Date(), {
      locale: pl,
    })

    const dateUTC = zonedTimeToUtc(parsed, 'UTC')

    expect(dateUTC.toISOString()).toStrictEqual('2003-12-29T00:00:00.000Z')
  })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接