【问题标题】:convert date based on timezone user is in根据用户所在的时区转换日期
【发布时间】:2019-09-14 03:56:39
【问题描述】:

我想根据他们的时区转换一个日期。

例如,我想设置为 EST 时间 (America/New_York)

2019-04-24 12:00:00

如果用户从 America/Los_Angeles 访问该站点,它将显示:

2019-04-24 09:00:00

我需要能够返回小时,因此在该示例中:9。

我尝试使用https://github.com/iansinnott/jstz 来确定他们的时区,并尝试使用https://moment.github.io/luxon 来处理转换而没有任何运气。

我正在通过更改计算机上的时区进行测试,但运气不佳。

【问题讨论】:

  • JavaScript Date 对象不会根据客户端的时区进行时区转换吗..?
  • new Date().getHours() 已经这样做了。
  • 您问题的第一部分是询问如何从代表特定时区(即“America/New_York”)的日期时间字符串创建Date 实例吗?关于您问题的第二部分,许多 JavaScript Date 方法(如 getHours())会在本地时间自动返回值,您是否在寻找其他行为?
  • 你为什么不使用 NTP api。网络时间协议,这将始终返回来自用户在其设备中使用的网络的时间,例如来自互联网服务提供商或设备中的 SIM 卡!!!!看一看; ntpjs.org
  • 使用 NTP 的原因如下:用户可能会通过更改设备日期和时间来欺骗应用程序,但 NTP 会为用户的特定位置从服务器提供 TIME 日期:) 干杯

标签: javascript timezone


【解决方案1】:

我认为这个问题可能需要进一步澄清 - 我的第一印象是您指的是您已经拥有并从服务器提供的日期时间。这个问题不是归结为 Date 对象是“用户时区感知”的吗?或不?但它是(确切地说,有些方法是)

您的日期/时间是 2019-04-24 12:00:00 EDT(我假设 P.M.) 这意味着以毫秒为单位的 Unix 时间戳是 1556121600000 (我假设 4 月是白天,所以不是纯 EST,而是 EDT 和 UTC-4:00 的偏移量)

当你打电话时

console.log(new Date(1556121600000).getHours())

对于在带有 PDT 时区的 America/Los_Angeles 的浏览器上执行的 Javascript,这不是按照您的建议返回 9 吗?

正如https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getHours 建议的那样:

getHours() 方法返回指定日期的小时数, 以当地时间为准。

【讨论】:

  • 虽然它本身是正确的,但这不是所要求的。 OP 没有提供 Unix 时间戳,或任何包含与 UTC 的偏移量的输入。他们要求将特定时区转换为用户的本地时间。
  • 此外,Date 对象不支持时区,但它具有一些使用本地时区的功能(用于输入和输出)。在您的示例中,Date 对象内部保留的唯一内容是1556121600000。在传递结果之前应用本地时区的是 getHours 调用。
  • 更新了答案以反映某些方法,而是“时区感知”。我使用 Unix 时间戳和 UTC 偏移量作为参考来正确放置我的示例,以支持全球存在 1556121600000 时刻并且只有其表示不同的想法——有时它可能有助于“脱离时区”心态”;这就是“输入”的来源:如果用户选择输入日期/时间,那么你的答案就是那个:)但是如果程序员事先决定(并从服务器提供它或对其进行硬编码),我理解,这就是我的回答:)
【解决方案2】:

听起来您要求将从特定时区转换为用户的本地时区(无论它可能是什么)。您不需要时区检测,但目前您确实需要一个库。 (建议将toLocaleString 与时区参数一起使用的答案是不正确的,因为该函数将 转换为 特定时区,但不能转到另一个方向。)

既然你提到了Luxon,我将提供一个 Luxon 具体的答案:

luxon.DateTime.fromFormat('2019-04-24 12:00:00',       // the input string
                          'yyyy-MM-dd HH:mm:ss',       // the format of the input string
                          { zone: 'America/New_York'}) // the time zone of the input
              .toLocal()                               // convert to the user's local time
              .toFormat('yyyy-MM-dd HH:mm:ss')         // return a string in the same format

//=>  "2019-04-24 09:00:00"

其他库也提供此功能,例如 date-fns-timezone、js-Joda 或 Moment-Timezone,但它还没有内置到 JavaScript 中。

【讨论】:

    【解决方案3】:

    可以像这样根据时间转换日期。参考convert date to another time zone下的例子sn-p。

    var usaTime = new Date().toLocaleString("en-US", {timeZone: "America/New_York"});
    usaTime = new Date(usaTime);
    console.log('USA time: '+usaTime.toLocaleString())
    
    
    var usaTime = new Date().toLocaleString("en-US", {timeZone: "America/Los_Angeles"});
    usaTime = new Date(usaTime);
    console.log('USA time: '+usaTime.toLocaleString())

    【讨论】:

    • Nooo.... 你不能只获取toLocaleString 的输出并将其传递回Date 构造函数。这是自找麻烦... Date 字符串解析器不需要接受特定于区域设置的格式,并且输入将被视为在 local 时区中。不要这样做。
    • 这是一个更好的解决方案。即使不使用库,也可以满足要求。
    • @MattJohnson 告诉我为什么这是自找麻烦并告诉我为什么不需要日期字符串解析器来接受本地特定格式?
    • @SachinthaNayanajith 据我在developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 看到的,当您从字符串构造日期时,该字符串必须是符合 IETF 的 RFC 2822 时间戳或 ISO8601 版本。从developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 看来, toLocaleString() 的格式似乎没有受到相同的限制 - 这可能是偶然的吗?
    • 正确。提供的链接上的注释解释了原因。超出规范的任何内容都取决于实现,并且在实现之间可能会有很大差异。此外,上面代码中的第二行和第三行也没有任何意义。第一行很好,并且已经有了转换后的输出。但是,它没有回答所提出的问题,因为这是将 from 本地时间转换为给定时区,OP 询问如何在相反的时区进行转换方向。
    【解决方案4】:

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString

    var date = new Date(Date.UTC(2012, 11, 12, 3, 0, 0));
    
    // toLocaleString() without arguments depends on the implementation,
    // the default locale, and the default time zone
    console.log(date.toLocaleString());
    // → "12/11/2012, 7:00:00 PM" if run in en-US locale with time zone America/Los_Angeles
    

    或者您可以使用getYear、getMonth、getDate、getHours、getMinutes、getSeconds 来格式化您自己的日期表示。这些方法都根据用户的本地时区返回值。

    【讨论】:

    • 这会将 UTC 转换为本地时间。这不是被问到的。
    【解决方案5】:

    您可以保留一个 timzeone 标识符列表以及它们相对于您的本地时间的对应 +/- 小时数列表(由您的时间函数返回)。

    一旦您有了用户的时区,并且您从本地时间戳中提取了当前小时,只需在列表中查找时区并使用它的索引来访问第二个列表,以查找要添加或减去的小时数用户时间。

    【讨论】:

    猜你喜欢
    • 2019-06-15
    • 2020-07-18
    • 2022-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-17
    • 2012-08-18
    • 1970-01-01
    相关资源
    最近更新 更多