在JavaScript中获取客户端的时区偏移量


613

如何收集访问者的时区信息?我需要时区以及GMT偏移时间。


3
我现在正在解决同样的问题。这是一个有趣的方法。
塔玛斯帕普(TamásPap)2012年

31
标题要求时区,而文本要求GMT偏移量。这是两件事。时区包含有关DST的信息,但不包含utc偏移量。时区具有名称和历史记录,偏移量则没有。建议将标题编辑为“在JS中获取客户端的gmt偏移量”。
13年

我需要时区。GMT偏移量也将有所帮助。
DaveWalley 2014年

9
这里的答案主要集中在偏移量上。对于时区,请参阅此答案。请参阅时区标签Wiki “时区!=偏移” 。
马特·约翰逊品脱

7
您可以通过使用此Intl.DateTimeFormat()得到确切的时区resolvedOptions()时区。
Mangesh Mandavgane

Answers:


594

var offset = new Date().getTimezoneOffset();
console.log(offset);

时区偏移量是UTC与本地时间之间的差(以分钟为单位)。请注意,这意味着如果本地时区在UTC之后,则偏移量为正;如果在本地时区之前,则偏移量为负。例如,如果您的时区是UTC + 10(澳大利亚东部标准时间),则将返回-600。夏时制即使在给定的语言环境下也可以防止该值保持恒定

请注意,并非所有时区都可以被整个小时抵消:例如,纽芬兰是UTC减去3h 30m(将夏令时排除在外)。


42
@abernier有关getTimezoneOffset不准确性的声明是否有效?您所指的文章的日期为2007年6月,没有详细介绍该功能的准确性。实际上,jsTimezoneDetect您指向的库会使用getTimezoneOffset它自己。
Mike

5
@abernier这是ES 1以来的一个标准,所以我确定任何实现问题现在都可以解决,我的意思是,这是一篇已有7年历史的文章。
LasagnaAndroid 2014年

49
var hrs = -(new Date().getTimezoneOffset() / 60) 抵消通常使用的小时数
Edwin Daniels

6
似乎没有考虑夏令时
Shahdat

21
timezone!=utc offset
bentytree '17

480

使用偏移量来计算时区是错误的方法,并且您总是会遇到问题。一年中的时区和夏时制规则可能会多次更改,因此很难跟上这些更改。

要使用JavaScript 获取系统的IANA时区,您应该使用

console.log(Intl.DateTimeFormat().resolvedOptions().timeZone)

截至2019年9月,这可在全球95%的浏览器中使用

旧的兼容性信息

ecma-402 / 1.0说,timeZone如果未提供给构造函数,则可能未定义。但是,将来的草案(3.0)通过更改为系统默认时区来解决该问题。

在此版本的ECMAScript国际化API中,timeZone如果timeZone提供给Intl.DateTimeFormat 构造函数的options对象中未提供任何属性,则该 属性将保持未定义状态。但是,应用程序不应依赖于此,因为将来的版本可能会返回一个String值,该值标识主机环境的当前时区。

在仍处于草案中的ecma-402 / 3.0中,将其更改为

在此版本的ECMAScript 2015 Internationalization API中,timeZone如果timeZone提供给Intl.DateTimeFormat构造函数的options对象中未提供任何属性 ,则该 属性将为默认时区的名称 。timeZone在这种情况下,以前的版本使 属性未定义。


17
这是获取时区的唯一答案,某些用户可能需要时区,而不仅仅是偏移量。因此,作为2016-09年的更新,Intl适用于大多数现代浏览器,但不适用于Safari。对于该浏览器,这里有一个相当准确的javascript后备-pellepim.bitbucket.org/jstz
user2085368 2016年

6
验证现在可以在Safari中使用。(使用10.0版)
BadPirate

2
如果这在所有现代浏览器中都可以,那就太好了。但是,IE11和最新的Firefox都为timeZone属性返回未定义。
哈普罗格'17

7
我现在已经使用Chrome 58,Edge 40和Firefox 53进行了测试-可以全部使用。它不适用于IE 11,我没有测试Opera。
苏马

7
我花了一些时间才能找到此API返回的时区列表。这是:en.wikipedia.org/wiki/List_of_tz_database_time_zones
Xavier Poinas '18

123

我意识到这个答案有点离题,但我想我们中许多人正在寻找一个答案,他们也想格式化显示的时区,也许还要获得时区缩写。所以就这样...

如果您希望客户端时区格式正确,则可以依赖JavaScript Date.toString方法并执行以下操作:

var split = new Date().toString().split(" ");
var timeZoneFormatted = split[split.length - 2] + " " + split[split.length - 1];

例如,这将为您提供“ GMT-0400(EST)”,包括时区分钟(如果适用)。

或者,使用正则表达式可以提取任何所需的部分:

对于“ GMT-0400(EDT)”:

new Date().toString().match(/([A-Z]+[\+-][0-9]+.*)/)[1]

对于“ GMT-0400”:

new Date().toString().match(/([A-Z]+[\+-][0-9]+)/)[1]

仅针对“ EDT”:

new Date().toString().match(/\(([A-Za-z\s].*)\)/)[1]

对于“ -0400”:

new Date().toString().match(/([-\+][0-9]+)\s/)[1]

Date.toString参考:https : //developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/toString


4
由于Chrome附加了时区名称,因此无法使用。不要使用split.length而是使用常量来代替split[4] + " " + split[5]?!
Christophe Roussy 2013年

4
这在(惊奇的)IE中也不起作用。我只是对分割的Date对象进行了控制台转储。在Chrome,Firefox和Safari中相同,但在IE中不同。因此,您也不能指望常量索引。2013年12月2日星期一12:22:50 GMT-0500(EST):Chrome,FF,Safari;2013年EST 12月2日星期一10:22:50:IE10
adimauro

1
天哪,谢谢你!我一直在试图显示浏览器时区。....ew Date()。toString()。match(/([[AZ] + [\ +-] [0-9] +。*)/)[)[ 1]正是我所需要的!
KiwiSunGoddess 2015年

1
这行不通。对我而言split包含:["Mon", "Mar", "13", "2017", "14:05:22", "GMT-0400", "(Eastern", "Daylight", "Time)"]所以结果是Daylight Time)
DLeh

7
实际上,这不是一个好主意,在执行之后,JS时间的实际表示形式new Date().toString()完全取决于您的语言环境设置。期望其他客户的输出类似于您的输出是一个非常糟糕的主意。
章鱼,

71

已经有人回答过如何以分钟为单位获取整数偏移量,但是如果有人希望将本地GMT偏移量作为字符串使用,例如"+1130"

function pad(number, length){
    var str = "" + number
    while (str.length < length) {
        str = '0'+str
    }
    return str
}

var offset = new Date().getTimezoneOffset()
offset = ((offset<0? '+':'-')+ // Note the reversed sign!
          pad(parseInt(Math.abs(offset/60)), 2)+
          pad(Math.abs(offset%60), 2))

1
您需要用替换第一填充pad(parseInt(Math.abs(offset/60)), 2)以使其正确...否则您可能最终得到+5.530,就像我的情况...我不确定数学地板等在这里是否会更好....但这atleast给了我+0530如预期的那样
Abhinav Singh

正是我一直在寻找。谢谢 !
codenooker 2013年

这将给出正确的结果: this.pad(Math.floor((Math.abs(offset / 60)),2)
Vivek

与使用您的pad函数相比,我发现这样做更简单:offset =(offset <0?“ +”:“-”)+(“ 0000” + parseInt((Math.abs(offset / 60)))) .slice(-4)
flurbius

67

您可以使用:

时区

<script src="moment.js"></script>
<script src="moment-timezone-with-data.js"></script>

// retrieve timezone by name (i.e. "America/Chicago")
moment.tz.guess();

浏览器时区检测很难正确设置,因为浏览器提供的信息很少。

那一刻时区使用Date.getTimezoneOffset(),并Date.toString()围绕本年度时刻屈指可数收集尽可能有关浏览器的环境中尽可能多的信息。然后,它将该信息与所有加载的时区数据进行比较,并返回最接近的匹配项。如果有联系,则返回人口最多的城市所在的时区。

console.log(moment.tz.guess()); // America/Chicago

12
这应该是公认的答案。这是唯一提供实际时区名称而不是偏移量的名称。请记住,时区偏移量可以从名称派生,反之则不正确。由于DST和其他细微差别,多个时区只能在一年中的某些特定日期具有相同的偏移量。
罗曼·G

1
现在有一个本机解决方案-Intl API。虽然moment.js在当时是一个很棒的库,但是目前有更小的替代方法(dayjsdate- fns)。瞬间是巨大的 ; 请不要将其推荐给客户端应用程序。
Dan Dascalescu

43

我在项目中编写了一个函数,该函数以hh:mm格式返回时区。我希望这可以帮助某人:

function getTimeZone() {
    var offset = new Date().getTimezoneOffset(), o = Math.abs(offset);
    return (offset < 0 ? "+" : "-") + ("00" + Math.floor(o / 60)).slice(-2) + ":" + ("00" + (o % 60)).slice(-2);
}

// Outputs: +5:00

工作小提琴


1
谢谢!这就是我所需要的!
杰里米·莫里茨

15

给出偏移量和时区的单线是简单地在新的Date对象上调用toTimeString()。从MDN:

toTimeString()方法以美国人可读的形式返回Date对象的时间部分。

问题是时区不是标准的IANA格式。它比“洲/城市” IANA格式更加人性化。试试看:

console.log(new Date().toTimeString().slice(9));
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone);
console.log(new Date().getTimezoneOffset() / -60);

