确定用户的时区
Web Server是否有任何标准的方法来确定用户在网页中的时区? 也许从HTTP头或用户代理string的一部分?
-new Date().getTimezoneOffset()/60;
getTimezoneOffset()
将从GMT中减去您的时间并返回分钟数。 所以,如果你住在格林尼治标准时间8,它将返回480.要把这个数小时,除以60.此外,请注意,符号是相反的,你需要的 – 它是计算格林尼治标准时间偏离你的时区,而不是时区与GMT的偏移。 要解决这个问题,只需乘以-1。
编辑
另外请注意, w3school说:
返回的值不是一个常数,因为使用夏令时的做法。
确定我所见过的时区的最stream行的(==标准?)方法是简单地询问用户自己。 如果您的网站需要订阅,则可以将其保存在用户的个人资料数据中。 对于匿名用户,date可以显示为UTC或GMT等。
我不想成为一个聪明的笨蛋。 只是有时候一些问题在任何编程环境之外都有更好的解决scheme。
虽然有人build议将它包含在HTTP规范中,但是目前还没有HTTP头将会报告客户端的时区。
如果是我,我可能会尝试使用客户端JavaScript获取时区,然后使用Ajax或其他方式将其提交给服务器。
Javascript是获取客户当地时间最简单的方法。 我build议使用XMLHttpRequest
发送本地时间,如果失败,则回退到根据IP地址检测到的时区。
就地理位置而言,我已经在几个项目上使用了MaxMind GeoIP ,并且效果很好,但我不确定它们是否提供时区数据。 这是您付费的服务,并且每月提供您的数据库更新。 他们提供几种网页语言的包装。
这是一个强大的JavaScript解决scheme,用于确定浏览器所在的时区。
>>> var timezone = jstz.determine(); >>> timezone.name(); "Europe/London"
这是一个更完整的方法。
- 获取用户的时区偏移量
- 在DLS边界上testing几天,以确定它们是否在使用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; }
从JS获取TZ和DST (通过回机器)
使用Unkwntech的方法,我写了一个使用jQuery和PHP的函数。 这是testing,并且工作!
在你想把时区作为variables的PHP页面上,在这个页面的顶部附近有这段代码:
<?php session_start(); $timezone = $_SESSION['time']; ?>
这将读取会议variables“时间”,我们现在要创build。
在同一页面上,你需要首先包含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>
您可能注意到,也可能没有注意到,但是您需要将url更改为您的实际域。
最后一件事。 你可能想知道什么是timezone.php。 那么,这只是:(创build一个名为timezone.php的新文件,并用上面的url指向它)
<?php session_start(); $_SESSION['time'] = $_GET['time']; ?>
如果这个工作正常,它将首先加载页面,执行JavaScript,并重新加载页面。 然后,您将能够阅读$ timezonevariables并使用它来享受您的乐趣! 它返回当前的UTC / GMT时区偏移量(GMT -7)或者你所在的任何时区。
我还没有看到一个详细的答案在这里得到的时区。 你不需要通过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.
不过,我发现简单地使用这个返回Olsen格式化时区的健壮的插件更容易:
使用jQuery将时区偏移量作为AJAX请求的HTTP标头提交
$.ajaxSetup({ beforeSend: function(xhr, settings) { xhr.setRequestHeader("X-TZ-Offset", -new Date().getTimezoneOffset()/60); } });
你也可以通过使用moment.tz.guess();
来做类似的事情来得到实际的时区名称moment.tz.guess();
从http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/
很简单,只需使用JavaScript getTimezoneOffset
函数即可:
-new Date().getTimezoneOffset()/60;
使用PHPdatefunction,您将获得站点所在服务器的date时间。 获得用户时间的唯一方法是使用JavaScript。
但是我build议你,如果你的网站有注册要求,那么最好的办法是在注册时要求用户作为必修课。 您可以在注册页面列出不同的时区并将其保存到数据库中。 在此之后,如果用户login到站点,则可以根据用户select的时区为该会话设置默认时区。 您可以使用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(); ?>
但根据我的观点,最好是向用户询问你的项目是否必须注册。
任何人都知道任何将IP与地理位置相匹配的服务
那么,幸运的是,你可以在我们自己的stackoverflow网站上find答案: 如何根据某个IP获取国家?
扰stream板: http : //www.hostip.info/use.html
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 Timestamp格式的时间提供给这个函数,javascript已经知道了用户的时区。
喜欢这个:
PHP:
echo '<script type="text/javascript"> var eltimio = maketimus('.$unix_timestamp_ofshiz.'); document.write(eltimio); </script><noscript>pls enable javascript</noscript>';
这将始终正确地显示时间正确的时间,人们已经设置在他的电脑时钟,不需要任何人问任何人,并将其保存到地方感谢上帝!
不要使用IP地址来确定位置(和时区) – 这是因为在NAT,代理(越来越stream行)和VPN,IP地址不一定真实地反映用户的实际位置,而是服务器的位置实施那些协议驻留。
类似于地区代码如何不再用于定位电话用户,因为号码携带的普及。
上面显示的IP和其他技术对于build议用户可以调整/更正的默认值是有用的。
魔法似乎都在
visitortime.getTimezoneOffset()
这很酷,我不知道。 它在IE等工作? 从那里你应该可以使用JS来ajax,设置cookie,不pipe。 我可能会自己去cookies路线。
你需要允许用户改变它。 我们之前尝试过使用地理位置(通过maxmind)来做这个,而且这个错误经常是错误的 – 足以让它不值得做,所以我们只是让用户把它设置在他们的个人资料中,并向用户显示一个通知还没有设置他们的。
如果您碰巧使用OpenID进行身份validation, 简单注册扩展将解决经过身份validation的用户的问题(您需要将tz从数字转换为数字)。
另一种select是从用户代理的国家偏好中推断出时区。 这是一个有点粗糙的方法(不适用于en-US),但是是一个很好的近似。
一个简单的方法是使用:
new Date().getTimezoneOffset();
这里是一篇文章(含源代码),解释了如何确定和使用ASP.NET(VB.NET,C#)应用程序中的本地化时间:
是时候了
简而言之,所描述的方法依赖于JavaScript getTimezoneOffset
函数,该函数返回保存在会话cookie中并由代码隐藏使用的值,以便在GMT和本地时间之间调整时间值。 好的是用户不需要指定时区(代码自动执行)。 还有更多的参与(这就是为什么我链接到文章),但提供的代码使它很容易使用。 我怀疑你可以把逻辑转换成PHP和其他语言(只要你理解ASP.NET)。
简单与JS
和PHP
:
即使用户可以弄乱他的内部时钟和/或时区,我发现到目前为止,获得偏移量的最佳方式仍然是new Date().getTimezoneOffset();
。 它的无创性,不会给头痛,并消除依赖第三方的需要。
假设我有一个包含字段date_created int(13)
的表users
,用于存储unix时间戳;
假设一个客户端creates a new account
,数据收到post
,我需要insert/update
date_created column
与客户端的Unix时间戳,而不是服务器的。
由于在插入/更新时需要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:ia");//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:ia",$date_created);//return it to the user or whatever
现在,当插入first
时间戳的时候,这个例子可能适合您的需要…当涉及到附加的时间戳或表格时,您可能要考虑将tzo值插入到用户表中以供将来参考或设置它作为会议或作为一个cookie。
PS但如果用户旅行和切换时区怎么办? 以GMT + 4login,快速到达GMT-1并重新login。 上次login将在未来。
我想…我们想太多了。
试试这个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']; ?>
一种可能的select是使用RFC 7231中定义的Date
标头字段,并且应该包含时区。 当然,并不能保证这个价值真的是客户的时区,但它可以是一个方便的起点。
这是我怎么做的。 这会将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.tz.guess() "America/Asuncion"
在PHP中获取有效的TZ数据库时区名称是一个两步骤的过程:
1)使用Javascript,通过getTimezoneOffset
获得时区偏移量,以分钟为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它也包含一个演示。