如何检测用户的时区?

时间:2013-05-13 15:21:37

标签: php codeigniter timezone

我需要知道我的用户目前在哪个时区基于他们的IP或http标头。

关于这个问题,我得到了很多答案,但我无法理解这些答案。有人说使用-new Date().getTimezoneOffset()/60from here)。但是这是什么意思?

我的(index.php)页面的根目录中有date_default_timezone_set("Asia/Calcutta");。因此,我必须动态获取时区并将其设置为Asia/Calcutta

6 个答案:

答案 0 :(得分:34)

总结Matt Johnson在代码方面的答案:

<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>

答案 1 :(得分:23)

浏览器的时区信息不是HTTP规范的一部分,因此您无法从标题中获取它。

如果您有位置坐标(例如,来自移动设备GPS),那么您可以找到时区using one of these methods。但是,按IP地址进行地理定位并不是一个很好的解决方案,因为IP通常是ISP或代理服务器,可能位于另一个时区。

您可以使用一些策略来尝试检测时区,例如使用jsTimeZoneDetect库,这是一个很好的起点,但不够完善,您不能仅仅依靠它。如果你正在使用moment.js,那么在时间 - 时区中有一个名为moment.tz.guess()的内置函数可以做同样的事情。

使用JavaScript getTimezoneOffset()函数的想法存在缺陷,因为您没有获得时区 - 只是特定日期的单个偏移量。请参阅the TimeZone tag wiki标题为“TimeZone!= Offset”的部分。

但是你看一下,最终你必须决定两种方法之一:

OR

  • 仅以UTC格式向浏览器发送时间,并使用浏览器上的JavaScript转换为用户可能将其计算机设置为的任何本地时区。

我在this answer中更详细地讨论了这个问题(从c#角度来看)。

答案 2 :(得分:2)

依赖关系:

  1. http://www.maxmind.com/download/geoip/api/php/php-latest.tar.gz
  2. 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/>';
    
  3. 引用:SGet visitor local time, sunrise and sunset time by IP with MaxMind GeoIP and PHP by Stanislav Khromov

答案 3 :(得分:1)

一个解决方案是问他们!特别是在可以捕获/注册用户的成员系统上 - 在那时给他们一个选择。简单但准确。

答案 4 :(得分:0)

这很好......

  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'));

答案 5 :(得分:0)

HTTP标头中没有时区,但country(缩写)位于ACCEPT_LANGUAGE标头中。它会像&#34; en-US&#34; (美国是国家代码)。这可以与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;
}

返回一个字符串,如&#34; -6S1&#34;对于中心区域(标准时间偏移为-6小时,DST在夏季活动并增加1小时)。我使用cookie将其提供给PHP。 PHP在TZ数据库中搜索与此匹配的区域和国家/地区。对于这里(美国,-6S1),有7个匹配区域,第一个是#34; America / Chicago&#34;。

顺便说一下,数据库中有2个区域,其中DST增加了1小时以外的东西:豪勋爵岛(10.5W0.5)和南极洲巨魔站(0W2)。