从浏览器获取客户端时区

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

用 JavaScript 自动检测时区

用 JavaScript 检测时区

289969 次浏览

看看这个存储库 翻页,它很有帮助

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

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

并从显示标记调用此函数

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

目前,最好的办法可能是像 Mbaylon 的回答中建议的那样使用 jstz。

为了完整起见,应该提到的是,有一个标准正在实现之中: 英特尔。你可以在 Chrome 浏览器中看到这一点:

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

(这实际上并不符合标准,这也是坚持使用库的另一个原因)

这是 Jsfiddle

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

下面是代码示例

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

通常,当人们在寻找“时区”时,只需要“ UTC 偏移量”即可。


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

值得注意的是,在 getTimezoneOffset()返回值 (来自 MDN 文件)的符号中有一个可能的“陷阱”:

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


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

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

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

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

我使用了一种类似于 乔什 · 弗雷泽拍的那张的方法,它决定浏览器的时间偏移与 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')的偏移量,其中后缀为 DST 的 D和标准(非 DST)的 S;
  • ClientTZ.hasDST(对或错)。

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

ClientTZ.UTCoffsetT背后的意图是将它用作时区表(这里没有提供)的键,例如用于下拉式 <select>列表。

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

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

这将返回 IANA 时区字符串,但不返回 抵消

截至2019年3月,全球90% 的浏览器都可以使用。

你可以用 瞬间-时区来猜测时区:

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