为了账号安全,请及时绑定邮箱和手机立即绑定

所有时区的同一日期

所有时区的同一日期

12345678_0001 2023-06-09 15:01:31
我在所有时区显示相同日期时遇到问题。例如,用户输入的是 01-01-2002,我将其存储为带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/PragueEurope/Berlin但是当我将时区更改为America/Tijuana然后formatISO返回时2001-12-31,这是错误的,我需要与Europe/Berlin始终保持相同的日期!Bud 对于Asia/Tokyo这个函数返回01-01-2002是正确的......一些想法?我尝试了很多解决方案,但没有一个适用于所有时区......我正在使用 "date-fns": "^2.15.0","date-fns-timezone": "^0.1.4"
查看完整描述

2 回答

?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

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


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


如果你想防止它们移动,你真的只有两个选项来处理仅限日期的值:


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


var dt = new Date(Date.UTC(2002, 0, 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"


    • 如果您需要解析日期字符串,请注意当前的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 提案旨在修复 JavaScript 中的此类缺陷。特别是,该Temporal.Date对象(初步名称)将能够用于仅限日期的值,而不会出现您和许多其他人遇到的转移问题。该提案目前处于 ECMAScript 进程的第 2 阶段,因此今天无法使用,但这个问题最终会得到解决!


查看完整回答
反对 回复 2023-06-09
?
白板的微信

TA贡献1883条经验 获得超3个赞

使用 ISO_8601 日期尝试此功能,然后更改计算机设置中的时区并使用新时区重试。它应该在您的网页上为两个时区打印相同的日期。


getDateFromISO(iso_string: string): string | Date {


    if (!iso_string)

        return null;



    const isIsoDate = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/.test(iso_string); // check if string is in format 2022-01-01T00:00:00.000Z

    const isDateTimeWithoutZone = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(iso_string); // check if string is in format 2022-01-01T00:00:00

    const isDateYMD = /\d{4}-\d{2}-\d{2}/.test(iso_string); // check if string is in format 2022-01-01


    if (!isIsoDate && isDateTimeWithoutZone)

        iso_string += '.000Z';

    else if (!isIsoDate && isDateYMD)

        iso_string += 'T00:00:00.000Z';

    else if (isIsoDate)

        iso_string = iso_string;

    else

        return iso_string;



    const dateFromServer = new Date(iso_string);

    const localOffset = new Date().getTimezoneOffset(); // in minutes

    const localOffsetMillis = 60 * 1000 * localOffset;

    const localDate = new Date(dateFromServer.getTime() + localOffsetMillis);


    return localDate;


 }


查看完整回答
反对 回复 2023-06-09
  • 2 回答
  • 0 关注
  • 134 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信