33

我需要根据他们的 IP 或 http 标头知道我的用户当前所在的时区。

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

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

4

6 回答 6

42

用代码来总结马特约翰逊的答案:

<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(); //For e.g.:"Asia/Kolkata" for the 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>
于 2013-05-13T18:54:33.730 回答
24

Time zone information of the browser is not part of the HTTP spec, so you can't just get it from a header.

If you have location coordinates (from a mobile device GPS, for example), then you can find the time zone using one of these methods. However, geolocation by IP address is not a great solution because often the IP is that of an ISP or proxy server which may be in another time zone.

There are some strategies you can use to try to detect the time zone, such as using jsTimeZoneDetect library, which is a great starting point, but imperfect enough that you can't just rely on that alone. If you're using moment.js, there's a built in function in moment-timezone called moment.tz.guess() that does the same thing.

The idea of using JavaScript's getTimezoneOffset() function is flawed in that you are not getting a time zone - just a single offset for a particular date. See the TimeZone tag wiki's section titled "TimeZone != Offset".

However you look at it, ultimately you have to decide on one of two approaches:

OR

  • Only send time to the browser in UTC, and use JavaScript on the browser to convert to whatever local time zone the user might have their computer set to.

I discuss this in more detail (from a c# perspective) in this answer.

于 2013-05-13T16:30:26.947 回答
3

依赖项:

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

引用:SGet 访客当地时间、日出和日落时间通过 IP 与 MaxMind GeoIP 和 PHP 由 Stanislav Khromov

于 2014-05-08T20:11:26.750 回答
1

一种解决方案是问他们!尤其是在您可以捕获/注册用户的成员系统上 - 在这一点上给他们一个选择。简单但准确。

于 2017-04-04T13:50:36.560 回答
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'));
于 2014-04-02T23:02:50.947 回答
0

Timezone is not available in the HTTP header, but country (abbreviation) is in the ACCEPT_LANGUAGE header. It'll be something like "en-US" (US is the country code). This can be combined with the JavaScript information to get a good idea of the user's timezone.

This is what I'm using in 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;
}

This returns a string like "-6S1" for the central zone (standard time offset of -6 hours, DST active in the summer and adds 1 hour). I use a cookie to make this available to PHP. PHP searches the TZ database for zones that match this, and the country. For here (US, -6S1) there are 7 matching zones, the first is "America/Chicago".

BTW, there are 2 zones in the database where DST adds something other than 1 hour: Lord Howe Island (10.5W0.5) and Troll Station, Antarctica (0W2).

于 2017-06-04T00:05:12.183 回答