Визначте часовий пояс користувача


610

Чи існує стандартний спосіб веб-сервера мати можливість визначати часовий пояс користувача в межах веб-сторінки?

Можливо, із заголовка HTTP або частини user-agentрядка?


6
Запитайте користувача. Якщо ви отримуєте часовий пояс з комп'ютера користувача, і він встановлений неправильно, то що?
Роб Вільямс

40
Тоді користувачеві, мабуть, все одно?
agnoster

2
Ви маєте на увазі stackoverflow.com/q/1091372/218196 ?
Фелікс Клінг

2
На жаль, відповіді на це питання також дозволяють профайлювати користувача та геофігурувати.
Вільям Ентрікен

1
Чому потрібно знати часовий пояс користувача?
Брайам

Відповіді:


326
-new Date().getTimezoneOffset()/60;

Метод getTimezoneOffset() відніме ваш час від GMT і поверне кількість хвилин. Тож якщо ви живете в GMT-8, він поверне 480.

Щоб розмістити це на години, розділіть на 60. Також зауважте, що знак протилежний тому, що вам потрібно - це обчислення зміщення GMT від вашого часового поясу, а не зміщення часового поясу від GMT. Щоб виправити це, просто помножте на -1.

Також зауважте, що w3school говорить:

Повернене значення не є постійною через практику використання літнього часу.


5
Що з користувачами, які використовують стільникові телефони, які мають браузери без підтримки JavaScript? Мені подобається питання, користувач запитує про заголовки HTTP, агент користувача ... Чи є спосіб зробити цю робочу сторону якомога точнішою?
Нішал

18
Це не завжди працює для DST. Отримати зміщення часового поясу робить саме те, що йдеться. Це отримує компенсацію. Зона часу - це фактично географічна область. Це не спрацює із заощадженням денного світла, оскільки ви не знаєте, в якій півкулі живе користувач, або якщо в їх країні навіть є економія денного світла. Чому б не скористатися цим замість цього:>>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
Кейо

