从浏览器获取客户端时区


138

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

使用JavaScript自动检测时区

JavaScript中的时区检测



8
我写了jsTimezoneDetect,您链接到上面,而我的情况是,它与使用纯跨浏览器javascript(无需地理定位和IP查找)所获得的效果非常接近。
乔恩·尼兰德

Answers:


87

查看此存储库pageloom很有帮助

下载jstz.min.js并将功能添加到您的html页面

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

然后从您的显示代码调用此函数


13
TL; DR我们现在可以Intl.DateTimeFormat().resolvedOptions().timeZone按照Wallace的建议使用(不使用IE11)。
Code4R7

194

半年后,我们有了内置的方法!对于现代浏览器,我将使用:

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

这将返回IANA时区字符串,但不会返回offset。在MDN参考中了解更多信息

兼容性表 -截至2019年3月,适用于全球90%使用的浏览器。在Internet Explorer上不起作用


4
在Firefox中不起作用:Intl.DateTimeFormat().resolvedOptions().timeZone->undefined
Tomas Tomecek


5
Intl.DateTimeFormat().resolvedOptions().timeZone将从Firefox 52开始返回期望值:kangax.github.io/compat-table/esintl/…–
julen

如何使用这是一种形式?根据developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/…所建议的隐藏值?
亨德里

4
现在可以在Firefox中使用
Dustin Michels,

74

人们在寻找“时区”时,通常只需“ UTC偏移量”即可。例如,他们的服务器位于UTC + 5中,并且他们想知道其客户端正在UTC-8中运行


简而言之,旧的javascript (new Date()).getTimezoneOffset()/60会返回当前距UTC的小时数。

值得注意的是,getTimezoneOffset()返回值的符号中可能存在“陷阱” (来自MDN文档)

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


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

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

可能需要提及客户可以轻易地伪造此信息。

(注意:此答案最初建议使用https://momentjs.com/,但dayjs是更现代,更小的选择。)


30
可能值得注意的是,偏移量和时区不一定相同。
Dex 2015年

9
如何仅使用偏移量应用DST?在那些地区,半年偏移是错误的。IMO时区更准确。
Savageman

4
DST是任何给定时间的偏移量的一部分。冬季的中欧时间为UTC + 01:00。但是,当应用DST时,CET是UTC + 02:00,就像现在我在丹麦的情况一样。
GertSønderby2015年

1
这就是为什么getTimezoneOffset()需要一个截止日期的原因-它会添加到当时生效的DST中。
OsamaBinLogin

2
考虑夏时制时,偏移量不准确。
格雷格L.19年

48

就目前而言,最好的选择可能是mbayloon的答案中建议的jstz

为了完整起见,应该提到的是有一个标准:Intl。您已经可以在Chrome浏览器中看到此内容:

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

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


1
Intl在Safari之外的所有内容中看起来都很稳定。 caniuse.com/#feat=internationalization
Michael Cole

2
如果您在构造时未手动指定时区,则@MichaelCole的符合规范的实现Intl应返回undefinedtimeZone属性DateTimeFormat。Chrome会通过返回系统时区来偏离标准。这就是约翰内斯的答案所利用的,也是他为什么说“实际上并没有遵循标准”的原因。
克里斯·杰斯特·杨

19
仅供参考-现在的标准是Intl.DateTimeFormat()。resolvedOptions()。timeZone
Nederby


4

这是一个jsfiddle

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

这是代码示例

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

1
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()));
2015年

5
您的小提琴不再起作用,并且在控制台中给出了错误。
Saumil '16

2

我使用的方法与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后缀为DST和标准(非DST)形式的偏移量'±hhmmD'(例如);'-0600D'DS
  • ClientTZ.hasDST (对或错)。

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

其背后的目的ClientTZ.UTCoffsetT是将其用作时区表(此处未提供)的键,例如用于下拉<select>列表。


如果观察到夏令时,它将看起来总是返回“ D”。为什么只有五个月的差异?当然,一月和七月会更可靠吗?
马特

@Matt-是的,您可以使用7-17月而不是6月。我不确定是否真的有什么不同,因为我怀疑有些地区的DST计划不包括6月。
David R Tribble

-13

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


23
需要说明的是:客户端的时钟可能未正确设置,或者可能是在恶意欺骗您,使您认为它们与实际时区不同。如果要使用客户所在的时区,请不要将其用于重要事项。
Ryan Kinal

7
-1给出可能引起误解的答案,但未澄清。
Doug S

6
是的,对于我的应用程序,我可以信任客户。如果客户端配置错误或存在错误,则由我的用户负责。
Michael Cole 2015年

3
我实际上同意弗洛里安。可靠的方法?有点儿。可靠的数据?绝对不是。
罗布

4
问题没有说明如何使用数据。例如,它没有说检测到的时区将被提交到服务器。因此,如果仅在本地使用数据,则有关信任的说明无关紧要。
支石墓
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.