确定用户的时区

jneque 发布于 2018-02-02 browser 最后更新 2018-02-02 11:28 1527 浏览

Web Server是否有任何标准的方法来确定用户在网页中的时区?也许从HTTP头或用户代理字符串的一部分?

已邀请:

eomnis

赞同来自:

虽然有人建议将它包含在HTTP规范中,但是目前还没有HTTP头将会报告客户端的时区。 如果是我,我可能会尝试使用客户端JavaScript获取时区,然后使用Ajax或其他方式将其提交给服务器。

baut

赞同来自:

Javascript是获取客户当地时间最简单的方法。我建议使用XMLHttpRequest发回本地时间,如果失败,则根据IP地址回退到检测到的时区。 就地理定位而言,我已经在几个项目上使用了MaxMind GeoIP,并且效果很好,但我不确定它们是否提供时区数据。这是您付费的服务,并且每月提供您的数据库更新。他们提供几种网页语言的包装。

aeius

赞同来自:

确定我所看到的时区的最流行的(==标准?)方式就是询问用户自己.如果您的网站需要订阅,可以将其保存在用户的个人资料数据中。对于匿名用户,日期可以显示为UTC或GMT等。 我不想成为一个聪明的笨蛋。只是有时候一些问题在任何编程环境之外都有更好的解决方案。

nerror

赞同来自:

魔法似乎都在

visitortime.getTimezoneOffset()
这很酷,我不知道。它在IE等工作? 从那里你应该可以使用JS来ajax,设置cookie,不管。我可能会自己去饼干路线。 你需要允许用户改变它。我们之前尝试过使用地理位置(通过maxmind)来做这个,而且这个错误经常是错误的 - 足以让它不值得做,所以我们只是让用户把它设置在他们的个人资料中,并向用户显示一个通知还没有设置他们的。

umodi

赞同来自:

Anyone know of any services that will match IP to geographic location
那么,幸运的是,你可以在我们自己的stackoverflow网站找到答案: How to get the Country according to a certain IP? 扰流板:http://www.hostip.info/use.html

nodit

赞同来自:

如果您碰巧正在使用OpenID进行身份验证,则Simple Registration Extension将为经过身份验证的用户解决问题(您需要将tz从数字转换为数字)。 另一种选择是从用户代理的国家偏好中推断出时区。这是一个有点粗糙的方法(不适用于en-US),但可以很好地近似。

tut

赞同来自:

-new Date().getTimezoneOffset()/60;
getTimezoneOffset()将从GMT中减去您的时间并返回分钟数。所以如果你住在格林尼治标准时间8时,它将返回480.要把这个数字除以60.另外,请注意,这个标志与你所需要的相反 - 它计算的是GMT时差,而不是你的时差时区与GMT的偏移。要解决这个问题,只需乘以-1。 Edit 另请注意,w3school表示:
The returned value is not a constant, because of the practice of using Daylight Saving Time.

onon

赞同来自:

这里有一篇文章(含源代码),解释了如何确定和使用ASP.NET(VB.NET,C#)应用程序中的本地化时间: It's About Time 简言之,所描述的方法依赖于JavaScript getTimezoneOffset函数,该函数返回保存在会话cookie中并由代码隐藏使用的值,以调整GMT和当地时间之间的时间值。好的是用户不需要指定时区(代码自动执行)。还有更多的参与(这就是为什么我链接到文章),但提供的代码使它很容易使用。我怀疑你可以将逻辑转换为PHP和其他语言(只要你理解ASP.NET)。

fillum

赞同来自:

使用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();
?>
但根据我的观点,最好是向用户询问你的项目是否必须注册。

qullam

赞同来自:

这是一个更完整的方法。

  1. 获取用户的时区偏移量
  2. 在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(通过回机器)

uharum

赞同来自:

使用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>
您可能注意到,也可能没有注意到,但是您需要将url更改为您的实际域。 最后一件事。你可能想知道什么是timezone.php。那么,这只是: (创建一个名为timezone.php的新文件,并用上面的url指向它)
<?php
    session_start();
    $_SESSION['time'] = $_GET['time'];
?>
如果这个工作正常,它将首先加载页面,执行JavaScript,并重新加载页面。然后,您将能够阅读$ timezone变量并使用它来享受您的乐趣!它返回当前的UTC/GMT时区偏移量(GMT -7)或者你所在的任何时区。

in_ut

赞同来自:

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>';
这将总是正确地显示时间的基础上,人们已经设置在他的电脑时钟的时区,无需向任何人询问任何东西,并保存到地方感谢上帝!

icum

赞同来自:

一个简单的方法是使用:

new Date().getTimezoneOffset();

wnihil

赞同来自:

这是我怎么做的。这会将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
?>

qea

赞同来自:

很简单,只需使用JavaScript getTimezoneOffset函数即可:

-new Date().getTimezoneOffset()/60;

jfugit

赞同来自:

试试这个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'];
?>

eomnis

赞同来自:

这是一个强大的JavaScript解决方案,用于确定浏览器所在的时区。

>>> var timezone = jstz.determine();
>>> timezone.name(); 
"Europe/London"
https://bitbucket.org/pellepim/jstimezonedetect

veos

赞同来自:

我还没有看到一个详细的答案在这里得到的时区。你不需要通过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格式化时区的健壮的插件更容易: https://github.com/scottwater/jquery.detect_timezone

vfugit

赞同来自:

使用jQuery将AJAX请求上的时区偏移量作为HTTP头提交

$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        xhr.setRequestHeader("X-TZ-Offset", -new Date().getTimezoneOffset()/60);
    }
});
您还可以使用http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/中的moment.tz.guess();来执行类似的操作,以获取实际的时区名称

est_et

赞同来自:

不要使用IP地址来确定位置(和时区) - 这是因为在NAT,代理(越来越流行)和VPN,IP地址不一定真实地反映用户的实际位置,而是服务器的位置实施那些协议驻留。 类似于地区代码如何不再用于定位电话用户,因为号码携带的普及。 上面显示的IP和其他技术对于建议用户可以调整/更正的默认非常有用。

asaepe

赞同来自:

一种可能的选择是使用在RFC 7231中定义的Date头字段,并且应该包含时区。当然,并不能保证这个价值真的是客户的时区,但它可以是一个方便的起点。

gut

赞同来自:

JSPHP简单: 即使用户可以弄乱他的内部时钟和/或时区,我发现到目前为止,获得偏移量的最佳方式仍然是new Date().getTimezoneOffset();。它的无创性,不会给头痛,并消除依赖第三方的需要。 假设我有一个表users,它包含一个字段date_created int(13),用于存储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: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。 附:但是如果用户旅行和切换时区呢?以GMT + 4登录,快速到达GMT-1并重新登录。上次登录将在未来。 我想...我们想太多了。

mest

赞同来自:

你可以在客户端上用moment-timezone来完成,并把值发送给服务器。样本用法:

> moment.tz.guess()
"America/Asuncion"

xeos

赞同来自:

在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 它也包含一个演示。