确定用户的时区


610

Web服务器是否可以通过标准方法确定网页中用户的时区?

也许来自HTTP标头或user-agent字符串的一部分?


6
询问用户。如果从用户计算机获取时区,并且设置错误,那又如何呢?
罗布·威廉姆斯

40
然后用户可能不在乎?
agnoster 2010年


2
不幸的是,该问题的答案也允许用户进行剖析和地理围栏。
William Entriken

1
为什么需要知道用户时区?
Braiam '18

Answers:


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

该方法getTimezoneOffset()将从GMT中减去您的时间,并返回分钟数。因此,如果您居住的是GMT-8,它将返回480。

要将其乘以小时,除以60。此外,请注意,该符号与您需要的符号相反-它是计算GMT与您所在时区的偏移量,而不是您所在时区与GMT的偏移量。要解决此问题,只需乘以-1。

另请注意,w3school说:

由于使用夏令时的做法,返回的值不是常数。


5
使用手机的用户使用的浏览器不支持JavaScript怎么办?我喜欢这个问题,用户询问HTTP标头,用户代理...是否有办法使此工作服务器端尽可能准确?
Nischal 2011年

18
这不适用于DST。获取时区偏移量完全符合其要求。得到的是偏移量。时区实际上是一个地理区域。由于您不知道用户居住在哪个半球,或者他们所在的国家/地区甚至还具有夏令时,因此这对于夏令时将不起作用。为什么不使用它代替:>>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
Keyo

