如何获取客户端的时区?

32

我正在使用Zend_Framework编写一个应用程序(因此解决方案可以依赖它)。

如何获取客户端的时区?

例如,如果某人在俄罗斯莫斯科,我希望得到3 * 60 * 60(因为那里是UTC +3)。如果他在英国,我想要零。如果他使用UTC-3:30(加拿大?),我想要-3.5 * 60 * 60。

(这不是关于格式的问题 - 我可以得到“Europe/Moscow”或“UTC-3”用于俄罗斯圣彼得堡,而是关于获取客户端使用的时区。但首选以秒为单位的差值)

唯一能想到的解决方案是让JavaScript获取本地时间并进行重定向。


2
请注意,此问题中所有答案都存在缺陷,因为它们只获取当前偏移量。请参阅时区标签wiki中的“时区!=偏移量”,并查看重复的问题及其答案。 - Matt Johnson-Pint
4个回答

12

我用jQuery和PHP编写了一个函数。这个函数已经经过测试,可以正常工作!

在你想将时区作为变量的PHP页面上,在页面顶部附近添加以下代码片段:

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

这将读取会话变量"时间",而现在我们将要创建它。

在同一页的代码中,你首先需要引入jQuery:

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

同时在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://domain.com/timezone.php",
                data: 'time='+ visitortimezone,
                success: function(){
                    location.reload();
                }
            });
        }
    });
</script>

你也许已经注意到了,但你需要将URL更改为你实际的域名。

最后一件事。你可能想知道timezone.php是什么。实际上,它只是这样: (创建一个名为 timezone.php 的新文件,并使用上面的URL指向它)

<?php
    session_start();
    $_SESSION['time'] = $_GET['time'];
?>
如果这个代码能够正确运行,它将首先加载页面,执行JavaScript,然后重新加载页面。接着你就可以读取$timezone变量并用它来达到你的目的!它会返回当前的UTC/GMT时区偏移量(GMT-7)或者你所在的时区偏移量。

1
混合使用JavaScript和PHP代码?你是认真的吗? - drull
4
为什么不呢?除非我弄错了,时区只能从客户端声明,在php会话中添加它可以增加很多灵活性。 - americanknight
当然,你需要使用JavaScript来完成这个任务。但是我正在谈论将纯PHP嵌入HTML中:这是猴子编码。最好使用模板。如果我做这样的事情,第二天我就会被解雇 :) - drull
2
模板引擎在某个时刻将您的模板代码转换为纯 PHP。 - adam
1
@drull,请在你愿意分享不受抱怨的更好代码之前,先克制一下批评。 - Dennis
显示剩余2条评论

8
请查看此篇文章以了解如何通过JavaScript设置Cookie来检测时区:PHP5时区解决方案。该文章较长,因为详细说明了解决方案。我在自己的应用程序中也实现了这样的解决方案,效果非常好。
您还可以通过Ajax将时区发送到服务器,并在那里进行任何需要的计算。或者,如果不需要在服务器端进行计算,请在客户端应用所需的地方应用时区。这取决于您的用例。
另外,建议让访问者自行设置其时区并将其存储在Cookie或会话中。

8
这个链接失效了。这可能是一份复制的链接:http://blog.codez.in/php5-time-zone-solution/web-development/2010/07/09 - Jose M Vidal
1
@Jose 感谢您指出并提供替代方案。 - Gordon
2
两个链接现在都失效了 :-( - rmirabelle
1
这两个页面都可以在强大的WebArchive中找到:www.incoherent.chblog.codez.in - AntonK

2
这是一个开销非常小的cookie解决方案:
  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'));

1
new DateTime('now', new DateTimeZone('GMT')); 可能应该使用 UTC 而不是 GMT,根据 MDN 的建议:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset - Gifford N.
UTC和GMT实际上是一样的。 - Zoltán Hajdú

1

我认为你最好的选择是根据客户端发送的Accept-Language头猜测。


要获取国家和城市,我可以使用geoip。但是类似于“Europe / Moscow”的时区只能针对特定的城市设置,而客户端可以来自任何地方。 - Valentin Golev
没错,Accept-Language 可能会涵盖大量的时区,但客户端并没有发送任何其他指示其时区的内容。最准确的方法是根据 JavaScript 重定向,但每个页面请求需要两次页面加载,这太糟糕了。 - Myles
我可以将它存储在会话中 :) 这只是一个额外的请求。如果我找不到其他更好的方法,我想我会用这种方式。 - Valentin Golev
1
一些Geo-IP服务为IP地址提供时区。因此,这里我提供了一个示例:https://dev59.com/S2445IYBdhLWcg3wq8Lp#10103105 - Mikhus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接