Как определить часовой пояс пользователя?

Мне нужно знать, в какой часовом поясе находятся мои пользователи, в зависимости от их IP-заголовка или http-заголовка.

У меня много ответов на эту проблему, но я не мог понять ответ. Некоторые из них используют -new Date().getTimezoneOffset()/60 (здесь). Но что это значит?

У меня есть date_default_timezone_set("Asia/Calcutta"); в корне моей страницы (index.php). Поэтому для этого я должен динамически установить часовой пояс и установить его вместо Asia/Calcutta.

Ответ 1

Подводя итог ответу Мэтта Джонсона в терминах кода:

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js">
</script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jstimezonedetect/1.0.4/jstz.min.js">
</script>
<script type="text/javascript">
  $(document).ready(function(){
    var tz = jstz.determine(); // Determines the time zone of the browser client
    var timezone = tz.name(); //'Asia/Kolhata' for Indian Time.
    $.post("url-to-function-that-handles-time-zone", {tz: timezone}, function(data) {
       //Preocess the timezone in the controller function and get
       //the confirmation value here. On success, refresh the page.
     });
  });
</script>

Ответ 2

Информация о часовом поясе браузера не является частью спецификации HTTP, поэтому вы не можете просто получить ее из заголовка.

Если у вас есть координаты местоположения (например, с GPS мобильного устройства), вы можете найти часовой пояс с помощью одного из этих методов. Однако геолокация по IP-адресу не является отличным решением, потому что часто IP-адрес провайдера или прокси-сервера, который может находиться в другом часовом поясе.

Есть несколько стратегий, которые вы можете использовать, чтобы попытаться определить часовой пояс, например, используя библиотеку jsTimeZoneDetect, что отлично отправной точкой, но недостаточно, чтобы вы не могли просто полагаться только на это. Если вы используете moment.js, там встроенная функция в момент-время называется moment.tz.guess(), которая делает то же самое.

Идея использования функции JavaScript getTimezoneOffset() ошибочна в том, что вы не получаете часовой пояс - просто одно смещение для определенной даты. См. раздел wiki темы TimeZone под названием "TimeZone!= Offset".

Однако вы смотрите на него, в конечном итоге вам нужно решить один из двух способов:

ИЛИ

  • Отправлять время только браузеру в UTC и использовать JavaScript в браузере для преобразования в любой локальный часовой пояс, на который пользователь может установить свой компьютер.

Я обсуждаю это более подробно (с точки зрения С#) в этом ответе.

Ответ 3

Зависимости:

  • http://www.maxmind.com/download/geoip/api/php/php-latest.tar.gz
  • http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz

    //Get remote IP
    $ip = $_SERVER['REMOTE_ADDR'];
    
    //Open GeoIP database and query our IP
    $gi = geoip_open("GeoLiteCity.dat", GEOIP_STANDARD);
    $record = geoip_record_by_addr($gi, $ip);
    
    //If we for some reason didnt find data about the IP, default to a preset location.
    if(!isset($record)) {
        $record = new geoiprecord();
        $record->latitude = 59.2;
        $record->longitude = 17.8167;
        $record->country_code = 'SE';
        $record->region = 26;
    }
    
    //Calculate the timezone and local time
    try {
        //Create timezone
        $user_timezone = new DateTimeZone(get_time_zone($record->country_code, ($record->region!='') ? $record->region : 0));
    
        //Create local time
        $user_localtime = new DateTime("now", $user_timezone);
        $user_timezone_offset = $user_localtime->getOffset();        
    }
    //Timezone and/or local time detection failed
    catch(Exception $e) {
        $user_timezone_offset = 7200;
        $user_localtime = new DateTime("now");
    }
    
    echo 'User local time: ' . $user_localtime->format('H:i:s') . '<br/>';
    echo 'Timezone GMT offset: ' . $user_timezone_offset . '<br/>';
    

Цитата: Местное время посетителя SGet, время восхода и захода солнца по IP с MaxMind GeoIP и PHP от Станислава Хромова

Ответ 4

Одно из них - спросить их! Особенно в тех системах членов, где вы можете захватить/зарегистрировать пользователя - дать им выбор в этот момент. Простой, но точный.

Ответ 5

Это отлично работает...

  echo <<<EOE
   <script type="text/javascript">
     if (navigator.cookieEnabled)
       document.cookie = "tzo="+ (- new Date().getTimezoneOffset());
   </script>
EOE;
  if (!isset($_COOKIE['tzo'])) {
    echo <<<EOE
      <script type="text/javascript">
        if (navigator.cookieEnabled) document.reload();
        else alert("Cookies must be enabled!");
      </script>
EOE;
    die();
  }
  $ts = new DateTime('now', new DateTimeZone('GMT'));
  $ts->add(DateInterval::createFromDateString($_COOKIE['tzo'].' minutes'));

Ответ 6

Часовой пояс недоступен в заголовке HTTP, но страна (аббревиатура) находится в заголовке ACCEPT_LANGUAGE. Это будет нечто вроде "en-US" (США - код страны). Это можно объединить с информацией JavaScript, чтобы получить представление о часовом поясе пользователя.

Это то, что я использую в JS:

function timezone() {
  var now = new Date();
  var jano = new Date(now.getFullYear(), 0, 1).getTimezoneOffset()/-60;
  var julo = new Date(now.getFullYear(), 6, 1).getTimezoneOffset()/-60;
  var tz = Math.min(jano, julo);
  if (jano != julo) tz += ((jano < julo) ? 'S' : 'W') + Math.abs(jano - julo);
  return tz;
}

Это возвращает строку, например, "-6S1" для центральной зоны (стандартное временное смещение -6 часов, летнее время действует летом и добавляет 1 час). Я использую cookie, чтобы сделать это доступным для PHP. PHP ищет базу данных TZ для зон, которые соответствуют этому, и страны. Для здесь (US, -6S1) существует 7 соответствующих зон, первая - "Америка/Чикаго".

Кстати, в базе данных есть две зоны, где DST добавляет что-то, кроме 1 часа: лорд-Хоу-Айленд (10.5W0.5) и Тролль-станция, Антарктида (0W2).