是否有可靠的方法从客户端浏览器获取时区?我看到了以下链接,但我想要一个更强大的解决方案。
使用JavaScript自动检测时区
JavaScript中的时区检测
五年之后,我们有了一个内置的方法!对于现代浏览器,我会使用:
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tz);
返回IANA时区字符串,但不返回偏移量。在MDN参考中了解更多信息。
兼容性表-截至2019年3月,适用于全球90%的浏览器。不支持ie浏览器
通常当人们寻找"时区"时,只需"UTC偏移量"就足够了。。例如,他们的服务器使用UTC+5,他们想知道他们的客户端使用UTC-8。
在普通的旧javascript中,(new Date()).getTimezoneOffset()/60
将返回当前与UTC偏移的小时数。
值得注意的是,getTimezoneOffset()
返回值(来自MDN文档)的符号中可能存在"gotcha":
时区偏移量是以分钟为单位的UTC和本地时间之间的差值。请注意,这意味着如果本地时区落后于UTC,则偏移量为正,如果超前于UTC,则偏移量为负。例如,对于时区UTC+10:00(澳大利亚东部标准时间,符拉迪沃斯托克时间,查莫罗标准时间),将返回-600。
但是,我建议您使用day.js来编写与时间/日期相关的Javascript代码。在这种情况下,您可以通过以下命令获得ISO 8601格式的UTC偏移量:
> dayjs().format("Z")
"-08:00"
值得一提的是,客户可以很容易地伪造这些信息。
(注意:这个答案最初推荐https://momentjs.com/,但dayjs是一个更现代,更小的替代方案。)
看看这个存储库页面,它很有帮助
下载jstz.min.js并在HTML页面中添加一个函数
<script language="javascript">
function getTimezoneName() {
timezone = jstz.determine()
return timezone.name();
}
</script>
并从显示标签
目前,最好的选择可能是mbayloon回答中建议的jstz。
为了完整起见,应该提到有一个标准:Intl。你可以在Chrome中看到:
> Intl.DateTimeFormat().resolvedOptions().timeZone
"America/Los_Angeles"
(这实际上并没有遵循标准,这是坚持使用库的另一个原因)
您可以使用moment-timezone来猜测时区:
> moment.tz.guess()
"America/Asuncion"
这是一个jsfield
提供当前用户时区的缩写。
下面是代码示例var tz = jstz.determine();
console.log(tz.name());
console.log(moment.tz.zone(tz.name()).abbr(new Date().getTime()));
我使用了一种与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
背后的意图是将其用作时区表(此处未提供)的键,例如下拉<select>
列表。
No。没有唯一可靠的方法,也永远不会有。你真的认为你可以信任委托人吗?