20
我希望与Keyo有所不同。getTimezoneOffset()的定义(根据ECMA标准ecma-international.org/ecma-262/5.1/#sec-15.9.5.26)为“以分钟为单位返回本地时间和UTC时间之间的时差”。-换句话说,应该考虑夏令时。Mozilla的文档说:“即使对于给定的语言环境,夏时制也可以防止该值成为常数。”
xgretsch 2013年

11
@xgretsch:获取用户当前与GMT 的偏移量。如果您要演示同一天发生的另一个时间,那很好(除非当前日期是转换日期,否则可能是错误的)。但是,许多时区与GMT的偏移时间相同,并且它们的转换日期可能不同,或者不使用夏令时。
Mike Dimmick 2014年

12
这里要注意的一件事;有些地方(例如加拿大的纽芬兰)的时区偏离半小时,因此,除以60后,您的答案可能不是整数。
杰森·沃尔顿2014年

193

确定我所看到的时区的最流行(==标准?)方法只是问用户自己。如果您的网站需要订阅,则可以将其保存在用户的个人资料数据中。对于匿名用户,日期可以显示为UTC或GMT或类似的日期。

我不是想成为聪明人。只是有时候某些问题在任何编程环境之外都有更好的解决方案。


5
当用户下载的.ics文件应具有特定于其所在位置的开始时间(例如,全国的上午9点至11点)时,该怎么办?他们不必说自己的时区是imo。
Marcy Sutton

33
@Ishmaeel:但是用户确实要出国旅行,每次从某个非本地时区登录时,他们都不需要告诉自己的时区
Rajat Gupta

10
这没有回答问题,这显然意味着他正在寻找技术解决方案。
G-Wiz

5
@gWiz OP正在寻求标准解决方案。这是很标准的。
西蒙·贝格

4
最好的解决方案可能是询问用户(例如,在报告顶部提供时区下拉列表),而当用户在移动设备上时,将下拉列表选项默认为GPS确定的时区的组合提供位置信息的设备,否则默认为UTC。
Triynko 2015年

131

到目前为止,还没有HTTP标头可以报告客户端时区,尽管建议将其包含在HTTP规范中。

如果是我,我可能会尝试使用客户端JavaScript获取时区,然后使用Ajax或其他方式将其提交到服务器。


16
奇怪的是,这是该问题的唯一正确答案,该问题询问如何在服务器端进行操作。我怀疑其他答案获得更多投票的原因是,一旦您意识到需要在客户端进行操作,您最终就会使用其他答案。但是恕我直言,任何支持其他答案的人也应该支持该答案。
TTT

我相信最好的方法是使用geo-ip位置对可能的时区进行排序,并默认选择与用户代理时间偏移量(紧密)匹配的第一个(需要JavaScript)。即使在此之后,即使该方法将选择不正确的时区,您也必须提供一种修复时区的方法。
Mikko Rantalainen

@MikkoRantalainen使用代理时要小心,因为它们并不总是在标头中宣传自己。
马修(Matthieu)

@Matthieu现在有一个更好的答案:stackoverflow.com/a/11836123/334451
Mikko Rantalainen

2
从字面上看,这是实际解决所提出问题的唯一答案。
lscoughlin '19

54

JavaScript是获取客户端本地时间的最简单方法。我建议使用XMLHttpRequest发送回本地时间,如果失败,请回退到基于其IP地址检测到的时区。

就地理位置而言,我已经在多个项目中使用了MaxMind GeoIP,并且效果很好,尽管我不确定它们是否提供时区数据。这是一项您需要付费的服务,它们每月提供数据库更新。他们提供几种Web语言的包装器。


我之所以投票赞成该答案,是因为可以将从GeoIP之类的数据库中获得的纬度和经度(目前有免费版本)与将此类坐标转换为时区的数据库结合使用。我认为GeoNames拥有后者这样的数据库。
Peter O.

MaxMind GeoIP数据库/ API的当前版本(免费版和付费版)确实提供了时区信息(我的时区返回“欧洲/伦敦”。)我不记得他们的GeoIP系统的旧版本是否做了同样的事情,但是现在效果很好!MaxMind字段分别命名为“ time_zone”,“ time_zone_name”。
马修·斯莱曼

51

首先,请了解JavaScript中的时区检测是不完善的。您可以使用对象的实例获取特定日期和时间的本地时区偏移量,但这与完整的IANA时区不同,例如getTimezoneOffsetDateAmerica/Los_Angeles

但是,有些选项可以起作用:

  • 大多数现代浏览器在其ECMAScript国际化API的实现中都支持IANA时区,因此您可以执行以下操作:

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

结果是一个字符串,其中包含运行代码的计算机的IANA时区设置。

Intl兼容性表中列出受支持的环境。展开该DateTimeFormat部分,然后查看名为的功能resolvedOptions().timeZone defaults to the host environment

  • 一些库(例如Luxon)使用此API通过诸如之类的函数来确定时区luxon.Settings.defaultZoneName

    • 如果需要支持更广泛的环境集(例如较旧的Web浏览器),则可以使用库在时区进行有根据的猜测。他们首先尝试IntlAPI是否可用,当API不可用时,他们会在几个不同的时间点询问对象的getTimezoneOffset功能,并Date使用结果从内部数据集中选择合适的时区。

    无论jsTimezoneDetect时刻,时区具有此功能。

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

    在这两种情况下,结果只能被认为是猜测。在许多情况下,猜测可能是正确的,但并非全部。

    此外,必须定期更新这些库,以抵消许多较旧的JavaScript实现仅了解其本地时区的当前夏令时规则这一事实。 这里有更多细节。

最终,更好的方法是实际询问用户的时区。提供一个可以更改的设置。您可以使用上述选项之一来选择默认设置,但是请不要偏离应用程序中的默认设置。

还有完全依赖用户计算机的时区设置的完全不同的方法。相反,如果您可以收集经度和纬度坐标,则可以使用以下方法之一将其解析为时区。这在移动设备上效果很好。


使用用户的地理位置(即他们的语言环境)来推断时区也是有缺陷的。用户可能希望在设备上使用不是本地时区的特定时区,甚至认为该时区可能显示相同的时间。例如,旅行者经常离开将其时区设置为惯常位置的设备,并且不希望在没有任何建议的情况下看到日期和时间使用其他偏移量。我可能是从个人经验谈起的…;-)
RobG

不知道你是不是在骗我罗布。;)但这些方法都不使用其区域设置,而是使用设备上的设置,因此与您的观点保持一致。(只有上一段提到的替代方法会使用当前位置。)
马特·约翰逊·品特

使用术语注释进行提示:“区域设置”着重不是用户的地理位置。“语言环境”是一组设置,例如语言,数字格式,日历等。例如,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。
Dirbaio '16

1
这个图书馆很聪明。它的工作方式是查询UTC的当前偏移量,然后通过增加或减去秒直到调整到UTC的偏移量来调整JavaScript Date对象的时间。使用此方法,该库可以找出足够多的DST更改,以唯一地标识时区。我认为,如果执行二进制搜索而不是线性搜索,该库甚至可以具有更好的性能。返回值是IANA区域信息密钥(又名Olson时区数据库)。
米科·兰塔莱宁

3
不再需要该库。现代浏览器支持Intl API,该API返回IANA时区字符串。看到这个答案
Dan Dascalescu

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

