Получение смещения часового пояса клиента в JavaScript

616

Как я могу собрать информацию о часовом поясе посетителя? Мне нужен часовой пояс, а также часы смещения по Гринвичу.

Árvíztűrő tükörfúrógép
источник
3
Я сейчас решаю ту же проблему. Вот интересный подход.
Тамас Пап
31
Заголовок запрашивает часовой пояс, а текст запрашивает смещение по Гринвичу. Это 2 разные вещи. Часовой пояс включает информацию о летнем времени, а смещение отсутствует. Часовой пояс имеет имя и историю, смещение не имеет. Рекомендую отредактировать заголовок «Получение смещения gmt клиента в JS».
citykid
Мне нужен часовой пояс. Смещение по Гринвичу также будет полезно.
DaveWalley
9
Ответы здесь сосредоточены в основном на смещении . Для часового пояса смотрите этот ответ . См. «Часовой пояс! = Смещение» в теге часового пояса вики .
Мэтт Джонсон-Пинт
7
Вы получаете точный часовой пояс, используя этот Intl.DateTimeFormat (). ResolvedOptions (). TimeZone
Mangesh Mandavgane

Ответы:

594

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

Смещение часового пояса - это разница в минутах между UTC и местным временем. Обратите внимание, что это означает, что смещение является положительным, если местный часовой пояс отстает от UTC, и отрицательным, если оно впереди. Например, если ваш часовой пояс UTC + 10 (австралийское восточное стандартное время), будет возвращено -600. Летнее время не позволяет этому значению быть постоянным даже для данной локали

Обратите внимание, что не все часовые пояса смещены на целые часы: например, Ньюфаундленд - это UTC минус 3 ч 30 м (исключая летнее время из уравнения).

NickFitz
источник
42
@abernier Действует ли утверждение о getTimezoneOffsetнеточности? Статья, на которую вы ссылаетесь, датирована июнем 2007 года и не содержит подробностей о том, как эта функция является неточной. И на самом деле указанная jsTimezoneDetectвами библиотека использует getTimezoneOffsetсама себя.
Майк
5
@abernier Это стандарт, начиная с ES 1, так что я уверен, что любая проблема с реализацией может быть исправлена ​​к настоящему времени, я имею в виду, это статья 7 лет.
LasagnaAndroid
49
var hrs = -(new Date().getTimezoneOffset() / 60) чтобы получить смещение в часах, которые обычно используются
Эдвин Дэниелс
6
Кажется, это не учитывает переход на летнее время
Шахдат
21
timezone! =utc offset
bendytree
484

Использование смещения для расчета часового пояса - неправильный подход, и вы всегда будете сталкиваться с проблемами. Часовые пояса и правила перехода на летнее время могут меняться несколько раз в течение года, и сложно идти в ногу с изменениями.

Чтобы получить часовой пояс IANA системы в JavaScript, вы должны использовать

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

По состоянию на сентябрь 2019 года это работает в 95% браузеров, используемых по всему миру .

Старая информация о совместимости

ecma-402 / 1.0 говорит, что timeZoneможет быть неопределенным, если не предоставлено конструктору. Тем не менее, будущий проект (3.0) исправил эту проблему, изменив часовой пояс системы по умолчанию.

В этой версии API интернационализации ECMAScript timeZoneсвойство останется неопределенным, если timeZoneв объекте параметров, предоставленном Intl.DateTimeFormat конструктору, не было указано никакого свойства . Однако приложения не должны полагаться на это, поскольку будущие версии могут возвращать значение String, идентифицирующее текущий часовой пояс среды хоста.

в ecma-402 / 3.0, которая все еще находится в черновике

В этой версии API интернационализации ECMAScript 2015 это timeZoneсвойство будет именем часового пояса по умолчанию, если timeZoneв объекте параметров, предоставленном Intl.DateTimeFormatконструктору, свойство не было предоставлено . Предыдущая версия оставила timeZoneсвойство неопределенным в этом случае.