20
Я прошу розрізнятися з Кейо. Визначення getTimezoneOffset () (згідно стандарту ECMA ecma-international.org/ecma-262/5.1/#sec-15.9.5.26 ) - "Повертає різницю між місцевим часом та часом UTC у хвилинах". - іншими словами, він повинен враховувати економію денного світла. У документації Mozilla йдеться про те, що "літній час заважає цьому значенню бути постійним навіть для даної місцевості".
xgretsch

11
@xgretsch: Отримано поточне зміщення користувача від GMT. Це добре, якщо ви представляєте інший час, який відбувається в той же день (якщо тільки поточна дата не є датою переходу, де це може бути неправильно). Однак є багато часових поясів, які мають однаковий зміщення від GMT, і вони можуть мати різні дати переходу або не використовувати економію денного світла.
Майк Діммік

12
Тут слід зазначити одне; у деяких місцях (наприклад, Ньюфаундленд у Канаді) є часові пояси, які вимкнені на півгодини, тому після поділу на 60 ваша відповідь може бути не цілим числом.
Джейсон Уолтон

193

Найпопулярніший (== стандарт?) Спосіб визначення часового поясу, який я бачив, - це просто запитати самих користувачів. Якщо ваш веб-сайт вимагає підписки, це може бути збережено в даних профілю користувачів. Для інших користувачів дати можуть відображатися як UTC чи GMT або деякі такі.

Я не намагаюся бути розумним гаком. Просто іноді деякі проблеми мають тонші рішення поза будь-яким контекстом програмування.


5
А як щодо того, коли користувач завантажує файл .ics, який повинен мати час початку, характерне для його місцезнаходження (наприклад, 9-11 ранку по всій країні)? Вони не повинні сказати, що таке їх часовий пояс.
Marcy Sutton

33
@Ishmaeel: але користувачі подорожують на міжнародному рівні, і їм не потрібно повідомляти про свій часовий пояс щоразу, коли вони увійдуть із якогось неродного часового поясу
Rajat Gupta,

10
Це не дає відповіді на запитання, яке чітко означає, що він шукає технологічне рішення.
G-Wiz

5
@gWiz OP просить стандартне рішення. Це досить стандартно.
Саймон Берго

4
Найкращим рішенням, мабуть, буде комбінація запитів у користувача (наприклад, надання часового поясу у верхній частині звіту), а дефолт вибору, що випадає, у визначений GPS-часовим поясом, коли користувач перебуває на мобільному телефоні пристрій, що надає інформацію про місцеположення, інакше за замовчуванням встановити UTC.
Трайнко

132

Наразі немає заголовків HTTP, які б повідомляли про часовий пояс клієнтів, хоча було запропоновано включити його до специфікації HTTP.

Якби це я, я, мабуть, спробував би домогтися часового поясу за допомогою JavaScript JavaScript JavaScript, а потім подати його на сервер за допомогою Ajax або чогось іншого.


16
Як не дивно, це єдина правильна відповідь на питання, яке задає питання, як це зробити на стороні сервера. Я підозрюю, що є інші відповіді, набравши більше голосів, це те, що, як тільки ви зрозумієте, що вам потрібно це зробити клієнтом, ви в кінцевому підсумку використовуєте інші відповіді. Але ІМХО, хто виступає за іншу відповідь, повинен також підтримувати цю відповідь.
TTT

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

@MikkoRantalainen обережно під час використання проксі, оскільки вони не завжди рекламують себе в заголовках.
Матьє

@Matthieu існує кращий відповідь в даний час: stackoverflow.com/a/11836123/334451
Мікко Rantalainen

2
Це буквально єдина відповідь, яка насправді стосується поставленого питання.
lscoughlin

54

JavaScript - це найпростіший спосіб отримати місцевий час клієнта. Я б запропонував використовувати XMLHttpRequest для повернення місцевого часу, і якщо це не вдасться, повернутися до виявленого часового поясу на основі їх IP-адреси.

Що стосується геолокації, я використовував MaxMind GeoIP у кількох проектах, і він працює добре, хоча я не впевнений, чи вони надають дані часового поясу. Це послуга, яку ви платите, і вони щомісяця оновлюють вашу базу даних. Вони надають обгортки декількома веб-мовами.


Я проголосував за цю відповідь, оскільки широта і довгота, отримані з баз даних, таких як GeoIP (яка має вільну версію, доступну на даний момент), можуть поєднуватися з базами даних, які перетворюють таку координату в часовий пояс. Я думаю, що у GeoNames є остання така база даних.
Петро О.

Поточні версії (як безкоштовні, так і оплачені) баз даних / API API MaxMind дійсно надають інформацію про часовий пояс (вона повертає "Європа / Лондон" для мого часового поясу.) Я не можу пригадати, чи була стара версія їхньої системи GeoIP зробив те саме, але це працює дуже добре зараз! Поля MaxMind мають назву "time_zone", "time_zone_name".
Меттью Сліман

51

По-перше, зрозумійте, що виявлення часового поясу в JavaScript недосконале. Ви можете отримати зміщення локального часового поясу на певну дату та час, використовуючи getTimezoneOffsetпримірник Dateоб'єкта, але це не зовсім так, як повний часовий пояс IANA, якAmerica/Los_Angeles .

Є деякі варіанти, які можуть працювати:

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

Результат - рядок, що містить налаштування часового поясу IANA комп'ютера, на якому працює код.

Підтримувані середовища перераховані в таблиці сумісності Intl . Розгорніть DateTimeFormatрозділ і подивіться на функцію з назвою resolvedOptions().timeZone defaults to the host environment.

  • Деякі бібліотеки, наприклад, Luxon, використовують цей API для визначення часового поясу за допомогою таких функцій luxon.Settings.defaultZoneName.

    • Якщо вам потрібно підтримувати більш широкий набір середовищ, наприклад, старих веб-браузерів, ви можете скористатися бібліотекою, щоб зробити загальну здогадку в часовому поясі. Вони працюють, спершу спробуючи IntlAPI, якщо він доступний, а коли він недоступний, вони допитують getTimezoneOffsetфункцію Dateоб'єкта протягом декількох різних моментів часу, використовуючи результати, щоб вибрати відповідний часовий пояс із внутрішнього набору даних.

    І jsTimezoneDetect, і часовий пояс мають цю функціональність.

    // using jsTimeZoneDetect
    var tzid = jstz.determine().name();
    
    // using moment-timezone
    var tzid = moment.tz.guess();

    В обох випадках результат можна вважати лише здогадкою. Здогадка може бути правильною у багатьох випадках, але не у всіх.

    Крім того, ці бібліотеки повинні періодично оновлюватися, щоб протидіяти тому, що багато старих реалізацій JavaScript знають лише поточне правило літнього часу для свого локального часового поясу. Детальніше про це тут.

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

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


Використання географічного розташування користувача (тобто його місцевості) для виведення часового поясу також є недоліком. Користувачі можуть скористатися певним часовим поясом на своєму пристрої, який не є локальним часовим поясом, навіть думаючи, що він може відображати той самий час (чи ні). Наприклад, мандрівники часто залишають свої пристрої з часовим поясом, встановленим у звичайній місцевості, і не сподіваються побачити дати та час використання іншого зміщення без попередження. Я можу тут говорити з особистого досвіду… ;-)
RobG