在加利福尼亚州,现在,toTimeString()回报Pacific Daylight Time而国际API返回America/Los_Angeles。在哥伦比亚,你会得到Colombia Standard Time,主场迎战America/Bogota

请注意,此问题的许多其他答案尝试通过调用Date.toString()获得相同的信息。正如MDN解释的那样,这种方法并不可靠:

日期实例引用特定的时间点。调用toString()将以人类可读的格式返回使用美国英语格式的日期。[...]有时需要获取时间部分的字符串;用这种toTimeString()方法可以完成这样的事情。

toTimeString()方法是特别有用的,因为实现ECMA-262标准的发动机可以从所获得的字符串中不同toString()Date对象,该格式是与实现有关的; 简单的字符串切片方法可能无法在多个引擎上产生一致的结果。


13

尝试getTimezoneOffset()Date对象:

var curdate = new Date()
var offset = curdate.getTimezoneOffset()

此方法返回以分钟为单位的时区偏移量,这是GMT与本地时间(以分钟为单位)之间的差。


9

JavaScript:

var d = new Date();
var n = d.getTimezoneOffset();
var timezone = n / -60;
console.log(timezone);


3
此答案提供了以前的答案没有提供的内容?
Dan Dascalescu

7

随着moment.js

moment().format('zz');

6
z并且zz已从1.6.0版开始弃用,请参见momentjs.com/docs/#/displaying/format
MrUpsidown 2014年

3
@MrUpsidown现在ZZZ
brauliobo

4
@brauliobo这些参数不会返回相同的值。z和zz返回时区,例如CST,但是Z和ZZ返回偏移量,例如-0600。
卡·史派勒

最新的文档显示.zoneAbbr()已替换zzz在此处
tabish89 '18

1
虽然moment.js在当时是一个很棒的库,但是目前有更小的替代方法(dayjsdate- fns)。瞬间是巨大的 ; 请不要将其推荐给客户端应用程序。
Dan Dascalescu

6

,您可以找到当前时区为

console.log(moment().utcOffset()); // (-240, -120, -60, 0, 60, 120, 240, etc.)
<script src="https://cdn.jsdelivr.net/momentjs/2.13.0/moment.min.js"></script>


,您可以找到当前时区为

console.log(dayjs().utcOffset()); // (-240, -120, -60, 0, 60, 120, 240, etc.)
<script src="https://unpkg.com/dayjs@1.8.10/dayjs.min.js"></script>

两个API均以分钟为单位返回utc偏移量。


虽然moment.js在当时是一个很棒的库,但是目前有更小的替代方法(dayjsdate- fns)。瞬间是巨大的 ; 请不要将其推荐给客户端应用程序。
Dan Dascalescu

1
“使用dayjs,您可以找到当前时区为”并不完全准确-您只会找到偏移量,而不是timezone。另外,Dayjs不支持时区。它的.utcOffset()方法是对native的简单包装getTimezoneOffset()
Dan Dascalescu

4

时区(以小时为单位)

var offset = new Date().getTimezoneOffset();
if(offset<0)
    console.log( "Your timezone is- GMT+" + (offset/-60));
else
    console.log( "Your timezone is- GMT-" + offset/60);

如果您想像评论中所说的那样精确,那么您应该尝试这样-

var offset = new Date().getTimezoneOffset();

if(offset<0)
{
    var extraZero = "";
    if(-offset%60<10)
      extraZero="0";

    console.log( "Your timezone is- GMT+" + Math.ceil(offset/-60)+":"+extraZero+(-offset%60));
}
else
{
    var extraZero = "";
    if(offset%60<10)
      extraZero="0";

    console.log( "Your timezone is- GMT-" + Math.floor(offset/60)+":"+extraZero+(offset%60));
}


不适用于非全时的时区,例如委内瑞拉,它返回GMT-4.5
Mirko

是的,这是正确的。0.5表示0.5 * 30分钟。我想你明白了,为什么它给0.5?
Abrar Jahin

是的,因此GMT-4.5不是有效的时区,它需要一些额外的解析才能变为GMT-4:30
Mirko

@Mirko现在,答案的第二部分适合您
Abrar Jahin

如果您想更精确一些,请使用UTC代替GMT,[Hilton and McCarthy 2013,p。1。231–2。],也请参见Wikipedia
GMT-

3

如果您只需要“ MST”或“ EST”时区缩写:

function getTimeZone(){
    var now = new Date().toString();
    var timeZone = now.replace(/.*[(](.*)[)].*/,'$1');//extracts the content between parenthesis
    return timeZone;
}