Павел Дубиель
источник
17
Это единственный ответ для получения часового пояса, который может понадобиться некоторым пользователям в отличие только от смещения. Итак, как обновление 2016-09, Intl работает на большинстве современных браузеров, но не на Safari. Для этого браузера есть достаточно точный запасной вариант JavaScript - pellepim.bitbucket.org/jstz
user2085368
6
Проверено, что это теперь, кажется, работает в Safari. (Использование версии 10.0)
BadPirate
2
Было бы хорошо, если бы это работало во всех современных браузерах. Однако IE11 и последний Firefox оба возвращают undefined для свойства timeZone.
17
7
Я тестировал сейчас с Chrome 58, Edge 40 и Firefox 53 - все будет работать. Он не работает с IE 11, я не тестировал Opera.
Сума
8
Мне потребовалось некоторое время, чтобы найти список часовых поясов, возвращаемых этим API. Вот оно: en.wikipedia.org/wiki/List_of_tz_database_time_zones
Ксавье Пойнас
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

Marquez
источник
4
Сломан с Chrome, так как он добавляет название часового пояса. Не используйте split.length, а вместо этого константу split[4] + " " + split[5]?!
Кристоф Русси
4
Это также не работает в (удивление, удивление) IE. Я только что сделал консольный дамп разделенного объекта Date. То же самое в Chrome, Firefox и Safari, но отличается в IE. Таким образом, вы также не можете рассчитывать на постоянные индексы. Понедельник 02.12.2013 10:22:50 GMT-0500 (EST): Chrome, FF, Safari; Пн 2 декабря 10:22:50 EST 2013:
IE10
1
Черт возьми спасибо! Я прыгал через обручи, пытаясь отобразить часовой пояс браузера ..... ew Date (). ToString (). Match (/ ([AZ] + [\ + -] [0-9] +. *) /) [ 1] было именно то, что мне было нужно!
KiwiSunGoddess
1
Это не работает Для меня splitсодержит: ["Mon", "Mar", "13", "2017", "14:05:22", "GMT-0400", "(Eastern", "Daylight", "Time)"]так что результатDaylight Time)
DLeh
7
На самом деле это не очень хорошая идея, фактическое представление времени JS после того, как вы это сделаете new Date().toString(), полностью зависит от ваших настроек локали. Ожидать, что результаты других клиентов будут напоминать ваши, - очень плохая идея.
Осьминог
71

На вопрос о том, как получить смещение в минутах в виде целого числа, уже отвечено, но в случае, если кто-то хочет локальное смещение по Гринвичу в виде строки, например "+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
Вам нужно заменить 1-е дополнение pad(parseInt(Math.abs(offset/60)), 2)на правильное ... иначе вы можете получить +5,530, как в моем случае ... я не уверен, что математический пол и т. Д. Будет лучше или нет ... но это по крайней мере дает мне +0530, как и ожидалось
Абхинав Сингх
Именно то, что я искал. Спасибо !
Codesnooker
это даст правильный результат: 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();

Обнаружение часового пояса в браузере довольно сложно сделать правильно, так как браузер предоставляет мало информации.

Момент Timezone использует Date.getTimezoneOffset()и Date.toString()на несколько моментов вокруг текущего года , чтобы собрать как можно больше информации об окружающей среде браузера , как это возможно. Затем он сравнивает эту информацию со всеми загруженными данными часового пояса и возвращает наиболее близкое совпадение. В случае связи возвращается часовой пояс с городом с наибольшим населением.

console.log(moment.tz.guess()); // America/Chicago
Самер Эк
источник
12
Это должен быть принятый ответ. Это единственный, который дает фактическое имя часового пояса, а не смещение. Помните, что смещение часового пояса может быть получено из названия, обратное неверно. Из-за летнего времени и других тонкостей, несколько часовых поясов могут иметь одинаковое смещение только в определенные дни года.
Romain G
1
Для этого сейчас есть нативное решение - Intl API . В то время, когда moment.js был отличной библиотекой того времени, в настоящее время есть гораздо меньшие альтернативы ( dayjs , date-fns ). Момент огромен ; пожалуйста, не рекомендуйте его для клиентских приложений.
Дан Даскалеску
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

Однострочник, который дает как смещение, так и часовой пояс, заключается в простом вызове toTimeString () для нового объекта Date. От 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-интерфейс Intl возвращается 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 и местным временем в минутах.

DFA
источник
9

JavaScript:

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

زياد
источник
3
Что этот ответ обеспечивает, что предыдущие ответы не имеют?
Дан Даскалеску
7

С moment.js :