Не можу сказати, чи ти мене робуєш? ;) Але жоден із цих підходів не використовує їхню локаль, а скоріше налаштування на пристрої, так що відповідає вашій точці. (Тільки альтернативний підхід, згаданий в останньому абзаці, використовує поточне місцеположення.)
Метт Джонсон-

Звернення до термінологічної примітки: "locale" - це явно не географічне положення користувача. "Локальний" - це група налаштувань, таких як мова, формат чисел, календар тощо. Наприклад, локальний файл de_DE вказує німецьку як мову за замовчуванням, євро як валюту за замовчуванням, коми як десятковий роздільник, періоди як роздільник тисяч і григоріанський як календар. Дивіться developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
azernik

49

Ось надійне рішення JavaScript для визначення часового поясу браузера.

>>> var timezone = jstz.determine();
>>> timezone.name(); 
"Europe/London"

https://bitbucket.org/pellepim/jstimezonedetect

Додаток 1: Зараз цей проект розміщено на GitHub: https://github.com/pellepim/jstimezonedetect


14
Відповіді лише на посилання відбиваються, оскільки якщо посилання зникає, відповідь перестає бути корисною; і тому, не переходячи за посиланням, читачі не знають, чи дає вона хорошу відповідь. У цьому випадку ви можете уточнити, що це стороння бібліотека, яка застосовує підхід до ідентифікації на основі бази даних, і, можливо, пояснить деякі принципи її роботи.
IMSoP

1
Це! Це шлях. Проста бібліотека, правильно обробляє DST. Інші відповіді наповнені WTF, і багато хто не роблять DST.
Дірбайо

1
Ця бібліотека дуже розумна. Він працює, запитуючи поточне зміщення до UTC, потім коригуючи час об’єкта JavaScript Дата, додаючи або віднімаючи секунди до зміщення UTC змін. За допомогою цього методу ця бібліотека з'ясовує досить багато змін DST, щоб однозначно ідентифікувати часовий пояс. Я думаю, що бібліотека могла б мати ще кращі показники, якби вона виконувала двійковий пошук замість лінійного пошуку. Повернене значення - це інформаційний ключ зони IANA (він же база даних часового поясу Олсона).
Мікко Ранталайнен

3
Ця бібліотека більше не потрібна. Сучасні браузери підтримують API Intl, який повертає рядок часового поясу IANA. Дивіться цю відповідь .
Дан Даскалеску

42

Ось більш повний спосіб.

  1. Отримайте зміщення часового поясу для користувача
  2. Випробуйте кілька днів меж літнього часу, щоб визначити, чи перебувають вони в зоні, де використовується літній режим.

Уривок наведено нижче:

function TimezoneDetect(){
    var dtDate = new Date('1/1/' + (new Date()).getUTCFullYear());
    var intOffset = 10000; //set initial offset high so it is adjusted on the first attempt
    var intMonth;
    var intHoursUtc;
    var intHours;
    var intDaysMultiplyBy;

    // Go through each month to find the lowest offset to account for DST
    for (intMonth=0;intMonth < 12;intMonth++){
        //go to the next month
        dtDate.setUTCMonth(dtDate.getUTCMonth() + 1);

        // To ignore daylight saving time look for the lowest offset.
        // Since, during DST, the clock moves forward, it'll be a bigger number.
        if (intOffset > (dtDate.getTimezoneOffset() * (-1))){
            intOffset = (dtDate.getTimezoneOffset() * (-1));
        }
    }

    return intOffset;
}

Отримання TZ та DST від JS (через Way Back Machine)


