是否有一种标准的方法可以让服务器在网页中确定用户的时区?

可能来自HTTP报头或用户代理字符串的一部分?


当前回答

使用Unkwntech的方法,我用jQuery和PHP编写了一个函数。这是经过测试和工作!

在您希望将时区作为变量的PHP页面上,在页面顶部附近放置以下代码片段:

<?php
    session_start();
    $timezone = $_SESSION['time'];
?>

这将读取会话变量“time”,这是我们现在将要创建的。

在同一个页面上,在<head>中,首先需要包含jQuery:

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>

同样在<head>, 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://example.org/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)或您所在的任何时区。

其他回答

有几种方法可以在浏览器中确定时区。如果您的浏览器提供并支持一个标准函数,那么您就应该使用它。下面是用不同格式获取相同信息的三种方法。避免使用基于特定假设或硬编码区域列表进行猜测的非标准解决方案,尽管如果没有其他办法,它们可能会有所帮助。

一旦你有了这个信息,你可以把它作为一个非标准的请求头传递给服务器,并在那里使用它。如果你还需要时区偏移量,你也可以在头文件中或请求有效载荷中传递给服务器,可以使用dateObj.getTimezoneOffset()来检索。

使用Intl API获取Olson格式(标准和推荐的方式):注意,这不是所有浏览器都支持。有关浏览器对此的支持的详细信息,请参阅此链接。 这个API可以让你获得Olson格式的时区,例如亚洲/加尔各答,美国/纽约等。

Intl . DateTimeFormat () timeZone resolvedOptions()。

使用Date对象获得较长的格式,如印度标准时间,东部标准时间等:这是所有浏览器支持的。

let dateObj =新的日期(2021,11,25,09,30,00); / /然后 dateObj.toString () / /收益率 2021年12月25日星期六09:30:00 GMT+0530(印度标准时间)//我位于印度(IST)

注意,字符串包含长格式和短格式的时区信息。你现在可以使用regex来获取这些信息:

let longZoneRegex = /\((.+)\)/; dateObj.toString () .match (longZoneRegex); / /收益率 ['(印度标准时间)','印度标准时间',索引:34,输入:' 2021年12月25日星期六09:30:00 GMT+0530(印度标准时间)',组:未定义] //注意output是一个数组,所以使用output[1]来获取时区名称。

使用Date对象获取短格式,如GMT+0530, GMT-0500等:所有浏览器都支持。

类似地,你也可以得到短格式:

let shortZoneRegex = /GMT[+-]\d{1,4}; dateObj.toString () .match (shortZoneRegex); / /收益率 ['GMT+0530',索引:25,输入:' 2021年12月25日星期六09:30:00 GMT+0530(印度标准时间)',分组:未定义] //注意output是一个数组,所以使用output[0]来获取时区名称。

首先,了解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.

最终,更好的方法是向用户询问他们所在的时区。提供一个他们可以改变的设置。你可以使用上面的选项之一来选择一个默认设置,但不要让它不可能偏离你的应用程序。

还有一种完全不同的方法,即完全不依赖用户电脑的时区设置。相反,如果可以收集纬度和经度坐标,则可以使用以下方法之一将它们解析为时区。这在移动设备上效果很好。

简单,只需使用JavaScript的getTimezoneOffset函数,如下所示:

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

这里有一种更完整的方法。

获取用户的时区偏移量 测试一些日子的夏令时边界,以确定它们是否在使用夏令时的区域。

节选如下:

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;
}

从JS获取TZ和DST(通过Way Back Machine)

不要使用IP地址来明确地确定位置(以及时区)——这是因为使用NAT、代理(越来越流行)和vpn, IP地址不一定真实地反映用户的实际位置,而是反映实现这些协议的服务器所在的位置。

类似于美国的区号对于定位电话用户不再有用,因为号码可携性很流行。

IP地址和上面显示的其他技术对于建议用户可以调整/纠正的默认值很有用。