Answers:
半年后,我们有了内置的方法!对于现代浏览器,我将使用:
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tz);
这将返回IANA时区字符串,但不会返回offset。在MDN参考中了解更多信息。
兼容性表 -截至2019年3月,适用于全球90%使用的浏览器。在Internet Explorer上不起作用。
Intl.DateTimeFormat().resolvedOptions().timeZone
->undefined
Intl.DateTimeFormat().resolvedOptions().timeZone
将从Firefox 52开始返回期望值:kangax.github.io/compat-table/esintl/…–
人们在寻找“时区”时,通常只需“ 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是更现代,更小的选择。)
就目前而言,最好的选择可能是mbayloon的答案中建议的jstz。
为了完整起见,应该提到的是有一个标准:Intl。您已经可以在Chrome浏览器中看到此内容:
> Intl.DateTimeFormat().resolvedOptions().timeZone
"America/Los_Angeles"
(这实际上并没有遵循标准,这是坚持使用该库的又一个原因)
Intl
应返回undefined
该timeZone
属性DateTimeFormat
。Chrome会通过返回系统时区来偏离标准。这就是约翰内斯的答案所利用的,也是他为什么说“实际上并没有遵循标准”的原因。
您可以使用moment-timezone猜测时区:
> moment.tz.guess()
"America/Asuncion"
这是一个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()));
我使用的方法与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'
D
S
ClientTZ.hasDST
(对或错)。ClientTZ.UTCoffset
以分钟而不是小时的形式提供,因为某些时区的小时偏移量很小(例如+0415)。
其背后的目的ClientTZ.UTCoffsetT
是将其用作时区表(此处未提供)的键,例如用于下拉<select>
列表。
7-1
7月而不是6月。我不确定是否真的有什么不同,因为我怀疑有些地区的DST计划不包括6月。
不,没有单一的可靠方法,也永远不会有。您真的认为您可以信任客户吗?