Це працювало для мене! Прочитайте коментарі під дописом блогу, щоб пару оновлень коду.
arlomedia

Це все одно поверне лише стандартний зсув для часового поясу, наприклад +02: 00. Це не дасть вам достатньо інформації для визначення часового поясу користувача, наприклад, Africa/Johannesburgабо Europe/Istanbul. Дивіться вікі тегів часового поясу .
Метт Джонсон-Пінт

32

Використовуючи підхід Unkwntech, я написав функцію за допомогою jQuery та PHP. Це перевірено і працює!

На сторінці PHP, де ви хочете мати часовий пояс як змінну, розмістіть цей фрагмент коду десь у верхній частині сторінки:

<?php
    session_start();
    $timezone = $_SESSION['time'];
?>

Це буде читати змінну сесії "час", яку ми зараз збираємося створити.

На цій же сторінці, в <head>, перш за все, потрібно включити jQuery:

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>

Також у <head> під jQuery вставте це:

<script type="text/javascript">
    $(document).ready(function() {
        if("<?php echo $timezone; ?>".length==0){
            var visitortime = new Date();
            var visitortimezone = "GMT " + -visitortime.getTimezoneOffset()/60;
            $.ajax({
                type: "GET",
                url: "http://example.org/timezone.php",
                data: 'time='+ visitortimezone,
                success: function(){
                    location.reload();
                }
            });
        }
    });
</script>

Ви можете або не помітили, але вам потрібно змінити URL-адресу на власний домен.

Одне останнє. Вам, напевно, цікаво, що це за чорт timezone.php. Ну, це просто так: (створіть новий файл під назвою timezone.php та вкажіть на нього за вказаною вище URL-адресою)

<?php
    session_start();
    $_SESSION['time'] = $_GET['time'];
?>

Якщо це працює правильно, він спочатку завантажить сторінку, виконає JavaScript і перезавантажить сторінку. Після цього ви зможете прочитати змінну часового поясу $ та використовувати її для свого задоволення! Він повертає поточне зміщення часового поясу UTC / GMT (GMT -7) або будь-який часовий пояс.


мені це подобається, але у мене може бути щось, що перевіряє поточний $ _SESSION ['time'], і лише я отримую JavaScript для перезавантаження, якщо його інше
Christopher Chase

1
Для транспортування цього файлу, напевно, простіше використовувати Cookie, ніж сесія, оскільки блокування та несеріалізація сеансу PHP може спричинити уповільнення роботи вашої програми. Для максимальної ефективності ви можете скопіювати значення в сеанс і видалити файл cookie, щоб він не надсилався в наступних запитах.
IMSoP

25

Щоб подати зміщення часового поясу у вигляді заголовка HTTP на запити AJAX за допомогою jQuery

$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        xhr.setRequestHeader("X-TZ-Offset", -new Date().getTimezoneOffset()/60);
    }
});

Ви також можете зробити щось подібне, щоб отримати фактичну назву часового поясу, скориставшись moment.tz.guess();з http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/


1
Це повертає лише поточне зміщення часового поясу - не часовий пояс . Дивіться вікі тегів часового поясу .
Метт Джонсон-Пінт

Відредаговано, щоб включити інформацію про те, як зробити те саме для назви часового поясу.
philfreo

24

Я досі не бачив детальної відповіді, яка отримує часовий пояс. Вам не потрібно геокодувати за IP-адресою або використовувати PHP (lol) або неправильно здогадуватися від компенсації.

По-перше, часовий пояс - це не просто зміщення від GMT. Це ділянка землі, в якій норми часу встановлені місцевими стандартами. Деякі країни мають економію денного світла, і вони включатимуть DST у різний час. Зазвичай важливо отримати фактичну зону, а не лише поточне зміщення.

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

Тепер, щоб отримати часовий пояс за допомогою JavaScript, ви можете скористатися цим:

>> new Date().toTimeString();
"15:46:04 GMT+1200 (New Zealand Standard Time)"
//Use some regular expression to extract the time.

Однак мені було простіше просто використовувати цей надійний плагін, який повертає часовий пояс, відформатований Olsen:

https://github.com/scottwater/jquery.detect_timezone


22

За допомогою dateфункції PHP ви отримаєте час дати сервера, на якому знаходиться сайт. Єдиний спосіб отримати час користувача - це використовувати JavaScript.

