我需要知道我的用户目前在什么时区基于他们的IP或http头。
关于这个问题,我得到了很多答案,但我无法理解这些答案。有人说用-new Date().getTimezoneOffset()/60
(从这里)。但这是什么意思呢?我有一个date_default_timezone_set("Asia/Calcutta");
在我的(index.php)页面的根。因此,为此,我必须动态地获取时区并将其设置在Asia/Calcutta
的位置。
用代码来总结Matt Johnson的回答:
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js">
</script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jstimezonedetect/1.0.4/jstz.min.js">
</script>
<script type="text/javascript">
$(document).ready(function(){
var tz = jstz.determine(); // Determines the time zone of the browser client
var timezone = tz.name(); //For e.g.:"Asia/Kolkata" for the Indian Time.
$.post("url-to-function-that-handles-time-zone", {tz: timezone}, function(data) {
//Preocess the timezone in the controller function and get
//the confirmation value here. On success, refresh the page.
});
});
</script>
浏览器的时区信息不是HTTP规范的一部分,所以你不能从标头中获取它。
如果您有位置坐标(例如来自移动设备GPS),那么您可以使用这些方法之一找到时区。然而,通过IP地址进行地理定位并不是一个很好的解决方案,因为IP通常是位于另一个时区的ISP或代理服务器的IP。
您可以使用一些策略来尝试检测时区,例如使用jsTimeZoneDetect库,这是一个很好的起点,但是不够完美,您不能仅仅依赖于它。如果你使用的是moment.js,在moment-timezone中有一个内置的函数叫做moment.tz.guess()
,它可以做同样的事情。
使用JavaScript的getTimezoneOffset()
函数的想法是有缺陷的,因为你没有得到一个时区-只是一个特定日期的偏移量。请参阅TimeZone标签wiki的标题为"TimeZone != Offset"的部分。
无论你怎么看,最终你必须在两种方法中选择一种:
- 要求用户告诉你他们的时区,从某种下拉列表或基于地图的时区选择器控件。
或
- 仅以UTC格式向浏览器发送时间,并在浏览器上使用JavaScript将时间转换为用户计算机设置的任何本地时区。
我将从c#的角度更详细地讨论这个问题。
依赖:
- http://www.maxmind.com/download/geoip/api/php/php-latest.tar.gz http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
//Get remote IP $ip = $_SERVER['REMOTE_ADDR']; //Open GeoIP database and query our IP $gi = geoip_open("GeoLiteCity.dat", GEOIP_STANDARD); $record = geoip_record_by_addr($gi, $ip); //If we for some reason didnt find data about the IP, default to a preset location. if(!isset($record)) { $record = new geoiprecord(); $record->latitude = 59.2; $record->longitude = 17.8167; $record->country_code = 'SE'; $record->region = 26; } //Calculate the timezone and local time try { //Create timezone $user_timezone = new DateTimeZone(get_time_zone($record->country_code, ($record->region!='') ? $record->region : 0)); //Create local time $user_localtime = new DateTime("now", $user_timezone); $user_timezone_offset = $user_localtime->getOffset(); } //Timezone and/or local time detection failed catch(Exception $e) { $user_timezone_offset = 7200; $user_localtime = new DateTime("now"); } echo 'User local time: ' . $user_localtime->format('H:i:s') . '<br/>'; echo 'Timezone GMT offset: ' . $user_timezone_offset . '<br/>';
引用:SGet访问本地时间,日出和日落时间的IP与MaxMind GeoIP和PHP由Stanislav Khromov
一个解决方案是问他们!特别是在会员系统中,你可以捕获/注册用户——在这一点上给他们一个选择。简单而准确。
这很好…
echo <<<EOE
<script type="text/javascript">
if (navigator.cookieEnabled)
document.cookie = "tzo="+ (- new Date().getTimezoneOffset());
</script>
EOE;
if (!isset($_COOKIE['tzo'])) {
echo <<<EOE
<script type="text/javascript">
if (navigator.cookieEnabled) document.reload();
else alert("Cookies must be enabled!");
</script>
EOE;
die();
}
$ts = new DateTime('now', new DateTimeZone('GMT'));
$ts->add(DateInterval::createFromDateString($_COOKIE['tzo'].' minutes'));
时区在HTTP报头中不可用,但是国家(缩写)在ACCEPT_LANGUAGE报头中。它会像"en-US"(美国是国家代码)。可以将此信息与JavaScript信息结合使用,以便更好地了解用户的时区。
这是我在JS中使用的:
function timezone() {
var now = new Date();
var jano = new Date(now.getFullYear(), 0, 1).getTimezoneOffset()/-60;
var julo = new Date(now.getFullYear(), 6, 1).getTimezoneOffset()/-60;
var tz = Math.min(jano, julo);
if (jano != julo) tz += ((jano < julo) ? 'S' : 'W') + Math.abs(jano - julo);
return tz;
}
返回一个类似"-6S1"的字符串,表示中心区域(标准时间偏移为-6小时,夏令时在夏季有效并增加1小时)。我使用cookie使其对PHP可用。PHP在TZ数据库中搜索与之匹配的区域和国家。这里(US, -6S1)有7个匹配区域,第一个是"America/Chicago"。
顺便说一句,数据库中有两个区域的夏时制增加了1小时以外的时间:Lord Howe Island (10.5W0.5)和Troll Station, Antarctica (0W2)。