在不使用字符串的情况下在 javascript 中获取另一个时区的时区偏移量

Posted

技术标签:

【中文标题】在不使用字符串的情况下在 javascript 中获取另一个时区的时区偏移量【英文标题】:get timezone offset of another timezone in javascript without using Strings 【发布时间】:2016-06-23 15:15:16 【问题描述】:

我想计算从“用户时间”到“WET/WEST”的偏移量。

我用新的Date().getTimezoneOffset() 获得用户偏移量。

但是如何获得 WET/WEST 的偏移量,以便计算两者的组合偏移量?

例如,如果用户处于欧洲中部时间 (CET/CEST),则在冬季,组合偏移量将为 -60 (CET) + 0 (WET) = -60。在夏天,它将是 -120 (CEST) + 60 (WEST) = -60。在这种情况下,它始终为 -60,但用户也可以有一个没有 DST 的时区。

如果不将其格式化为字符串并从该字符串中读出新时区,这是否可能?

【问题讨论】:

由于 Date 对象的核心是 UTC,您可以忽略本地时区,只需将您喜欢的任何偏移量应用于 UTC 部分,然后读取新的 UTC 值。您无法从Date.prototype.toString 的结果中可靠地读取时区,因为它依赖于实现。时区可能缺失、不明确或无法辨认。 但是我在哪里可以获得 WET 的偏移量?我正在寻找类似 new Timezone("WET").getOffset 为此,您需要构建自己的实用程序,可能基于广泛使用的IANA timezone database。我认为不需要构造函数,时区是与 UTC 有偏移的简单事物,所以 myDateLib.getTimezoneOffset('WET')myDateLib.getTimezoneOffset('LHDT')myDateLib.getTimezoneOffset('Australia/Lord_Howe') 【参考方案1】:

您不能可靠地使用时区缩写进行输入,因为它们可以以多种不同的方式进行解释。例如,CST 可能是北美的“中部标准时间”、“中国标准时间”或“古巴标准时间”。虽然WETWEST 等一些缩写是独一无二的,但很多都是模棱两可的。参考the list of time zone abbreviations here。

相反,您需要知道 IANA 时区标识符。 that uses WET/WEST 的一个位置是葡萄牙,它是 "Europe/Lisbon" 的 IANA 标识符。您可以找到标识符列表here。选择正确的标识符很重要,因为时区会随着时间而变化。每个标识符都反映了每个地区的特定历史。

如果您知道 IANA 时区标识符,那么您可以选择如何使用它:

    在一些完全支持ECMAScript Internationalization API (ECMA-402) 的时区功能的现代浏览器中,您可以执行以下操作:

    var d = new Date();
    var s = d.toLocaleString(undefined,  timeZone: "Europe/Lisbon" )
    

    这将在格式化期间将提供的日期和时间转换为正确的时区。在第一个参数中传递undefined 将使用当前语言环境进行格式化。

    这种方法有一些缺点,因为它尚未在所有浏览器中实现,并且没有用于仅检索特定时间点的原始时区偏移量的 API。

    您可以考虑使用实现此功能的库。 I list several of them here。我个人偏好moment.js 和moment-timezone 插件,您可以执行以下操作:

    var m = moment.tz("Europe/Lisbon");
    var s = m.format();
    

    您可以将参数传递给format 方法以显示您喜欢的输出。您还可以转换现有时间,例如:

    var m = moment.utc("2016-01-01T00:00:00").tz("Europe/Lisbon");
    var s = m.format();
    

    您还可以像这样获取特定时刻的偏移量:

    var m = moment.utc("2016-01-01T00:00:00").tz("Europe/Lisbon");
    var offsetInMinutes = m.utcOffset();
    var offsetAsString = m.format("Z");
    

    您可以编写自己的代码来处理特定时区。虽然这很容易出错,但我通常不推荐它。如果您沿着这条路走,更新可能会特别困难。

还请记住,特定时区的偏移量会因生效日期和时间而异。因此,代表“现在”的new Date() 不一定总是正确的输入,具体取决于您的情况。

【讨论】:

关于#1。好的,所以我可以将给定的日期更改为特定的时区。但是我(和操作员)想要计算用户当前时区和任意时区之间的时区差异。所以在你的例子中:ds 之间有什么区别(以小时、秒或其他为单位)?【参考方案2】:

我想在不使用库的情况下做到这一点,所以我编写了这个函数,它可以为您提供给定时区和 utc 之间的时区偏移:

function getTimezoneOffsetFrom(otherTimezone) 
    if (otherTimezone === void 0)  otherTimezone = "Europe/Amsterdam"; 
    var date = new Date();
    function objFromStr(str) 
        var array = str.replace(":", " ").split(" ");
        return 
            day: parseInt(array[0]),
            hour: parseInt(array[1]),
            minute: parseInt(array[2])
        ;
    
    var str = date.toLocaleString(['nl-NL'],  timeZone: otherTimezone, day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: false );
    var other = objFromStr(str);
    str = date.toLocaleString(['nl-NL'],  day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: false );
    var myLocale = objFromStr(str);
    var amsterdamOffset = (other.day * 24 * 60) + (other.hour * 60) + (other.minute);
    var myLocaleOffset = (myLocale.day * 24 * 60) + (myLocale.hour * 60) + (myLocale.minute);
    return myLocaleOffset - amsterdamOffset + date.getTimezoneOffset();

也许可以通过使用 en-US 作为语言环境字符串来批准它,然后 str.replace 可能需要过滤逗号或其他东西。

【讨论】:

【参考方案3】:

我也想没有图书馆,但即使它有固定数量的时区数据,所以如果你不继续更新,30 年后就会中断,只是让我有点恼火。虽然这确实使用了字符串,但没有什么比解析一个只是数字的字符串更复杂了

function getTimezoneOffset(dt, timezone) 

     let getItem = function(format) 
         format.timeZone = timezone;
         return parseInt(dt.toLocaleString(
            'en-US', format));
     ;
    
     let adjDate = new Date(
        getItem(year: 'numeric'),
        getItem(month: 'numeric') - 1, // months are zero based
        getItem(day: 'numeric'),
        getItem(hour: 'numeric',hour12: false),
        getItem(minute: 'numeric'));
     let noSecs = new Date(dt.getTime());
     noSecs.setSeconds(0, 0);
     let diff = Math.round((adjDate.getTime() - noSecs.getTime()) / 60000);
    
     return dt.getTimezoneOffset() - diff;
    

【讨论】:

以上是关于在不使用字符串的情况下在 javascript 中获取另一个时区的时区偏移量的主要内容,如果未能解决你的问题,请参考以下文章

有啥方法可以在不使用 getImageData() 的情况下在 JavaScript 中找到像素的颜色?

有没有办法在不使用画布的情况下在 JavaScript 中合并图像?

如何在不解析的情况下在javascript中同步包含JSON数据?

如何在不使用 JSON.stringify 或 JSON.parse 的情况下在 javascript 中克隆数组? [复制]

如何在不点击链接的情况下在 javascript 中打开新页面

jquery 或 javascript 中有没有一种方法可以在不使用 ajax 请求的情况下在页面加载时填充下拉列表?