微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

所有时区中的日期相同

如何解决所有时区中的日期相同

我在所有时区都显示相同的日期时遇到问题。 例如,用户输入为2002年1月1日,我将其存储为带有Eureope/Berlin时区的日期 parseFromTimeZone(String(birthDate),{ timeZone: 'Europe/Berlin' }) parseFromTimeZone的结果就是这个字符串'2001-12-31T23:00:00.000Z'。字符串日期以柏林的时区计算,这就是为什么它会偏移一小时。

我需要在所有时区都从'2001-12-31T23:00:00.000Z'01-01-2002

我使用formatISO(new Date(date),{ representation: 'date' }))时区为01-01-2002Europe/Prague时返回Europe/Berlin

但是当我将时区更改为America/Tijuana时,formatISO返回2001-12-31,这是错误的,我需要始终与Europe/Berlin中的日期相同!为Asia/Tokyo芽,此函数返回正确的01-01-2002 ...

有些想法?我尝试了很多解决方案,但没有一个适用于所有时区的方法...

我正在使用"date-fns": "^2.15.0""date-fns-timezone": "^0.1.4"

解决方法

Date对象,尽管其名称为,但并不表示“日期”。它代表一个时间戳。它在内部存储的只是自Unix纪元(基于UTC)以来的毫秒数。它根据调用的函数,根据UTC或运行机器的本地时区输出值。

因此,如果从仅日期的值构造Date对象,则实际上是从该时区获取“午夜时间”并将其调整为UTC。您在2002-01-01中的Europe/Berlin示例中对此进行了证明。您将其视为2002-01-01T00:00:00.000+01:00,其确具有与2001-12-31T23:00:00.000Z相等的UTC,因此不包含与预期时区相同的年,月和日元素。

如果您想防止仅日期的值发生偏移,实际上只有两个选项可以处理仅日期的值:

  • 您的第一个选择是使用Date对象,但将输入视为UTC,并且仅使用基于UTC的函数。例如:

    var dt = new Date(Date.UTC(2002,1));  // "2002-01-01T00:00:00.000Z"
    
    var y = dt.getUTCFullYear();  // 2002
    var m = dt.getUTCMonth() + 1; // 1
    var d = dt.getUTCDate();      // 1
    
    var dtString = d.toISOString().substring(0,10) // "2002-01-01"
    
    • 如果您需要解析日期字符串,请注意, current ECMAScript规范将仅日期的值视为UTC(这是您想要的),但是在过去,这种行为是未定义。因此,某些浏览器可能会根据new Date('2002-01-01')创建本地时间结果。为了安全起见,您可能希望像Z那样显式地添加时间和new Date('2002-01-01' + 'T00:00:00.000Z')

    • 如果要使用date-fns,请小心-parseISOformatISO函数使用的是本地时间,而不是UTC。

  • 第二个选项是使用Date对象。将日期保留为字符串形式(ISO 8601 yyyy-mm-dd格式),或将其保留在您自己构造的或来自库的其他对象中。

ECMAScript TC39 Temporal proposal旨在解决JavaScript中的此类缺陷。特别是,Temporal.Date对象(初步名称)将能够用于仅日期的值,而不会遇到您和其他许多人遇到的移位问题。该提案目前处于ECMAScript流程的第2阶段,因此今天无法使用,但最终会解决此问题!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。