Але я пропоную вам, якщо на вашому сайті потрібна реєстрація, тоді найкращий спосіб - попросити користувача, щоб він був обов'язковим для реєстрації. Ви можете перелічити різні часові пояси на сторінці реєстру та зберегти їх у базі даних. Після цього, якщо користувач увійде на сайт, тоді ви можете встановити часовий пояс за замовчуванням для цього сеансу відповідно до обраного користувачем часового поясу.

Ви можете встановити будь-який конкретний часовий пояс за допомогою функції PHP date_default_timezone_set. Це встановлює вказаний часовий пояс для користувачів.

В основному часовий пояс користувачів переходить на сторону клієнта, тому для цього ми повинні використовувати JavaScript.

Нижче наведено сценарій, щоб отримати часовий пояс користувачів за допомогою PHP та JavaScript.

<?php
    #http://www.php.net/manual/en/timezones.php List of Time Zones
    function showclienttime()
    {
        if(!isset($_COOKIE['GMT_bias']))
        {
?>

            <script type="text/javascript">
                var Cookies = {};
                Cookies.create = function (name, value, days) {
                    if (days) {
                        var date = new Date();
                        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
                        var expires = "; expires=" + date.toGMTString();
                    }
                    else {
                        var expires = "";
                    }
                    document.cookie = name + "=" + value + expires + "; path=/";
                    this[name] = value;
                }

                var now = new Date();
                Cookies.create("GMT_bias",now.getTimezoneOffset(),1);
                window.location = "<?php echo $_SERVER['PHP_SELF'];?>";
            </script>

            <?php

        }
        else {
          $fct_clientbias = $_COOKIE['GMT_bias'];
        }

        $fct_servertimedata = gettimeofday();
        $fct_servertime = $fct_servertimedata['sec'];
        $fct_serverbias = $fct_servertimedata['minuteswest'];
        $fct_totalbias = $fct_serverbias  $fct_clientbias;
        $fct_totalbias = $fct_totalbias * 60;
        $fct_clienttimestamp = $fct_servertime + $fct_totalbias;
        $fct_time = time();
        $fct_year = strftime("%Y", $fct_clienttimestamp);
        $fct_month = strftime("%B", $fct_clienttimestamp);
        $fct_day = strftime("%d", $fct_clienttimestamp);
        $fct_hour = strftime("%I", $fct_clienttimestamp);
        $fct_minute = strftime("%M", $fct_clienttimestamp);
        $fct_second = strftime("%S", $fct_clienttimestamp);
        $fct_am_pm = strftime("%p", $fct_clienttimestamp);
        echo $fct_day.", ".$fct_month." ".$fct_year." ( ".$fct_hour.":".$fct_minute.":".$fct_second." ".$fct_am_pm." )";
    }

    showclienttime();
?>

Але, на мою точку зору, краще запитати користувачів, чи обов’язкова реєстрація у вашому проекті.


22

Не використовуйте IP-адресу для остаточного визначення місця розташування (а отже, і часового поясу) - це тому, що з NAT, проксі-серверами (все більш популярними) та VPN-адресами, IP-адреси не обов'язково реально відображають фактичне місцезнаходження користувача, але місце, у якому проживають сервери, що реалізують ці протоколи.

Подібно до того, як американські місцеві коди більше не корисні для пошуку телефонного користувача, враховуючи популярність переносу номерів.

IP-адреса та інші методи, показані вище, корисні для того, щоб запропонувати користувачеві налаштування / виправлення за замовчуванням .


21

JavaScript:

function maketimus(timestampz)
{
    var linktime = new Date(timestampz * 1000);
    var linkday = linktime.getDate();
    var freakingmonths = new Array();

    freakingmonths[0]  = "jan";
    freakingmonths[1]  = "feb";
    freakingmonths[2]  = "mar";
    freakingmonths[3]  = "apr";
    freakingmonths[4]  = "may";
    freakingmonths[5]  = "jun";
    freakingmonths[6]  = "jul";
    freakingmonths[7]  = "aug";
    freakingmonths[8]  = "sep";
    freakingmonths[9]  = "oct";
    freakingmonths[10] = "nov";
    freakingmonths[11] = "dec";

    var linkmonthnum = linktime.getMonth();
    var linkmonth = freakingmonths[linkmonthnum];
    var linkyear = linktime.getFullYear();
    var linkhour = linktime.getHours();
    var linkminute = linktime.getMinutes();

    if (linkminute < 10)
    {
        linkminute = "0" + linkminute;
    }

    var fomratedtime = linkday + linkmonth + linkyear + " " +
                       linkhour + ":" + linkminute + "h";
    return fomratedtime;
}

