【问题标题】:JavaScript Date() - getting / offsetting multiple timezonesJavaScript Date() - 获取/偏移多个时区
【发布时间】:2019-11-16 03:02:09
【问题描述】:

我不是 js 的菜鸟,但还没有做大量的日期工作。

我需要在三个 GMT 时区(偏移 +5:30、+7、+8)中获取“现在”,我很困惑var now = new Date(); 是否会是世界任何地方的本地“现在” ,或者我是否需要为每个时区计算一个单独的“现在”来根据 GMT 或 UTC 进行评估。

然后我需要将“现在”变量与这三个时区中的日期(2019 年 11 月 19 日上午 10:00)进行比较。例如,

let now = new Date();
let presale530 = new Date('11-19-2019 10:00 AM GMT+5:30'); // Bangalore
if (now > presale530) {
  // start the presale in Bangalore
}

以上需要在不同的时区同时发生:

let now = new Date();
let presale7 = new Date('11-19-2019 10:00 AM GMT+7'); // Jakarta
if (now > presale7) {
  // start the presale in Jakarta
}

【问题讨论】:

    标签: javascript date


    【解决方案1】:

    new Date() 返回浏览器指定时区的日期和时间。 编辑:正如 RobG 所指出的,这是错误的。 new Date() 返回一个带有实际 UTC 时间的对象。像toString() 这样的方法或普通的get 方法取决于浏览器/系统。每个浏览器的行为不同,有些在设置中,有些从系统时区继承。

    所以这取决于您的业务逻辑。看起来您的目标是不同的位置,因此假设用户不篡改他们的设备/浏览器时区并让他们设置到他们所在的任何位置,您的 now 将正常工作。如果您有一些其他代码可以通过 ip 确定他们的位置,然后将相应的代码提供给该区域,而不是依赖他们的浏览器/系统设置,那么您的 now 将不够用。请改用Date().getTime() 来获取绝对纪元时间,然后将其格式化为您想要的时区。

    所以这取决于你是否信任用户,以及你是否有更好的方法来定位用户并提供适当的代码。

    编辑: 重新查看您的问题后,您似乎正在为 3 个单独的页面编写 3 组代码。我假设您有一个后端检测 ip 并为 3 个不同的站点提供服务,可能使用不同的 .us、.ca、.cn 等。

    在这种情况下,您会希望每个网站同时开始预售,而不是依赖于浏览器/计算机设置。这是您必须澄清的业务逻辑。如果是这种情况,最好使用getTime() 并将其格式化为您希望比较的时区。

    【讨论】:

    • 你是对的。是的,它返回带有 UTC 时间的对象。返回本地值的是常见的 get 方法。 getTime() 将返回 UTC 时间。感谢您的澄清。
    • 这是我在说出你的答案之前拼凑起来的。这行得通吗? jsfiddle.net/kirkbross/xke09j1y/23。如果我手动更改日期,它可以在这里工作,但我需要 100% 确定这些日期会在指定时间在这些时区启动和关闭。
    【解决方案2】:

    我对 var now = new Date(); 是否感到困惑将是世界上任何地方的本地“现在”,还是我需要为每个时区计算一个单独的“现在”以根据 GMT 或 UTC 进行评估。

    日期为 UTC,因此无论本地偏移量如何,“现在”都是相同的,但需要注意必须正确设置系统时钟。系统时区偏移仅用于假定本地值的情况(普通 set 方法、解析没有偏移的字符串等)。

    Date.prototype.toString 根据主机系统时区偏移返回一个字符串,而普通的 get 方法返回本地值。

    getUTC 方法返回 UTC 值,并且无论主机系统设置如何,都应该相同(与上述相同的警告)。

    但是,如果您有一个像“2019 年 11 月 19 日 10:00 AM”这样没有时区偏移的字符串,那么您必须手动解析并应用偏移(编写您自己的函数或使用库)。

    例如将“2019 年 11 月 19 日上午 10:00”等字符串解析为 UTC 并应用 +05:30 等时区偏移量的函数是:

    /* Parse string in format MMMM DD, YYYY hh:mm a as UTC and apply
    ** a timezone offset in format +/-HH:mm)
    **
    ** @param {string} s - string to parse
    ** @param {string} offset - +/-HH:mm default '+00:00'
    ** @returns {Date}
    */
    function myParse(s, offset = '+00:00') {
      let months = ['jan','feb','mar','apr','may','jun',
                    'jul','aug','sep','oct','nov','dec'];
      let b = s.split(/[ ,:]+/);
      let m = months.indexOf(b[0].toLowerCase().substr(0,3));
      let hr = +b[3];
      let min = +b[4];
      let ap = b[5];
      hr = (hr % 12) + (ap.toLowerCase() == 'am'? 0 : 12);
    
      // Get hr and min of timezone offset with sign
      let c = offset.split(':');
      let oSign = c[0] < 0? '-' : '+';
      let oHr = +c[0]
      let oMin = c[1] * (oSign == '-'? -1 : 1);
    
      // Create date using values as UTC, apply offset
      return new Date(Date.UTC(b[2], m, b[1], hr + oHr, min + oMin)); 
    }
    
    // +00:00 - i.e. UTC
    console.log(myParse("November 19, 2019 10:00 AM"));
    // +05:30
    console.log(myParse("November 19, 2019 10:00 AM", '+05:30'));
    // -07:00
    console.log(myParse("November 19, 2019 12:00 AM", '-07:00'));
    // Difference in dates is 12:30, which is the difference in timezone offsets

    但是,如果您需要执行其他日期运算或支持不同的格式,那么库可能会有所帮助。

    【讨论】:

    • 这是我在说出你的答案之前拼凑起来的。这会奏效吗? jsfiddle.net/kirkbross/xke09j1y/23。如果我手动更改日期,它可以在这里工作,但我需要 100% 确定这些日期会在指定时间在这些时区启动和关闭。
    • @KirkRoss——如果您还有其他问题,请在另一篇文章中提出。 new Date('11-19-2019 10:00 AM GMT+5:30') 在我测试的第一个浏览器中生成无效日期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    • 2014-02-15
    • 2014-01-09
    • 1970-01-01
    • 2010-11-06
    相关资源
    最近更新 更多