【问题标题】:get client time zone from browser [duplicate]从浏览器获取客户端时区[重复]
【发布时间】:2011-10-19 20:40:01
【问题描述】:

是否有可靠的方法从客户端浏览器获取时区?我看到了以下链接,但我想要一个更强大的解决方案。

Auto detect a time zone with JavaScript

Timezone detection in JavaScript

【问题讨论】:

  • 我写了上面链接的 jsTimezoneDetect,我对这种情况的看法是,它与纯跨浏览器 javascript(没有地理定位和 IP 查找)尽可能接近。

标签: javascript http browser timezone


【解决方案1】:

五年后,我们有了一个内置的方法! 对于现代浏览器,我会使用:

const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tz);

这将返回 IANA 时区字符串,但不返回 the offset。通过MDN reference了解更多信息。

Compatibility table - 截至 2019 年 3 月,适用于全球 90% 的浏览器。 Doesn't work on Internet Explorer.

【讨论】:

【解决方案2】:

看看这个仓库pageloom很有帮助

下载 jstz.min.js 并在你的 html 页面中添加一个函数

<script language="javascript">
    function getTimezoneName() {
        timezone = jstz.determine()
        return timezone.name();
    }
</script>

并从您的显示标签调用此函数

【讨论】:

  • TL;DR 我们现在可以按照 Wallace 的建议使用 Intl.DateTimeFormat().resolvedOptions().timeZone(无 IE11)。
【解决方案3】:

通常当人们在寻找“时区”时,“UTC 偏移量”就足够了。 例如,他们的服务器在 UTC+5 中,他们想知道他们的客户端在 UTC-8 中运行


在普通的旧 javascript 中,(new Date()).getTimezoneOffset()/60 将返回与 UTC 偏移的当前小时数。

值得注意的是,getTimezoneOffset() 返回值 (from MDN docs) 的符号中可能存在“陷阱”:

时区偏移是 UTC 和本地时间之间的差异,以分钟为单位。请注意,这意味着如果本地时区晚于 UTC,则偏移量为正,如果早于 UTC,则偏移量为负。例如,对于时区 UTC+10:00(澳大利亚东部标准时间、符拉迪沃斯托克时间、查莫罗标准时间),将返回 -600。


但是,我建议您将day.js 用于与时间/日期相关的 Javascript 代码。在这种情况下,您可以通过运行获得 ISO 8601 格式的 UTC 偏移量:

> dayjs().format("Z")
"-08:00"

值得一提的是,客户很容易伪造这些信息。

