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

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


当前回答

我认为@Matt Johnson-Pints是目前为止最好的,CanIuse搜索显示它现在被广泛采用:

.timeZone .resolvedOptions https://caniuse.com/?search=Intl.DateTimeFormat () ()

其中一个挑战是考虑为什么要知道时区。因为我认为大多数人忽略了一件事,那就是他们是可以改变的!如果一个用户带着他的笔记本电脑从欧洲旅行到美国,如果你之前把它存储在数据库中,那么他们的时区现在是不正确的(即使用户从来没有更新过他们的设备时区)。这也是@Mads Kristiansen回答的问题,因为用户会旅行——你不能把它当作给定的。

例如,我的Linux笔记本电脑关闭了“自动时区”。虽然时间可能会更新我的时区却不会。

所以我相信答案是——你需要它做什么?客户端似乎提供了一种更简单的方法来确定它,但是客户端和服务器端代码都将依赖于用户更新他们的时区或自动更新。我当然可能是错的。

其他回答

不要使用IP地址来明确地确定位置(以及时区)——这是因为使用NAT、代理(越来越流行)和vpn, IP地址不一定真实地反映用户的实际位置,而是反映实现这些协议的服务器所在的位置。

类似于美国的区号对于定位电话用户不再有用,因为号码可携性很流行。

IP地址和上面显示的其他技术对于建议用户可以调整/纠正的默认值很有用。

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

这将始终显示正确的时间基于时区的人已设置在他/她的计算机时钟。没有必要向任何人索取任何东西,把它保存到合适的地方,感谢上帝!

下面是一个健壮的JavaScript解决方案,用于确定浏览器所在的时区。

>>> var timezone = jstz.determine();
>>> timezone.name(); 
"Europe/London"

https://github.com/pellepim/jstimezonedetect

它是简单的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,然后再次登录。最后一次登录将在将来。

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

简单,只需使用JavaScript的getTimezoneOffset函数,如下所示:

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