是否有一种标准的方法可以让服务器在网页中确定用户的时区?
可能来自HTTP报头或用户代理字符串的一部分?
是否有一种标准的方法可以让服务器在网页中确定用户的时区?
可能来自HTTP报头或用户代理字符串的一部分?
当前回答
使用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();
?>
但在我看来,最好是询问用户在你的项目中是否必须注册。
其他回答
所有的魔力似乎都在
visitortime.getTimezoneOffset()
真酷,我还不知道呢。它能在ie浏览器上运行吗?从这里你应该能够使用JavaScript到Ajax,设置cookie等等。我自己可能也会吃饼干。
不过,您需要允许用户更改它。我们曾尝试使用地理定位(通过maxmind)来实现这一点,但这是错误的,不值得这么做。所以我们让用户在他们的配置文件中设置它,并向还没有设置的用户显示一个通知。
我是这样做的。这将把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
?>
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时间戳格式提供给该函数即可;JavaScript已经知道用户的时区。
是这样的:
PHP:
echo '<script type="text/javascript">
var eltimio = maketimus('.$unix_timestamp_ofshiz.');
document.write(eltimio);
</script><noscript>pls enable javascript</noscript>';
这将始终显示正确的时间基于时区的人已设置在他/她的计算机时钟。没有必要向任何人索取任何东西,把它保存到合适的地方,感谢上帝!
首先,了解JavaScript中的时区检测是不完善的。您可以在date对象的实例上使用getTimezoneOffset获取特定日期和时间的本地时区偏移量,但这与完整的IANA时区(如America/Los_Angeles)不完全相同。
以下是一些可行的方法:
大多数现代浏览器在实现ECMAScript国际化API时都支持IANA时区,所以你可以这样做:
const tzid = Intl.DateTimeFormat().solveOptions().timeZone; console.log(tzid);
结果是一个字符串,其中包含运行代码的计算机的IANA时区设置。
支持的环境列在Intl兼容性表中。展开DateTimeFormat部分,并查看名为resolvedOptions()的特性。timeZone默认为主机环境。
Some libraries, such as Luxon use this API to determine the time zone through functions like luxon.Settings.defaultZoneName. If you need to support an wider set of environments, such as older web browsers, you can use a library to make an educated guess at the time zone. They work by first trying the Intl API if it's available, and when it's not available, they interrogate the getTimezoneOffset function of the Date object, for several different points in time, using the results to choose an appropriate time zone from an internal data set. Both jsTimezoneDetect and moment-timezone have this functionality. // using jsTimeZoneDetect var tzid = jstz.determine().name(); // using moment-timezone var tzid = moment.tz.guess(); In both cases, the result can only be thought of as a guess. The guess may be correct in many cases, but not all of them. Additionally, these libraries have to be periodically updated to counteract the fact that many older JavaScript implementations are only aware of the current daylight saving time rule for their local time zone. More details on that here.
最终,更好的方法是向用户询问他们所在的时区。提供一个他们可以改变的设置。你可以使用上面的选项之一来选择一个默认设置,但不要让它不可能偏离你的应用程序。
还有一种完全不同的方法,即完全不依赖用户电脑的时区设置。相反,如果可以收集纬度和经度坐标,则可以使用以下方法之一将它们解析为时区。这在移动设备上效果很好。
我认为@Matt Johnson-Pints是目前为止最好的,CanIuse搜索显示它现在被广泛采用:
.timeZone .resolvedOptions https://caniuse.com/?search=Intl.DateTimeFormat () ()
其中一个挑战是考虑为什么要知道时区。因为我认为大多数人忽略了一件事,那就是他们是可以改变的!如果一个用户带着他的笔记本电脑从欧洲旅行到美国,如果你之前把它存储在数据库中,那么他们的时区现在是不正确的(即使用户从来没有更新过他们的设备时区)。这也是@Mads Kristiansen回答的问题,因为用户会旅行——你不能把它当作给定的。
例如,我的Linux笔记本电脑关闭了“自动时区”。虽然时间可能会更新我的时区却不会。
所以我相信答案是——你需要它做什么?客户端似乎提供了一种更简单的方法来确定它,但是客户端和服务器端代码都将依赖于用户更新他们的时区或自动更新。我当然可能是错的。