从JS获取TZ和DST(通过Way Back Machine)


这对我有用!阅读博客文章下的评论,以获取代码的一些更新。
arlomedia

这仍将仅返回时区的标准偏移量,例如+02:00。它不会为您提供足够的信息来确定用户的时区,例如Africa/JohannesburgEurope/Istanbul。请参阅时区标签Wiki
Matt Johnson-Pint 2014年

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>

同样在jQuery下面的<head>中,粘贴以下代码:

<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,然后重新加载页面。然后,您将能够读取$ timezone变量,并乐于使用它!它返回当前UTC / GMT时区偏移量(GMT -7)或您所在的任何时区。


我确实喜欢这样,但是我可能会检查当前的$ _SESSION ['time']并仅在不同的情况下才能重新加载javascript
Christopher Chase

1
使用Cookie可能比使用Session进行传输要容易得多,因为锁定和反序列化PHP会话可能会导致应用程序运行缓慢。为了获得最大的效率,您可以将值复制到会话中并删除co​​okie,以便在后续请求中不发送该cookie。
IMSoP

25

使用jQuery在AJAX请求上将时区偏移量提交为HTTP标头

$.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
这仅返回当前时区偏移量-不返回时区。请参阅时区标签Wiki
Matt Johnson-Pint 2014年

编辑以包含有关对时区名称执行相同操作的信息。
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

用PHP date函数,您将获得站点所在服务器的日期时间。获得用户时间的唯一方法是使用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?尽管似乎可以很好地解决此问题,但这里还是缺少一些东西,并且无法正常工作。


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

1
本文也可通过PDF形式获得:app.box.com/shared/bfvvmidtyg
Ivaylo Slavov

本文中描述的将UTC服务器时间转换为本地客户端时间的方法是错误的。使用当前客户端偏移量来调整服务器上的UTC时间,对于观察夏令时的客户端语言环境,将导致半年不正确的“本地”时间。考虑这种情况:英国的一位客户在2013年1月14日(格林尼治标准时间+0000标准时间)将日期和时间设置为2015年8月21日14:00(格林尼治标准时间+0100夏令时间)。这已在服务器上标准化为2015年8月21日13:00 UTC。在发生这种情况的那天,客户偏移量为0,因此发送回客户的时间为2015年8月21日13:00。
史蒂芬·布莱尔

有道理,但我并没有声称这是防弹解决方案。如果您需要实施一个真正的时间敏感型解决方案,例如火车票预订应用程序,那么您需要找到一个更全面(且复杂)的解决方案。但是,对于许多应用程序来说,这不是问题。因为在许多情况下,我们要本地化当前会话的GMT值。现在,如果您有一个甚至在将来甚至需要保存一些时间戳的应用程序,并且它不能容忍DTS,那么一种正确的方法是提出一种在GMT中直接节省时间的选项。如果您知道更好的选择,请分享。
Alek Davis


13

使用JavaScript和PHP很简单:

即使用户可能会弄​​乱他/她的内部时钟和/或时区,但到目前为止,我发现的最好方法仍然是偏移量 new Date().getTimezoneOffset();。它是非侵入性的,不会产生头痛,并且消除了对第三方的依赖。

假设我有一个表,users其中包含一个字段date_created int(13),用于存储Unix时间戳;

假设一个客户端creates a new account,数据被接收post,而我需要insert/updatedate_created column与客户的Unix时间戳,而不是服务器的。

由于在插入/更新时需要timezoneOffset,因此当客户端提交表单时,它将作为一个额外的$ _POST元素进行传递,从而消除了将其存储在会话和/或cookie中的需要,并且也没有其他服务器命中。

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

检索创建的日期时,您可以像这样转换时间戳:

$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,然后再次登录。上次登录将在以后。

我想...我们想得太多了。



11

在PHP中获取有效的TZ数据库时区名称是一个两步过程:

  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并将其发送到Web服务器。参考文献:stackoverflow.com/questions/9772955/...
迈克尔曾


8

一种可能的选择是使用Date标头字段,该字段在RFC 7231中定义,并且应该包含时区。当然,不能保证该值确实是客户的时区,但这可以是一个方便的起点。


1
不幸的是,该标头似乎主要是为响应而不是请求而设计的:“用户代理可以在请求中发送Date标头字段,尽管通常不会这样做,除非它被认为可以将有用的信息传达给服务器。” 我刚刚检查了一下,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'];
?>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.