moment().format('zz');
kolypto
источник
6
zи zzбыл объявлен устаревшим с 1.6.0, см. momentjs.com/docs/#/displaying/format
MrUpsidown,
3
@MrUpsidown это сейчас ZиZZ
brauliobo
4
@brauliobo Эти параметры не возвращают одно и то же. z и zz возвращают часовой пояс, например, CST, но Z и ZZ возвращают смещение, например, -0600.
Лука Спиллер
Последние док-шоу .zoneAbbr()заменили zи zz. Смотрите документацию здесь
tabish89
1
В то время, когда moment.js был отличной библиотекой того времени, в настоящее время есть гораздо меньшие альтернативы ( dayjs , date-fns ). Момент огромен ; пожалуйста, не рекомендуйте его для клиентских приложений.
Дан Даскалеску
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 был отличной библиотекой того времени, в настоящее время есть гораздо меньшие альтернативы ( dayjs , date-fns ). Момент огромен ; пожалуйста, не рекомендуйте его для клиентских приложений.
Дан Даскалеску
1
«С dayjs вы можете найти текущий часовой пояс как» не совсем точно - вы найдете только смещение, а не часовой пояс . Кроме того, Dayjs не имеет поддержки часовых поясов . Его метод .utcOffset () является простой оболочкой над нативным getTimezoneOffset().
Дан Даскалеску
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
Мирко
Да, именно так. 0,5 означает 0,5 * 30 минут. Я думаю, вы получили это, почему он дает 0,5?
Абрар
да, поэтому GMT-4.5 не является действительным
Мирко
@Mirko теперь вторая часть ответа для вас
Абрар
Если вы хотите быть более точным, используйте UTC вместо GMT, [Hilton and McCarthy 2013, p. 231-2. ], см. также в Википедии по Гринвичу - ( en.wikipedia.org/wiki/Greenwich_Mean_Time )
Том
3

Если все, что вам нужно, это сокращение часового пояса "MST" или "EST":

function getTimeZone(){
    var now = new Date().toString();
    var timeZone = now.replace(/.*[(](.*)[)].*/,'$1');//extracts the content between parenthesis
    return timeZone;
}
JohnP2
источник
Использование Date.toString()не надежно, и MDN объясняет почему. Я вставил соответствующий раздел из их документов в своем ответе .
Дан Даскалеску
3

Посмотрите, этот результирующий оператор был противоположен часовому поясу. Так что примените некоторую математическую функцию, затем подтвердите число меньше или больше.

введите описание изображения здесь

Смотрите документ MDN

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

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

console.log(res)

Prasanth
источник
1
в случае отрицательного значения, некоторые проблемы
Арун Прасад ES
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;
}

Пример: чт 21 июня 2018 18:12:50 GMT + 0530 (стандартное время Индии)

O / P: +0530

Чандракант Говда
источник
Использование Date.toString()не надежно, и MDN объясняет почему. Я вставил соответствующий раздел из их документов в своем ответе .
Дан Даскалеску
3

Попробуй это,

new Date().toString().split("GMT")[1].split(" (")[0]
Сринивасан Секар
источник
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 раза.
Дан Даскалеску
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 )

brauliobo
источник
В то время, когда moment.js был отличной библиотекой того времени, в настоящее время есть гораздо меньшие альтернативы ( dayjs , date-fns ). Момент огромен ; пожалуйста, не рекомендуйте его для клиентских приложений.
Дан Даскалеску
1

Используйте это, чтобы преобразовать OffSet в позитивное:

var offset = new Date().getTimezoneOffset();
console.log(offset);
this.timeOffSet = offset + (-2*offset);
console.log(this.timeOffSet);
Кумал Перейра
источник
-2

Я искал только 3-буквенную строку (например, «PDT») и попробовал ответ Маркеса, но мне пришлось немного подправить его для поддержки кроссбраузерности. К счастью, строка является последним потенциальным совпадением :)

Вот что я сделал в 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, например (Central European Summer Time)
jbrosi
Использование Date.toString()не надежно, и MDN объясняет почему. Я вставил соответствующий раздел из их документов в своем ответе .
Дан Даскалеску
-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>
Dayachand Patel
источник
-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())

user8066707
источник
Вот как это должно быть сделано, я думаю: на new Date(new Date().getTime()); нем будет отображаться: «Пт, 28 декабря 2018 10:15:23 GMT + 0100 (центральноевропейское стандартное время) {}»
Дармис,
-4

Это сделает работу.


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

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

не определено

SysMurff
источник