使用Date.toString()不可靠,MDN解释了原因。我已经在他们的答案中粘贴了他们文档中的相关部分。
Dan Dascalescu

3

看到这个结果运算符与时区相反。

在此处输入图片说明

参阅MDN文件

var a = new Date().getTimezoneOffset();

var res = -Math.round(a/60)+':'+-(a%60);
res = res < 0 ?res : '+'+res;

console.log(res)


1
万一负值,一些问题
阿伦·普拉萨德

1
为什么round呢 应该floor是不是?
Qwertiy

3
function getLocalTimeZone() {
    var dd = new Date();
    var ddStr = dd.toString();
    var ddArr = ddStr.split(' ');
    var tmznSTr = ddArr[5];
    tmznSTr = tmznSTr.substring(3, tmznSTr.length);
    return tmznSTr;
}

范例:2018年6月21日星期四18:12:50 GMT + 0530(印度标准时间)

输电话:+0530


使用Date.toString()不可靠,MDN解释了原因。我已经在他们的答案中粘贴了他们文档中的相关部分。
Dan Dascalescu


2

该值来自用户的计算机,可以随时更改,因此我认为这无关紧要,我只想获取一个近似值,然后在服务器中将其转换为GMT。

例如,我来自台湾,它为我返回“ +8”。

工作实例

JS

function timezone() {
    var offset = new Date().getTimezoneOffset();
    var minutes = Math.abs(offset);
    var hours = Math.floor(minutes / 60);
    var prefix = offset < 0 ? "+" : "-";
    return prefix+hours;
}


$('#result').html(timezone());

的HTML

<div id="result"></div>

结果

+8

2

在上,new Date(您可以获取偏移量,以获取时区名称:

new Date().toString().replace(/(.*\((.*)\).*)/, '$2');

您将获得()日期末尾之间的值,即时区的名称。


使用Date.toString()不可靠,MDN解释了原因。我已经在他们的答案中粘贴了他们文档中的相关部分。而且,这个答案已经至少给出了3次。
Dan Dascalescu

2

这是我的解决方案:


    // For time zone:
    const timeZone = /\((.*)\)/.exec(new Date().toString())[1];
    
    // Offset hours:
    const offsetHours = new Date().getTimezoneOffset() / 60;
    
    console.log(`${timeZone}, ${offsetHours}hrs`);

1

作为替代new Date().getTimezoneOffset()moment().format('zz'),你也可以使用

var offset = moment.parseZone(Date.now()).utcOffset() / 60
console.log(offset);
<script src="https://cdn.jsdelivr.net/momentjs/2.13.0/moment.min.js"></script>

jstimezone也有很多错误且无法维护(https://bitbucket.org/pellepim/jstimezonedetect/issues?status=new&status=open


虽然moment.js在当时是一个很棒的库,但是目前有更小的替代方法(dayjsdate- fns)。瞬间是巨大的 ; 请不要将其推荐给客户端应用程序。
Dan Dascalescu


-2

我只是在寻找3个字母的字符串(例如“ PDT”),并尝试了Marquez的答案,但为了进行跨浏览器支持,不得不对其进行一些调整。幸运的是,字符串是最后的潜在匹配项:)

这是我在CoffeeScript中所做的:

browserTimezone = ->
  userDate = new Date()
  zoneMatches = userDate.toString().match(/([A-Z][A-Z][A-Z])/g)
  userZone = zoneMatches[zoneMatches.length - 1]

可在IE8,IE9,Safari 9,Firefox 44和Chrome 48中使用


2
但是,有些时区有4个字母-注意:例如CEST(中欧夏令时)
jbrosi '16

使用Date.toString()不可靠,MDN解释了原因。我已经在他们的答案中粘贴了他们文档中的相关部分。
Dan Dascalescu

-3

您只需要包含moment.js和jstz.js

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstimezonedetect/1.0.6/jstz.min.js"></script>

在那之后

<script>
$(function(){
 var currentTimezone = jstz.determine();
 var timezone = currentTimezone.name();
 alert(timezone);
});

</script>

-3

这对我来说是非常好的工作:

// Translation to offset in Unix Timestamp
let timeZoneOffset = ((new Date().getTimezoneOffset())/60)*3600;

1
有什么解释吗?

-4

您可以尝试一下。它将返回您当前的机器时间

var _d = new Date(), t = 0, d = new Date(t*1000 + _d.getTime())


我认为应该这样做:new Date(new Date().getTime()); 它将显示:“ Fri Dec 28 2018 10:15:23 GMT + 0100(Central European Standard Time){}”
darmis

-4

这样就可以了。


var time = new Date(),
timestamp = Date(1000 + time.getTime());
console.log(timestamp);

Thu May 25 2017 21:35:14 GMT+0300 (IDT)

未定义

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.