是否有一种标准的方法可以让服务器在网页中确定用户的时区?
可能来自HTTP报头或用户代理字符串的一部分?
是否有一种标准的方法可以让服务器在网页中确定用户的时区?
可能来自HTTP报头或用户代理字符串的一部分?
当前回答
如果您碰巧使用OpenID进行身份验证,Simple Registration Extension将解决经过身份验证的用户的问题(您需要从tz转换为numeric)。
另一种选择是根据用户代理的国家偏好推断时区。这是一种有点粗糙的方法(不适用于en-US),但可以很好地近似。
其他回答
有几种方法可以在浏览器中确定时区。如果您的浏览器提供并支持一个标准函数,那么您就应该使用它。下面是用不同格式获取相同信息的三种方法。避免使用基于特定假设或硬编码区域列表进行猜测的非标准解决方案,尽管如果没有其他办法,它们可能会有所帮助。
一旦你有了这个信息,你可以把它作为一个非标准的请求头传递给服务器,并在那里使用它。如果你还需要时区偏移量,你也可以在头文件中或请求有效载荷中传递给服务器,可以使用dateObj.getTimezoneOffset()来检索。
使用Intl API获取Olson格式(标准和推荐的方式):注意,这不是所有浏览器都支持。有关浏览器对此的支持的详细信息,请参阅此链接。 这个API可以让你获得Olson格式的时区,例如亚洲/加尔各答,美国/纽约等。
Intl . DateTimeFormat () timeZone resolvedOptions()。
使用Date对象获得较长的格式,如印度标准时间,东部标准时间等:这是所有浏览器支持的。
let dateObj =新的日期(2021,11,25,09,30,00); / /然后 dateObj.toString () / /收益率 2021年12月25日星期六09:30:00 GMT+0530(印度标准时间)//我位于印度(IST)
注意,字符串包含长格式和短格式的时区信息。你现在可以使用regex来获取这些信息:
let longZoneRegex = /\((.+)\)/; dateObj.toString () .match (longZoneRegex); / /收益率 ['(印度标准时间)','印度标准时间',索引:34,输入:' 2021年12月25日星期六09:30:00 GMT+0530(印度标准时间)',组:未定义] //注意output是一个数组,所以使用output[1]来获取时区名称。
使用Date对象获取短格式,如GMT+0530, GMT-0500等:所有浏览器都支持。
类似地,你也可以得到短格式:
let shortZoneRegex = /GMT[+-]\d{1,4}; dateObj.toString () .match (shortZoneRegex); / /收益率 ['GMT+0530',索引:25,输入:' 2021年12月25日星期六09:30:00 GMT+0530(印度标准时间)',分组:未定义] //注意output是一个数组,所以使用output[0]来获取时区名称。
我仍然没有看到一个详细的答案在这里得到时区。你不需要按IP地址进行地理编码或使用PHP (lol)或从偏移量中错误地猜测。
首先,时区不只是与格林尼治标准时间的偏移量。这是一块由当地标准制定时间规则的土地。一些国家有夏时制,并在不同的时间开启夏令时。通常重要的是获取实际区域,而不仅仅是当前偏移量。
如果您打算存储这个时区,例如在用户首选项中,您需要的是时区,而不仅仅是偏移量。对于实时转换来说,这并不重要。
现在,要用javascript获取时区,你可以使用这个:
>> new Date().toTimeString();
"15:46:04 GMT+1200 (New Zealand Standard Time)"
//Use some regular expression to extract the time.
然而,我发现简单地使用这个健壮的插件更容易,它返回奥尔森格式的时区:
https://github.com/scottwater/jquery.detect_timezone
我是这样做的。这将把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
?>
你可以在客户端使用moment-timezone将值发送给服务器;示例用法:
> moment.tz.guess()
"America/Asuncion"
这里有一种更完整的方法。
获取用户的时区偏移量 测试一些日子的夏令时边界,以确定它们是否在使用夏令时的区域。
节选如下:
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)