Просто вкажіть цю функцію у форматі часових позначок Unix; JavaScript вже знає часовий пояс користувача.

Подобається це:

PHP:

echo '<script type="text/javascript">
var eltimio = maketimus('.$unix_timestamp_ofshiz.');
document.write(eltimio);
</script><noscript>pls enable javascript</noscript>';

Це завжди показуватиме правильний час залежно від часового поясу, який людина встановила на годиннику комп'ютера. Не потрібно нікому нічого просити і зберігати на місцях, слава богу!


$ unix_timestamp_ofshiz? Щось тут не вистачає і не дуже працює, хоча це здається, що це може бути гарною відповіддю.

20

Просто, просто використовуйте функцію JavaScript getTimezoneOffsetтак:

-new Date().getTimezoneOffset()/60;

1
Це функція Javascript, а не функція PHP.
cincodenada

Крім того, він повертає лише поточне зміщення часового поясу - не часовий пояс . Дивіться вікі тегів часового поясу .
Метт Джонсон-Пінт

3
Це просто копія прийнятої відповіді, чому ви навіть голосуєте за неї.
Рамбатіно

19

Магія все, здається, в

visitortime.getTimezoneOffset()

Це здорово, я про це не знав. Чи працює це в Internet Explorer тощо? Звідти ви повинні мати можливість використовувати JavaScript в Ajax, встановлювати файли cookie, що завгодно. Я б, мабуть, пішов самим маршрутом печива.

Вам потрібно буде дозволити користувачеві його змінити. Ми намагалися використовувати геолокацію (через maxmind), щоб зробити це деякий час тому, і це було помилково досить часто - достатньо, щоб зробити це не варто, тому ми просто дозволили користувачеві встановити його у своєму профілі та показати сповіщення користувачам, які ще не встановили свої.


15