(注意:这个答案最初推荐https://momentjs.com/,但dayjs 是一个更现代、更小的替代方案。)

【讨论】:

  • 值得注意的是,偏移量和时区不一定是一回事。
  • 你将如何应用只有偏移量的 DST?在那些地区,半年的偏移量是错误的。 IMO 时区更准确。
  • 夏令时是任何给定时间偏移的一部分。冬季的中欧时间是 UTC+01:00。但是,当应用 DST 时,CET 是 UTC+02:00,就像现在在我所在的丹麦一样。
  • 在考虑夏令时时偏移不准确。
  • 我会把第一句话改成:“通常,当人们认为偏移量足够时,他们真正需要的是一个时区。前者完全忽略了夏令时,而后者则没有。”
【解决方案4】:

目前,最好的选择可能是 mbayloon's answer 中建议的 jstz。

为了完整起见,应该提到它有一个标准:Intl。您已经可以在 Chrome 中看到这一点:

> Intl.DateTimeFormat().resolvedOptions().timeZone
"America/Los_Angeles"

(这实际上并不遵循标准,这是坚持使用该库的另一个原因)

【讨论】:

  • Intl 在除 Safari 之外的所有设备中看起来都很稳定。 caniuse.com/#feat=internationalization
  • @MichaelCole Conformant 如果您在构造@987654328 时未手动指定时区,则Intl 的实现应该为timeZone 属性返回undefined @。 Chrome 通过返回系统的时区来偏离标准;这就是约翰内斯的回答所利用的,也是他说“实际上并不遵循标准”的原因。
  • 仅供参考 - 现在的标准是 Intl.DateTimeFormat().resolvedOptions().timeZone
【解决方案5】:

您可以使用moment-timezone 来猜测时区:

> moment.tz.guess()
"America/Asuncion"

【讨论】:

【解决方案6】:

这是jsfiddle

它提供了当前用户时区的缩写。

这里是代码示例

var tz = jstz.determine();
console.log(tz.name());
console.log(moment.tz.zone(tz.name()).abbr(new Date().getTime()));

【讨论】:

  • 将日期显示为May 22 2015 03:45 PM CDT 我使用了console.log(moment(now).format('MMM DD YYYY hh:mm A') + ' ' + moment.tz.zone(tz.name()).abbr(now.getTime()));
  • 您的小提琴不再工作,并且在控制台中出现错误。
【解决方案7】:

我使用了类似于the one taken by Josh Fraser 的方法,它确定了浏览器与UTC 的时间偏移量以及它是否识别DST(但从他的代码中有所简化):

var ClientTZ = {
    UTCoffset:  0,          // Browser time offset from UTC in minutes
    UTCoffsetT: '+0000S',   // Browser time offset from UTC in '±hhmmD' form
    hasDST:     false,      // Browser time observes DST

    // Determine browser's timezone and DST
    getBrowserTZ: function () {
        var self = ClientTZ;

        // Determine UTC time offset
        var now = new Date();
        var date1 = new Date(now.getFullYear(), 1-1, 1, 0, 0, 0, 0);    // Jan
        var diff1 = -date1.getTimezoneOffset();
        self.UTCoffset = diff1;

        // Determine DST use
        var date2 = new Date(now.getFullYear(), 6-1, 1, 0, 0, 0, 0);    // Jun
        var diff2 = -date2.getTimezoneOffset();
        if (diff1 != diff2) {
            self.hasDST = true;
            if (diff1 - diff2 >= 0)
                self.UTCoffset = diff2;     // East of GMT
        }

        // Convert UTC offset to ±hhmmD form
        diff2 = (diff1 < 0 ? -diff1 : diff1) / 60;
        var hr = Math.floor(diff2);
        var min = diff2 - hr;
        diff2 = hr * 100 + min * 60;
        self.UTCoffsetT = (diff1 < 0 ? '-' : '+') + (hr < 10 ? '0' : '') + diff2.toString() + (self.hasDST ? 'D' : 'S');

        return self.UTCoffset;
    }
};

// Onload
ClientTZ.getBrowserTZ();

加载后,ClientTZ.getBrowserTZ() 函数被执行,它设置:

  • ClientTZ.UTCoffset 到浏览器与 UTC 的时间偏移,以分钟为单位(例如,CST 为 -360 分钟,与 UTC 相差 -6.0 小时);
  • ClientTZ.UTCoffsetT'±hhmmD' 形式的偏移量(例如,'-0600D'),其中后缀为 D 用于 DST,S 用于标准(非 DST);
  • ClientTZ.hasDST(对或错)。

ClientTZ.UTCoffset 以分钟而不是小时提供,因为某些时区具有小数小时偏移量(例如,+0415)。

ClientTZ.UTCoffsetT 背后的意图是将其用作时区表(此处未提供)的键,例如用于下拉 &lt;select&gt; 列表。

【讨论】:

  • 如果遵守夏令时,它看起来总是会返回“D”。为什么只有五个月的差异? 1 月和 7 月肯定会更可靠地工作吗?
  • @Matt - 是的,您可以在 7 月而不是 6 月使用 7-1。我不确定这是否真的有什么不同,因为我怀疑是否存在不包括 6 月的区域 DST 计划。
【解决方案8】:

没有。没有单一可靠的方法,而且永远不会有。你真的认为你可以信任客户吗?

【讨论】:

  • 澄清:客户的时钟可能设置不正确,或者他们可能恶意试图欺骗您,让您认为他们与实际处于不同的时区。如果您要使用客户的时区,请不要将其用于任何重要的事情。
  • -1 给出了可能具有误导性的答案而不是澄清。
  • 是的,对于我的应用程序,我可以信任客户。如果客户端配置错误或有错误,那是我的用户。
  • 我实际上同意弗洛里安的观点。可靠的方法?的种类。可靠的数据?绝对不是。
  • 该问题并未说明如何使用数据。例如,它并没有说检测到的时区将永远提交给服务器。因此,如果数据纯粹在本地使用,那么关于信任的评论就无关紧要了。
猜你喜欢
  • 1970-01-01
  • 2012-09-11
  • 2022-01-13
  • 2020-02-12
  • 2018-04-11
  • 2018-11-29
  • 1970-01-01
  • 2012-01-25
相关资源
最近更新 更多