我想通过 PHP 中的 IP 地址获取时区。实际上,我有一个将在客户端机器上运行的应用程序。我有客户端机器的 IP 地址。但我无法获得每台客户端机器的时区。
9 回答
$ip = "189.240.194.147"; //$_SERVER['REMOTE_ADDR']
$ipInfo = file_get_contents('http://ip-api.com/json/' . $ip);
$ipInfo = json_decode($ipInfo);
$timezone = $ipInfo->timezone;
date_default_timezone_set($timezone);
echo date_default_timezone_get();
echo date('Y/m/d H:i:s');
有时它在本地服务器上不起作用,所以在服务器上尝试。
编辑:此数据来自ip-api.com,只要您每分钟不超过 45 个请求并且不使用商业用途,它们就可以免费使用。看他们的TOS,不是很长的一页。
甚至不能依靠 IP 地址映射到一个国家;如果您还想获得时区,那您就如履薄冰。您最好让客户端向您发送时区,也许在标题中。
请参阅Tor:在线匿名,这是停止将 IP 地址用于非设计用途的另一个原因。
如果你在本地机器上运行它,你可以检查配置的时区。
http://www.php.net/manual/en/function.date-default-timezone-get.php
有很多更好、更可靠的方法,然后尝试使用 GeoIP 猜测时区。如果您感觉幸运,请尝试:http ://www.php.net/manual/en/book.geoip.php
$region = geoip_region_by_name('www.example.com');
$tz = geoip_time_zone_by_country_and_region($region['country_code'],
$region['region']);
没有绝对确定的方法来获取客户的时区,但是如果您让客户从他们的机器上提交日期和时间,您可以根据它相对于 GMT 的时间来计算它。因此,如果他们的机器上是晚上 7:00 并且是格林威治标准时间上午 12:00,那么您可以确定他们是格林威治标准时间或 (EST/DST) 的 -5
通过他或她的 IP 地址搜索用户的时区不是一个好主意,因为他可以在不同的时间从不同的地方访问他或她的帐户。所以不可能通过ip地址定位到他的时区。但我试图找到一个解决方案,我在这里给出我的代码。对编码技术的任何批评都将受到高度赞赏。
<?php
$time_zone = getTimeZoneFromIpAddress();
echo 'Your Time Zone is '.$time_zone;
function getTimeZoneFromIpAddress(){
$clientsIpAddress = get_client_ip();
$clientInformation = unserialize(file_get_contents('http://www.geoplugin.net/php.gp?ip='.$clientsIpAddress));
$clientsLatitude = $clientInformation['geoplugin_latitude'];
$clientsLongitude = $clientInformation['geoplugin_longitude'];
$clientsCountryCode = $clientInformation['geoplugin_countryCode'];
$timeZone = get_nearest_timezone($clientsLatitude, $clientsLongitude, $clientsCountryCode) ;
return $timeZone;
}
function get_client_ip() {
$ipaddress = '';
if (getenv('HTTP_CLIENT_IP'))
$ipaddress = getenv('HTTP_CLIENT_IP');
else if(getenv('HTTP_X_FORWARDED_FOR'))
$ipaddress = getenv('HTTP_X_FORWARDED_FOR');
else if(getenv('HTTP_X_FORWARDED'))
$ipaddress = getenv('HTTP_X_FORWARDED');
else if(getenv('HTTP_FORWARDED_FOR'))
$ipaddress = getenv('HTTP_FORWARDED_FOR');
else if(getenv('HTTP_FORWARDED'))
$ipaddress = getenv('HTTP_FORWARDED');
else if(getenv('REMOTE_ADDR'))
$ipaddress = getenv('REMOTE_ADDR');
else
$ipaddress = 'UNKNOWN';
return $ipaddress;
}
function get_nearest_timezone($cur_lat, $cur_long, $country_code = '') {
$timezone_ids = ($country_code) ? DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $country_code)
: DateTimeZone::listIdentifiers();
if($timezone_ids && is_array($timezone_ids) && isset($timezone_ids[0])) {
$time_zone = '';
$tz_distance = 0;
//only one identifier?
if (count($timezone_ids) == 1) {
$time_zone = $timezone_ids[0];
} else {
foreach($timezone_ids as $timezone_id) {
$timezone = new DateTimeZone($timezone_id);
$location = $timezone->getLocation();
$tz_lat = $location['latitude'];
$tz_long = $location['longitude'];
$theta = $cur_long - $tz_long;
$distance = (sin(deg2rad($cur_lat)) * sin(deg2rad($tz_lat)))
+ (cos(deg2rad($cur_lat)) * cos(deg2rad($tz_lat)) * cos(deg2rad($theta)));
$distance = acos($distance);
$distance = abs(rad2deg($distance));
// echo '<br />'.$timezone_id.' '.$distance;
if (!$time_zone || $tz_distance > $distance) {
$time_zone = $timezone_id;
$tz_distance = $distance;
}
}
}
return $time_zone;
}
return 'unknown';
}
这不是直截了当的,但我得到了时间,包括使用 jquery 和 php 的 2 个 api 调用的夏令时偏移量。所有这些都可以很容易地在 PHP 中完成,只需稍加调整即可。我确信这也可以以不同的方式布局,但我只是从现有的代码中获取它,这适合我当时的需要。
jQuery/php:
function get_user_time(){
var server_time = <? echo time(); ?>; //accuracy is not important it's just to let google know the time of year for daylight savings time
$.ajax({
url: "locate.php",
dataType: "json",
success: function(user_location) {
if(user_location.statusCode=="OK"){
$.ajax({
url: "https://maps.googleapis.com/maps/api/timezone/json?location="+user_location.latitude+","+user_location.longitude+"×tamp="+server_time+"&sensor=false",
dataType: "json",
success: function(user_time) {
if(user_time.statusCode=="error"){
//handle error
}else{
user_time.rawOffset /= 3600;
user_time.dstOffset /= 3600;
user_real_offset = user_time.rawOffset+user_time.dstOffset+user_time.utc;
//do something with user_real_offset
}
}
});
}
}
});
}
定位.php
function get_client_ip() {
$ipaddress = '';
if ($_SERVER['HTTP_CLIENT_IP'])
$ipaddress = $_SERVER['HTTP_CLIENT_IP'];
else if($_SERVER['HTTP_X_FORWARDED_FOR'])
$ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
else if($_SERVER['HTTP_X_FORWARDED'])
$ipaddress = $_SERVER['HTTP_X_FORWARDED'];
else if($_SERVER['HTTP_FORWARDED_FOR'])
$ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
else if($_SERVER['HTTP_FORWARDED'])
$ipaddress = $_SERVER['HTTP_FORWARDED'];
else if($_SERVER['REMOTE_ADDR'])
$ipaddress = $_SERVER['REMOTE_ADDR'];
else
$ipaddress = 'UNKNOWN';
return $ipaddress;
}
$location = file_get_contents('http://api.ipinfodb.com/v3/ip-city/?key=xxxxxxxxx&ip='.get_client_ip().'&format=json');
$location = json_decode($location,true);
if(is_array($location)){
date_default_timezone_set('UTC');
$location['utc'] = time();
echo json_encode($location);
}else{
echo '{"statusCode":"error"}';
}
在此处注册免费密钥:http: //ipinfodb.com/register.php(没有限制,但如果每秒请求超过 1 个,则排队)
查看 Maxmind GeoLite2 数据库。它包含有关大多数 IP 地址的大陆/国家/城市和纬度/经度的详细信息,包括time_zone,如下所示。
我在这里描述了如何编译 PHP 扩展,以及如何在 PHP 中使用 mmdb 数据库:
如果您需要知道浏览您网页的用户的时区,那么您可以使用IP2LOCATION之类的服务来猜测时区。但请记住,正如 altCognito 所说,这不是告诉客户时区的 100% 准确的方法。这种方法存在一些准确性问题。
这是一个使用将 IP 地址映射到时区的位置 API的示例,例如发送请求并https://ipapi.co/<IP-Address>/timezone/
返回该 IP 地址的时区。
PHP 代码
file_get_contents('https://ipapi.co/1.2.3.4/timezone/');
准确率并非像其他人所说的那样是 100%。