是否有一种标准的方法可以让服务器在网页中确定用户的时区?

可能来自HTTP报头或用户代理字符串的一部分?


当前回答

它是简单的JavaScript和PHP:

即使用户可以打乱他/她的内部时钟和/或时区,我迄今为止发现的最好的方法,以获得偏移量,仍然是新的Date(). gettimezoneoffset();。它是非侵入性的,不会让人头痛,也不需要依赖第三方。

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

假设客户端创建了一个新帐户,数据是通过post接收的,我需要用客户端的Unix时间戳插入/更新date_created列,而不是服务器的。

由于在插入/更新时需要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时,你可以像这样转换时间戳:

$date_created = // Get from the database
$created = date("F j, Y, g:i a",$date_created); // Return it to the user or whatever

现在,这个示例可能适合您的需要,当涉及插入第一个时间戳时……当涉及到额外的时间戳或表时,您可能需要考虑将tzo值插入到用户表中以供将来参考,或者将其设置为会话或cookie。

P.S.但是如果用户旅行并切换时区怎么办?在GMT+4登录,快速移动到GMT-1,然后再次登录。最后一次登录将在将来。

我认为……我们想得太多了。

其他回答

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

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

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

至于地理定位,我已经在几个项目中使用了MaxMind GeoIP,它工作得很好,尽管我不确定他们是否提供时区数据。这是一项你付费的服务,他们每月更新你的数据库。他们提供多种网络语言的包装器。

在实际的HTML代码或任何用户代理字符串中没有这样的方法来计算时区,但您可以做的是使用JavaScript创建一个基本函数来获取时区。

我还不知道如何用JavaScript编码,所以我的函数可能需要时间来制作。

但是,您也可以尝试使用JavaScript在Date部分中的getTzimezoneOffset()函数或简单地使用new Date(). gettimezoneoffset();来获得实际的时区。

一个简单的方法是使用:

new Date().getTimezoneOffset();

这里有一种更完整的方法。

获取用户的时区偏移量 测试一些日子的夏令时边界,以确定它们是否在使用夏令时的区域。

节选如下:

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)