我需要知道我的用户目前在哪个时区基于他们的IP或http标头。
关于这个问题,我得到了很多答案,但我无法理解这些答案。有人说使用-new Date().getTimezoneOffset()/60
(from here)。但是这是什么意思?
我的(index.php)页面的根目录中有date_default_timezone_set("Asia/Calcutta");
。因此,我必须动态获取时区并将其设置为Asia/Calcutta
。
答案 0 :(得分:34)
总结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(); //'Asia/Kolhata' for 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>
答案 1 :(得分:23)
浏览器的时区信息不是HTTP规范的一部分,因此您无法从标题中获取它。
如果您有位置坐标(例如,来自移动设备GPS),那么您可以找到时区using one of these methods。但是,按IP地址进行地理定位并不是一个很好的解决方案,因为IP通常是ISP或代理服务器,可能位于另一个时区。
您可以使用一些策略来尝试检测时区,例如使用jsTimeZoneDetect库,这是一个很好的起点,但不够完善,您不能仅仅依靠它。如果你正在使用moment.js,那么在时间 - 时区中有一个名为moment.tz.guess()
的内置函数可以做同样的事情。
使用JavaScript getTimezoneOffset()
函数的想法存在缺陷,因为您没有获得时区 - 只是特定日期的单个偏移量。请参阅the TimeZone tag wiki标题为“TimeZone!= Offset”的部分。
但是你看一下,最终你必须决定两种方法之一:
OR
我在this answer中更详细地讨论了这个问题(从c#角度来看)。
答案 2 :(得分:2)
依赖关系:
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/>';
答案 3 :(得分:1)
一个解决方案是问他们!特别是在可以捕获/注册用户的成员系统上 - 在那时给他们一个选择。简单但准确。
答案 4 :(得分:0)
这很好......
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'));
答案 5 :(得分:0)
HTTP标头中没有时区,但country(缩写)位于ACCEPT_LANGUAGE标头中。它会像&#34; en-US&#34; (美国是国家代码)。这可以与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;
}
返回一个字符串,如&#34; -6S1&#34;对于中心区域(标准时间偏移为-6小时,DST在夏季活动并增加1小时)。我使用cookie将其提供给PHP。 PHP在TZ数据库中搜索与此匹配的区域和国家/地区。对于这里(美国,-6S1),有7个匹配区域,第一个是#34; America / Chicago&#34;。
顺便说一下,数据库中有2个区域,其中DST增加了1小时以外的东西:豪勋爵岛(10.5W0.5)和南极洲巨魔站(0W2)。