Ось стаття (із вихідним кодом), яка пояснює, як визначити та використовувати локалізований час у додатку ASP.NET (VB.NET, C #):

Це про час

Коротше кажучи, описаний підхід покладається на функцію JavaScript getTimezoneOffset, яка повертає значення, яке зберігається в файлі cookie сеансу і використовується кодовим відставанням для налаштування значень часу між GMT та місцевим часом. Приємно те, що користувачеві не потрібно вказувати часовий пояс (код робить це автоматично). Є більше залучених (саме тому я посилаюсь на статтю), але наданий код робить його дійсно простим у використанні. Я підозрюю, що ви можете перетворити логіку на PHP та інші мови (поки ви розумієте ASP.NET).


1
Посилання мертва. Я думаю, що це альтернативне посилання: devproconnections.com/article/aspnet2/it-s-about-time-122778
Gan

1
Стаття доступна і у формі PDF тут: app.box.com/shared/bfvvmidtyg
Івайло Славов

Метод перетворення часу сервера UTC на час локального клієнта, описаний у цій статті, є неправильним. Використання поточного зсуву клієнта для налаштування часу UTC на сервері призведе до неправильних "місцевих" часів протягом півроку для клієнтських локалів, які спостерігають літній час. Розглянемо цей сценарій: клієнт у Великобританії 14 січня 2013 року (GMT + 0000 Стандартний час) встановлює дату та час 21 серпня 14:00 (GMT + 0100, літній час). Це нормалізується на сервері до 21 серпня 2015 13:00 UTC. У день, коли це відбувається, компенсація клієнта дорівнює 0, тому час, відправлений назад клієнтові, буде 21 серпня 2015 13:00.
Стівен Блер

Дійсна точка, але я не стверджував, що це куленебезпечне рішення. Якщо вам потрібно реалізувати дійсно залежне від часу рішення, скажімо, заявку на бронювання квитків на поїзд, тоді вам потрібно знайти більш комплексне (і складне рішення). Однак для багатьох програм це не буде проблемою. Тому що в багатьох випадках ми хочемо локалізувати значення GMT для поточного сеансу. Тепер, якщо у вас є програма, яка потребує економії часу для деяких навіть у майбутньому, і вона не може терпіти DTS, то правильним способом було б представити можливість заощадити час безпосередньо в GMT. Якщо ви знаєте кращий варіант, будь ласка, поділіться.
Алек Девіс

14

Якщо ви використовуєте OpenID для аутентифікації, Просте розширення реєстрації вирішить проблему для аутентифікованих користувачів (Вам потрібно буде перетворити з tz в числовий).

Іншим варіантом може бути висновок про часовий пояс із переваг країни-агента користувача. Це дещо сирий метод (не працюватиме для en-US), але робить хороше наближення.


13

З JavaScript і PHP це просто:

Незважаючи на те, що користувач може возитися зі своїм внутрішнім годинником та / або часовим поясом, найкращим способом, який я знайшов поки що, отримати компенсацію, залишається new Date().getTimezoneOffset(); . Це неінвазивно, не болить головами і позбавляє від необхідності покладатися на сторонніх осіб.

Скажіть, у мене є таблиця users, яка містить полеdate_created int(13) для зберігання часових позначок Unix;

Припускаючи , що клієнт creates a new account, дані приймаються post, і мені потрібноinsert/updatedate_created column з Відмітка часу Unix клієнта, а на серверах.

Оскільки timezoneOffset потрібен під час вставки / оновлення, він передається як додатковий елемент $ _POST, коли клієнт подає форму, тим самим усуваючи необхідність зберігати її в сесіях та / або кукі, а також додаткові сервери не звертаються.

var off = (-new Date().getTimezoneOffset()/60).toString();//note the '-' in front which makes it return positive for negative offsets and negative for positive offsets
var tzo = off == '0' ? 'GMT' : off.indexOf('-') > -1 ? 'GMT'+off : 'GMT+'+off;

Скажіть, сервер отримує tzoяк $_POST['tzo'];

$ts = new DateTime('now', new DateTimeZone($_POST['tzo']);
$user_time = $ts->format("F j, Y, g:i a");//will return the users current time in readable format, regardless of whether date_default_timezone() is set or not.
$user_timestamp = strtotime($user_time);

Вставити / оновити date_created=$user_timestamp .

Отримавши дата_create, ви можете конвертувати часову позначку так:

$date_created = // Get from the database
$created = date("F j, Y, g:i a",$date_created); // Return it to the user or whatever

Тепер цей приклад може відповідати потребам, якщо мова йде про вставку firstчасової позначки ... Якщо мова заходить про додаткову часову позначку або таблицю, ви можете розглянути можливість вставлення значення tzo в таблицю користувачів для подальшого ознайомлення або встановлення його як сеанс або як cookie.

PS АЛЕ що робити, якщо користувач подорожує та перемикає часові пояси. Увійдіть у систему GMT + 4, швидко переходите до GMT-1 та знову входите в систему. Останнє вхід буде в майбутньому.

Я думаю ... ми занадто багато думаємо.


13

Ви можете зробити це на клієнті з моментним часовим поясом і надіслати значення серверу; використання вибірки:

> moment.tz.guess()
"America/Asuncion"

5
Назва функції розповідає все про її точність ;-)
Легенди

В даний час, moment.js я вже не рекомендую. Наразі є набагато менші альтернативи ( dayjs , date-fns ). Момент величезний .
Дан Даскалеску

11

Отримання дійсного імені часового поясу бази даних TZ в PHP - це двоетапний процес:

  1. За допомогою JavaScript можна змістити часовий пояс за кілька хвилин getTimezoneOffset. Це зміщення буде позитивним, якщо місцевий часовий пояс відстає від UTC і негативним, якщо воно попереду. Отже, ви повинні додати протилежний знак до зміщення.

    var timezone_offset_minutes = new Date().getTimezoneOffset();
    timezone_offset_minutes = timezone_offset_minutes == 0 ? 0 : -timezone_offset_minutes;

    Передайте це зміщення PHP.

  2. У PHP конвертуйте це зміщення у дійсне ім'я часового поясу з функцією timezone_name_from_abbr .

    // Just an example.
    $timezone_offset_minutes = -360;  // $_GET['timezone_offset_minutes']
    
    // Convert minutes to seconds
    $timezone_name = timezone_name_from_abbr("", $timezone_offset_minutes*60, false);
    
    // America/Chicago
    echo $timezone_name;</code></pre>

Я написав повідомлення про це в блозі: Як виявити часовий пояс користувача в PHP . Він також містить демонстраційну версію.


1
Я думаю, що більш простий процес - це зателефонувати Intl.DateTimeFormat().resolvedOptions().timeZoneта відправити його на веб-сервер. Посилання: stackoverflow.com/questions/9772955/…
Майкл Цанг

9

Простий спосіб зробити це за допомогою:

new Date().getTimezoneOffset();

8
Чому ти переклав ідентичну відповідь (Джон Ісаакс) від 2 років тому: stackoverflow.com/a/1809974/836407 ?
човен

2
Крім того, він повертає лише поточне зміщення часового поясу - не часовий пояс . Дивіться вікі тегів часового поясу .
Метт Джонсон-Пінт

8

Одним із можливих варіантів є використання Dateполя заголовка, яке визначено в RFC 7231 і, як передбачається, включає часовий пояс. Звичайно, не гарантується, що це дійсно часовий пояс клієнта, але це може бути зручною відправною точкою.


1
На жаль, цей заголовок, здається, в основному розроблений для відповідей, а не запитів: "Агент користувача МОЖЕ надсилати поле заголовка Дата у запиті, хоча, як правило, цього не зробить, якщо не вважається, що він передає корисну інформацію серверу." Я щойно перевірив, і Firefox не надсилає його.
IMSoP

8

Ось як я це роблю. Це встановить часовий пояс PHP за замовчуванням для місцевого часового поясу користувача. Просто вставте наступне вгорі всіх сторінок:

<?php
session_start();

if(!isset($_SESSION['timezone']))
{
    if(!isset($_REQUEST['offset']))
    {
    ?>
        <script>
        var d = new Date()
        var offset= -d.getTimezoneOffset()/60;
        location.href = "<?php echo $_SERVER['PHP_SELF']; ?>?offset="+offset;
        </script>
        <?php   
    }
    else
    {
        $zonelist = array('Kwajalein' => -12.00, 'Pacific/Midway' => -11.00, 'Pacific/Honolulu' => -10.00, 'America/Anchorage' => -9.00, 'America/Los_Angeles' => -8.00, 'America/Denver' => -7.00, 'America/Tegucigalpa' => -6.00, 'America/New_York' => -5.00, 'America/Caracas' => -4.30, 'America/Halifax' => -4.00, 'America/St_Johns' => -3.30, 'America/Argentina/Buenos_Aires' => -3.00, 'America/Sao_Paulo' => -3.00, 'Atlantic/South_Georgia' => -2.00, 'Atlantic/Azores' => -1.00, 'Europe/Dublin' => 0, 'Europe/Belgrade' => 1.00, 'Europe/Minsk' => 2.00, 'Asia/Kuwait' => 3.00, 'Asia/Tehran' => 3.30, 'Asia/Muscat' => 4.00, 'Asia/Yekaterinburg' => 5.00, 'Asia/Kolkata' => 5.30, 'Asia/Katmandu' => 5.45, 'Asia/Dhaka' => 6.00, 'Asia/Rangoon' => 6.30, 'Asia/Krasnoyarsk' => 7.00, 'Asia/Brunei' => 8.00, 'Asia/Seoul' => 9.00, 'Australia/Darwin' => 9.30, 'Australia/Canberra' => 10.00, 'Asia/Magadan' => 11.00, 'Pacific/Fiji' => 12.00, 'Pacific/Tongatapu' => 13.00);
        $index = array_keys($zonelist, $_REQUEST['offset']);
        $_SESSION['timezone'] = $index[0];
    }
}

date_default_timezone_set($_SESSION['timezone']);

//rest of your code goes here
?>

1
Це не враховує коригування літнього часу - користувач у Дубліні буде відповідати вашому "Європа / Дублін" взимку, а "Європа / Белград" влітку. Якщо ви збираєтеся використовувати поточне зміщення, все, що ви можете обґрунтовано припустити, - це зміщення, а не географічний ідентифікатор.
IMSoP

8

Спробуйте цей PHP-код:

<?php
    $ip = $_SERVER['REMOTE_ADDR'];
    $json = file_get_contents("http://api.easyjquery.com/ips/?ip=" . $ip . "&full=true");
    $json = json_decode($json,true);
    $timezone = $json['LocalTimeZone'];
?>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.