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

可能来自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,然后再次登录。最后一次登录将在将来。

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

其他回答

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

getTimezoneOffset()方法将从GMT减去您的时间并返回分钟数。如果你住在GMT-8,它会返回480。

把它换算成小时,除以60。此外,请注意,符号与您需要的相反——它计算的是GMT与您的时区的偏移量,而不是您的时区与GMT的偏移量。要解决这个问题,只需乘以-1。

还要注意w3school说:

返回值不是一个常量,因为使用的惯例 日光节约时间。

你可以在客户端使用moment-timezone将值发送给服务器;示例用法:

> moment.tz.guess()
"America/Asuncion"

我所见过的最流行的(==标准?)确定时区的方法是简单地询问用户自己。如果你的网站需要订阅,这可以保存在用户的个人资料数据。对于anon用户,日期可以显示为UTC或GMT或类似的格式。

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

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

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

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

以下是一些可行的方法:

大多数现代浏览器在实现ECMAScript国际化API时都支持IANA时区,所以你可以这样做:

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

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

支持的环境列在Intl兼容性表中。展开DateTimeFormat部分,并查看名为resolvedOptions()的特性。timeZone默认为主机环境。

Some libraries, such as Luxon use this API to determine the time zone through functions like luxon.Settings.defaultZoneName. If you need to support an wider set of environments, such as older web browsers, you can use a library to make an educated guess at the time zone. They work by first trying the Intl API if it's available, and when it's not available, they interrogate the getTimezoneOffset function of the Date object, for several different points in time, using the results to choose an appropriate time zone from an internal data set. Both jsTimezoneDetect and moment-timezone have this functionality. // using jsTimeZoneDetect var tzid = jstz.determine().name(); // using moment-timezone var tzid = moment.tz.guess(); In both cases, the result can only be thought of as a guess. The guess may be correct in many cases, but not all of them. Additionally, these libraries have to be periodically updated to counteract the fact that many older JavaScript implementations are only aware of the current daylight saving time rule for their local time zone. More details on that here.

最终,更好的方法是向用户询问他们所在的时区。提供一个他们可以改变的设置。你可以使用上面的选项之一来选择一个默认设置,但不要让它不可能偏离你的应用程序。

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