отримати часовий пояс клієнта з браузера


139

Чи є надійний спосіб отримати часовий пояс із браузера клієнта? Я бачив наступні посилання, але хочу більш надійного рішення.

Автоматичне виявлення часового поясу за допомогою JavaScript

Виявлення часового поясу в JavaScript



8
Я написав jsTimezoneDetect, на який ви посилаєтесь вище, і мій погляд на ситуацію полягає в тому, що він наближений до чистого крос-браузера JavaScript (без геолокації та IP-пошуку).
Джон Ніландер

Відповіді:


87

Подивіться на це сховище pageloom корисно

завантажте jstz.min.js і додайте функцію на вашу html-сторінку

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

і зателефонуйте на цю функцію з вашого тегу відображення


13
TL; DR Зараз ми можемо використовувати Intl.DateTimeFormat().resolvedOptions().timeZone(без IE11), як запропонував Уоллес.
Code4R7

195

Через півтора десятиліття у нас є вбудований спосіб для цього! Для сучасних браузерів я б використовував:

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

Це повертає рядок часового поясу IANA, але не зміщує . Дізнайтеся більше за посиланням MDN .

Таблиця сумісності - станом на березень 2019 року працює для 90% браузерів, які використовуються в усьому світі. Не працює в Internet Explorer .


4
не працює у firefox: Intl.DateTimeFormat().resolvedOptions().timeZone->undefined
Томаш Томечек

3
Firefox та IE, здається, не підтримують властивість :( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Wallace

5
Intl.DateTimeFormat().resolvedOptions().timeZoneповерне очікуване значення починаючи з Firefox 52: kangax.github.io/compat-table/esintl/…
червня

Як можна використовувати цю форму? У прихованому значенні, як було запропоновано developer.mozilla.org/en-US/docs/Web/HTML/Element/input/… ?
хендрі

4
Працює у Firefox зараз
Дастін Міхельс

76

Часто, коли люди шукають "часових поясів", достатньо лише "зміщення UTC". наприклад, їх сервер знаходиться в UTC + 5, і вони хочуть знати, що їх клієнт працює в UTC-8 .


У звичайному старий javascript (new Date()).getTimezoneOffset()/60поверне поточну кількість годин зміщення з UTC.

Варто відзначити можливу "готчу" в знаку getTimezoneOffset()повернутого значення (від документів MDN) :

Зсув часового поясу - це різниця в хвилинах між UTC та місцевим часом. Зауважте, що це означає, що зсув є позитивним, якщо локальний часовий пояс знаходиться за UTC і негативним, якщо він попереду. Наприклад, для часового поясу UTC + 10: 00 (австралійський східний стандартний час, Владивостокський час, стандартний час Шаморро) буде повернуто -600.


Однак я рекомендую використовувати day.js для коду Javascript, пов’язаного з часом / датою. У такому випадку ви можете отримати зміщення UTC відформатованого ISO 8601, запустивши:

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

Напевно, тут згадується, що клієнт може легко підробити цю інформацію.

(Примітка: цю відповідь спочатку рекомендували https://momentjs.com/ , але dayjs - це більш сучасна, менша альтернатива.)


30
Можливо, варто відзначити, що зміщення та часовий пояс - це не обов'язково те саме.
Dex

9
Як би ви застосували DST лише зі зміщенням? У цих районах компенсація неправильна за півроку. IMO часовий пояс є більш точним.
Савагеман

4
DST є частиною компенсації в будь-який момент часу. Центральноєвропейський час взимку - UTC + 01: 00. Однак коли DST застосовується CET - це UTC + 02: 00, як зараз у Данії, де я є.
Герт Шондербі

1
саме тому getTimezoneOffset () потрібна дата, для якої потрібно відпрацювати - вона додасть у DST, що діє на той час.
OsamaBinLogin

2
Зсув не є точним при розгляді літнього режиму.
Грег Л.

48

На даний момент найкраща ставка - це, мабуть, jstz, як це запропоновано у відповіді mbayloon .

Для повноти слід зазначити, що на цьому шляху є стандарт: Intl . Ви вже можете бачити це в Chrome:

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

(Це насправді не відповідає стандарту, що є ще однією причиною дотримуватися бібліотеки)


1
Intl виглядає стабільним у всьому, крім Safari. caniuse.com/#feat=internationalization
Майкл Коул

2
@MichaelCole Реалізації Conformant of Intlповинні повернутися undefinedдля timeZoneвластивості, якщо ви не вручну вказали часовий пояс при побудові DateTimeFormat. Chrome відхиляється від стандарту, повертаючи часовий пояс системи; це те, що Йоганнес використовує у відповіді, але також, чому він сказав, що "насправді не відповідає стандарту".
Кріс Єстер-Янг

20
FYI - тепер стандарт Intl.DateTimeFormat (). ДозвілOptions (). TimeZone
Недербі


4

Ось jsfiddle

Він надає абревіатуру поточного часового поясу користувача.

Ось зразок коду

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

1
Для відображення дати, яку 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()));
αƞjiβ

5
Ваша загадка більше не працює і дає помилки в консолі.
Saumil

2

Я використовував підхід, аналогічний тому, який застосовує Джош Фрейзер , який визначає зміщення часу браузера від 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 хвилин, що становить −6,0 годин від UTC);
  • ClientTZ.UTCoffsetTдо зміщення у формі '±hhmmD'(наприклад, '-0600D'), де суфікс призначений Dдля DST та Sдля стандартного (non-DST);
  • ClientTZ.hasDST (до істинного чи хибного).

ClientTZ.UTCoffsetНадається протягом декількох хвилин , а не годин, тому що деякі часові пояси мають дробові часові зміщення (наприклад, +0415).

Завдання ClientTZ.UTCoffsetTполягає в тому, щоб використовувати його в якості ключа в таблиці часових поясів (тут не вказано), наприклад, у спадному <select>списку.


Схоже, завжди буде повертатися "D", якщо спостерігається економія денного світла. І чому лише п'ять місяців різниці? Напевно, січень та липень працюватимуть надійніше?
Метт

@Matt - Так, ви можете використовувати 7-1липень замість червня. Я не впевнений, чи насправді це має значення, оскільки я сумніваюся, що існують регіональні схеми DST, які не включають червень.
David R

-13

Ні. Єдиного надійного способу немає і його ніколи не буде. Ви справді думали, що можете довіряти клієнту?


23
Щоб уточнити: годинник клієнта може бути встановлений неправильно, або він може зловмисно намагатися обдурити вас, думаючи, що вони знаходяться в іншому часовому поясі від фактичного. Якщо ви збираєтеся використовувати часовий пояс клієнта, не робіть цього для нічого важливого.
Райан Кінал

7
-1 за те, щоб дати потенційно оманливу відповідь і не уточнити.
Doug S

6
Так, для своєї заявки я можу довіряти клієнту. Якщо клієнт був неправильно налаштований або має помилку, це стосується моїх користувачів.
Майкл Коул

3
Я фактично згоден з Флоріаном. Надійний метод? Типу. Надійні дані? Напевно ні.
Роб

4
Питання не говорить про те, як будуть використовуватися дані. Наприклад, це не говорить про те, що виявлений часовий пояс коли-небудь буде поданий на сервер. Тож зауваження про довіру не має значення, якщо дані використовуються виключно локально.
дольмен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.