Web服务器是否有任何标准方式能够确定用户在网页中的时区?也许从HTTP头或用户代理字符串的一部分?确定用户的时区
确定用户的时区
回答
虽然有人建议将HTTP头包含在HTTP规范中,但目前还没有HTTP头会报告客户端时区。
如果是我,我可能会尝试使用客户端JavaScript获取时区,然后使用Ajax或其他方式将其提交给服务器。
JavaScript是获取客户当地时间的最简单方法。我建议使用XMLHttpRequest
发送本地时间,如果失败,则回退到基于IP地址检测到的时区。
就地理定位而言,我在几个项目上使用了MaxMind GeoIP,它运行良好,但我不确定它们是否提供时区数据。这是您支付的服务,它们每月提供数据库更新。他们提供几种网页语言的包装。
我已经投了这个答案,因为经纬度从像GeoIP这样的数据库中获得(它现在有一个免费版本)可以与将这种坐标转换为时区的数据库结合使用。我认为GeoNames有一个后者这样的数据库。 – 2011-11-20 06:52:34
另请参阅[这个问题](http://stackoverflow.com/questions/5584602)。 – 2011-12-01 07:11:39
确定我所见过的时区的最流行的(==标准?)方式仅仅是询问用户自己的。如果您的网站需要订阅,可以将其保存在用户的个人资料数据中。对于匿名用户,日期可以显示为UTC或GMT等。
我不想成为一个聪明的笨蛋。只是有时候某些问题在任何编程环境之外都有更好的解决方案。
当用户下载一个.ics文件时,应该有一个特定于他们的位置的开始时间(例如,在全国各地的上午9点11分)?他们不应该说他们的时区是imo。 – 2011-01-27 21:57:48
为什么不接受这是正确的答案? Unkwntech给出的答案甚至不适用于非IE浏览器。 – 2011-02-18 01:33:02
@Ishmaeel:但用户确实需要国际旅行,而且每次他们从某个非本地时区登录时都不需要告诉他们的时区 – 2011-07-22 08:04:51
魔都似乎是在
visitortime.getTimezoneOffset()
这很酷,我不知道。它在IE等工作? 从那里你应该可以使用JS来ajax,设置cookie,不管。我可能会自己去饼干路线。
您需要允许用户修改它。我们之前尝试过使用地理位置(通过maxmind)来做这件事,而且这种错误经常是错的 - 足以让它不值得做,所以我们只是让用户在他们的个人资料中设置它,并向用户显示通知还没有设置他们的。
任何人都知道,这将 匹配IP地理位置
好吧,算你走运这个问题的答案可以在我们自己的计算器网站上找到任何服务: How to get the Country according to a certain IP?
我刚刚去了那个网站,这是完全错误的: -/ – 2010-08-25 02:46:49
如果您碰巧使用OpenID进行身份验证,则Simple Registration Extension会sol对于经过身份验证的用户有问题(您需要将tz从数字转换为数字)。
另一种选择是从用户代理的国家/地区首选项中推断出时区。这是一种有些粗糙的方法(不适用于en-US),但是可以很好地近似。
-new Date().getTimezoneOffset()/60;
getTimezoneOffset()
将从GMT中减去您的时间并返回分钟数。所以如果你住在格林威治标准时间8,它将返回480。把这个数字除以60即可。另外,注意这个符号与你所需要的符号相反 - 它计算的是GMT时间的偏移量,而不是你的时区与GMT的偏移量。要解决这个问题,只需乘以-1。
编辑
还要注意的是w3school说:
返回的值不是一个常量,因为使用 夏令时的做法。
这对我来说最有意义。有没有什么理由不应该使用这个问题,或者是否每个人都会让问题比他们需要的更困难。 – jordanstephens 2010-06-28 19:54:50
@jordanstephens我不是专家,所以我不知道是否有情况下这不会工作,但它对我来说工作得很好。 – 2010-06-28 20:00:24
那些使用带有浏览器而没有javascript支持的手机的用户呢? 我喜欢这个问题,用户询问HTTP标头,用户代理...有没有办法让这个工作服务器端,尽可能准确? – Nischal 2011-09-09 14:57:20
下面是一个物品(与源代码),说明如何确定和使用本地化时间在ASP.NET(VB.NET,C#)应用:
总之,所描述的方法依赖于JavaScript的getTimezoneOffset
函数,它返回被保存在会话cookie和使用代码隐藏到GMT与本地时间之间调整时间值的值。好的是用户不需要指定时区(代码自动执行)。涉及更多(这就是为什么我链接到文章),但提供的代码使它非常易于使用。我怀疑你可以将逻辑转换为PHP和其他语言(只要你理解ASP.NET)。
和PHP日期函数,你就可以了解哪些网站所在服务器的日期时间。获得用户时间的唯一方法是使用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();
?>
但是按照我的观点,最好是向用户问一下,如果你的项目中注册是强制性的。
这里是一个更完整的方法。
- 获得时区的用户
- 测试上DLS边界几天的时间来确定他们是否在使用DLS区域 偏移。
除了如下面:
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;
}
Getting TZ and DST from JS(通过归路机)
这对我有效!阅读博客帖子下的评论,对代码进行一些更新。 – arlomedia 2012-04-15 19:35:14
使用Unkwntech的做法,我写了使用jQuery和PHP函数。这已经过测试,并且确实有效!
在PHP页面,你想拥有的时区作为一个变量,有此代码段靠近页面顶部的地方:
<?php
session_start();
$timezone = $_SESSION['time'];
?>
这将读取会话变量“时间”,我们现在即将创建。
在同一页上,在,你需要首先包括jQuery的:
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
另外在,jQuery的下方,粘贴:
<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://domain.com/timezone.php",
data: 'time='+ visitortimezone,
success: function(){
location.reload();
}
});
}
});
</script>
您可能会或可能没有注意到,但你需要将网址更改为你的实际域名。
最后一件事。你可能想知道timezone.php是什么。嗯,这很简单: (创建一个名为timezone.php并指向它与上面的网址一个新的文件)
<?php
session_start();
$_SESSION['time'] = $_GET['time'];
?>
如果这个工作正常,它会首先加载页面,执行JavaScript并重新加载页面。然后您将能够读取$ timezone变量并将其用于您的乐趣!它返回当前的UTC/GMT时区偏移量(北京时间)或任何时区你是在
我这样做,但我可能有东西,检查当前$ _SESSION ['时间'],只有得到的JavaScript重新加载,如果它不同 – 2011-09-15 04:59:39
的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>';
这将始终正确显示了基于该人已在他的计算机时钟设置时区的时间,不用问什么对任何人,并将其保存到感谢上帝的地方!
一个简单的方法来做到这一点是通过使用:
new Date().getTimezoneOffset();
你为什么从2年前转贴相同的答案(由约翰伊萨克斯):http://stackoverflow.com/a/1809974/836407? – chown 2012-01-30 01:01:22
这里是我如何做到这一点。这会将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
?>
简单,只需使用JavaScript getTimezoneOffset
功能,像这样:
-new Date().getTimezoneOffset()/60;
试试这个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'];
?>
这里一个强大的JavaScript解决方案来确定浏览器所在的时区。
>>> var timezone = jstz.determine();
>>> timezone.name();
"Europe/London"
我还没有在这里看到了详细的回答得到的时区。您不需要通过IP地址进行地理编码,也不需要使用PHP(lol)或从偏移量错误地猜测。
首先,时区不仅仅是GMT的偏移量。时间规则是由当地标准设定的一块土地。一些国家有夏令时,并且会在不同的时间开启夏令时。获取实际区域通常很重要,而不仅仅是当前的偏移量。
如果您打算存储此时区,例如在用户首选项中您希望区域而不仅仅是偏移量。对于实时转换,这并不重要。
现在,让你可以使用这个JavaScript时区:
>> new Date().toTimeString();
"15:46:04 GMT+1200 (New Zealand Standard Time)"
//Use some regular expression to extract the time.
但是我发现它很容易直接使用这个强大的插件,它返回奥尔森格式化时区:
将时区偏移量作为AJAX请求上的HTTP标题提交,其中jQuery
$.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/
获得实际的时区名称,请勿使用IP地址来明确地确定位置(和hense时区)的东西 - 这是因为使用NAT,代理服务器(越来越多流行)以及VPN,IP地址不一定真实地反映用户的实际位置,而是实现这些协议的服务器驻留的位置。
鉴于Number Portability的流行性,与区号查找电话用户不再有用的方法类似。
上面显示的IP和其他技术对于有用,建议用户可以调整/更正的默认。
首先,了解JavaScript中的时区检测不完善。您可以在Date
对象的实例上使用getTimezoneOffset
获取本地时区偏移量对于特定日期和时间,但这与IANA time zone(如America/Los_Angeles
)的实例不完全相同。
有一些可以工作,虽然选择:
大多数现代浏览器都支持IANA时区在其执行ECMAScript Internationalization API的,所以你可以这样做:
const tzid = Intl.DateTimeFormat().resolvedOptions().timeZone;
结果包含运行代码的计算机的IANA时区设置的字符串。
支持环境列表in the Intl compatibility table。展开
DateTimeFormat
部分,并查看名为resolvedOptions().timeZone defaults to the host environment
的功能。如果您需要支持更广泛的环境(例如较早的Web浏览器),则可以使用库在时区对进行猜测。他们首先尝试使用
Intl
API(如果可用),并且在不可用时,它们会在几个不同的时间点询问对象的getTimezoneOffset
函数,并使用结果从内部数据集中选择适当的时区。jsTimezoneDetect和moment-timezone都具有此功能。
// using jsTimeZoneDetect var tzid = jstz.determine().name(); // using moment-timezone var tzid = moment.tz.guess();
在这两种情况下,结果都只能被视为猜测。在许多情况下,猜测可能是正确的,但不是全部。
此外,这些库必须定期更新,以抵消以下事实:许多较旧的JavaScript实现仅知道其当地时区的夏令时规则当前。 More details on that here.
最终,更好的方法是实际询问用户的时区。提供可以更改的设置。您可以使用上述选项之一来选择默认设置,但不要让它不可能偏离您的应用程序。
还有完全不同的方法而不是完全依赖于用户计算机的时区设置。相反,如果您可以收集经度和纬度坐标,则可以使用one of these methods将这些坐标解析为时区。这在移动设备上运行良好。
一种可能的选择是使用Date
标题字段,该字段在RFC 7231中定义,并且应该包含时区。当然,这并不能保证价值真的是客户的时区,但它可以是一个方便的起点。
简单与JS
和PHP
:
即使得到了弥补与他的内部时钟和/或时区,我发现迄今最好的方式,用户可以胡来,仍然new Date().getTimezoneOffset();
。它的无创性,不会给头痛,并消除依赖第三方的需要。
假设我有一个表users
,它包含一个字段date_created int(13)
,用于存储unix时间戳;
假设一个客户端creates a new account
,数据由post
接受,我需要与客户的UNIX时间戳,而不是服务器对insert/update
的date_created column
。
由于在插入/更新时需要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 db
$created = date("F j, Y, g:i a",$date_created);//return it to the user or whatever
现在,这个例子可以适应人的需求,当谈到插入first
时间戳...当它涉及到一个额外的时间戳或表格,你可能要考虑将tzo值插入用户表中以供将来参考,或将其设置为会话或cookie。
P.S.但是如果用户旅行并切换时区将会怎样。以GMT + 4登录,快速到达GMT-1并重新登录。最后登录将在未来。
我想...我们想太多了。
你可以用moment-timezone做它在客户端和发送值的服务器;示例用法:
> moment.tz.guess()
"America/Asuncion"
在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;
我写上一篇博客文章:http://usefulangle.com/post/31/detect-user-browser-timezone-name-in-php 它包含了演示也。
- 1. JavaScript如何确定用户的时区?
- 2. 如何从Twitter API可靠地确定用户的时区?
- 3. 如何根据用户的时区确定用户的网络文化?
- 4. 确定iPhone用户iTunes Store地区?
- 5. PHP和MySQL时区,同时支持用户定义的时区
- 6. 基于时区的重定向用户
- 7. 在Python中确定时区
- 8. 如何正确地为用户定义的时区存储时间?
- 9. 客户端时区与用户指定的时区相同(javascript/moment.js/moment-timezone.js)
- 10. 获取用户时区以显示正确的时间
- 11. 将GMT时区转换为用户特定时区
- 12. 确定T-SQL中的时区偏移
- 13. foursquare如何确定签入的时区?
- 14. 如何忽略用户的时区并强制Date()使用特定时区
- 15. 获取用户时区并将utc转换为用户时区
- 16. SQL Server:确定使用服务帐户时的域用户
- 17. 确定用户何时离开网站
- 18. 确定用户何时单击x-VBA
- 19. YouTube如何确定用户的地区/位置
- 20. libparted确定使用扇区
- 21. 如何向用户显示正确的时区?
- 22. 使用python,什么是自动确定用户当前时区的最准确的方法
- 23. 确定给定时区的UTC时间是否在DST
- 24. 在GWT应用在服务器侧确定用户区域
- 25. 确定SharePoint上的用户
- 26. 将UTC日期时间显示到用户定义的时区
- 27. 根据时区确定电话号码?
- 28. 如何确定时区中的文化/区域设置
- 29. 如何确定一个(ASP.NET/MonoRail)网站用户在哪个时区?
- 30. 检测用户时区并显示该时区的UTC时间
你可能会考虑让John Isaacks的答案是正确的......他的解决方法简单得多,说得轻松一些。 – catphive 2011-04-08 20:49:49