获得当前的GMT世界时间

时间:2009-01-28 21:58:41

标签: javascript

我如何获得当前时间? (在JavaScript中)

不是你电脑的时间:

now = new Date;
now_string = addZero(now.getHours()) + ":" + addZero(now.getMinutes()) + ":" + addZero(now.getSeconds());

但真正准确的世界时间?

我是否需要连接到服务器(很可能是,哪一个?我如何从中检索时间?)

我从谷歌搜索的所有搜索都会返回(new Date).getHours()

编辑:

如果用户的计算机时间错误,我希望避免显示错误的时间。

12 个答案:

答案 0 :(得分:26)

您可以使用JSON [P]并访问时间API:

(下面的代码应该可以正常工作,只需测试它......)

function getTime(zone, success) {
    var url = 'http://json-time.appspot.com/time.json?tz=' + zone,
        ud = 'json' + (+new Date());
    window[ud]= function(o){
        success && success(new Date(o.datetime));
    };
    document.getElementsByTagName('head')[0].appendChild((function(){
        var s = document.createElement('script');
        s.type = 'text/javascript';
        s.src = url + '&callback=' + ud;
        return s;
    })());
}

getTime('GMT', function(time){
    // This is where you do whatever you want with the time:
    alert(time);
});

答案 1 :(得分:20)

首先,要获得准确的GMT时间,您需要一个您信任的来源。这意味着某处服务器。 Javascript通常只能进行HTTP调用,而且只能访问托管相关页面的服务器(相同的源策略)。因此,该服务器必须是您的GMT时间来源。

我会将您的网络服务器配置为使用NTP将其时钟与GMT同步,并让网络服务器通过向页面写入变量来告诉脚本它的时间。或者,当您需要知道时间时,将make和XmlHttpRequest返回给服务器。缺点是由于所涉及的延迟,这将是不准确的:服务器确定时间,将其写入响应,响应通过网络传播,并且只要客户端的cpu给它一个时间片,javascript就会执行,等等。慢速链接如果页面很大,你可以预期延迟几秒钟。您可以通过确定用户时钟与GMT的距离来节省一些时间,并且只需通过该偏移调整所有时间计算。当然,如果用户的时钟速度很慢或很快(不仅仅是迟到或早期),或者如果用户在PC上更改时间,那么您的偏移量就会被烧毁。

另请注意,客户端可以更改数据,因此不要信任他们发送给您的任何时间戳。

修改JimmyP's answer非常简单易用:使用Javascript添加<script>元素,该元素调用诸如http://json-time.appspot.com/time.json?tz=GMT之类的网址。这比自己更容易,因为json-time.appspot.com服务器作为GMT时间的来源,并以允许您解决同源策略的方式提供此数据。对于简单的网站我会建议。但是它有一个主要缺点:json-time.appspot.com站点可以在用户的​​页面上执行任意代码。这意味着,如果该网站的运营商想要分析您的用户或劫持他们的数据,他们可以做到这一点。即使您信任运营商,您也需要相信他们没有被黑客入侵或受到攻击。对于商业网站或任何具有高可靠性问题的网站,我建议您自己托管时间解决方案。

编辑2 JimmyP's answer有一条评论表明json-time应用程序在其可以支持的请求数量方面存在一些限制。这意味着如果您需要可靠性,您应该自己托管时间服务器。但是,在服务器上添加一个响应相同格式数据的页面应该很容易。基本上,您的服务器会进行查询,例如

http://json-time.appspot.com/time.json?tz=America/Chicago&callback=foo

并返回一个字符串,如

foo({
 "tz": "America\/Chicago", 
 "hour": 15, 
 "datetime": "Thu, 09 Apr 2009 15:07:01 -0500", 
 "second": 1, 
 "error": false, 
 "minute": 7
})

注意包装JSON对象的foo();这对应于查询中的callback = foo。这意味着当脚本加载到页面中时,它将调用你的foo函数,它可以随时随地执行任何操作。此示例的服务器端编程是一个单独的问题。

答案 2 :(得分:6)

为什么不在每个页面上发送时间?例如html中的某个地方:

<span id="time" style="display:none;">
    2009-03-03T23:32:12
</span>

然后,您可以在网站加载并解释日期时运行Javascript。这将减少网络必须完成的工作量。您可以存储相应的本地时间并在每次需要时计算偏移量。

答案 3 :(得分:3)

您可以使用getTimezoneOffset获取本地日期与GMT之间的偏移量,然后进行数学计算。但这只会像用户的时钟一样准确。

如果您想要准确的时间,则应连接到NTP server。由于Same Origin Policy,您无法使用JS向另一台服务器发出请求。我建议你创建一个连接到NTP服务器的服务器端脚本(用PHP或任何你想要的语言)并返回准确的日期。然后,使用AJAX请求来读取此时间。

答案 4 :(得分:3)

Mr. Shiny and NewJames答案的一点点补充

这是一个PHP脚本,您可以将其放在自己的服务器上,而不是使用json-time.appspot.com

<?php
header('Content-Type: application/json');
header("Expires: Tue, 01 Jan 1990 00:00:00 GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

$error = "false";
$tz = $_GET['tz'];

if ( !in_array($tz, DateTimeZone::listIdentifiers())) {
   $error = 'invalid time zone';
   $tz = 'UTC';
}

date_default_timezone_set($tz);

?>
<?php echo htmlspecialchars($_GET['callback'], ENT_QUOTES, 'UTF-8' ); ?>({
 "tz": "<?php echo $tz ?>",
 "hour": <?php echo date('G'); ?>,
 "datetime": "<?php echo date(DATE_RFC2822); ?>",
 "second": <?php echo intval(date('s')); ?>,
 "error": "<?php echo $error; ?>",
 "minute": <?php echo intval(date('i')); ?>
})

答案 5 :(得分:2)

就像Mr. Shiny and New所说的那样,你需要一个服务器,并且时间正确。它可以是您站点所在的服务器,也可以是您可以阅读的格式发送正确时间的其他服务器。

如果您想在页面上多次使用日期,相隔一秒或几秒钟,您可能不希望每次都从服务器获取时间,而是缓存差异并使用客户端时钟。如果是这种情况,这里有许多解决方案之一:

var MyDate = new function() {
    this.offset = 0;
    this.calibrate = function (UTC_msec) {
        //Ignore if not a finite number
        if (!isFinite(UTC_msec)) return;

        // Calculate the difference between client and provided time
        this.offset = UTC_msec - new Date().valueOf();

        //If the difference is less than 60 sec, use the clients clock as is.
        if (Math.abs(this.offset) < 60000) this.offset = 0;
    }
    this.now = function () {
        var time = new Date();
        time.setTime(this.offset + time.getTime());
        return time;
    }
}();

将其包含在您的页面上,让服务器端脚本生成如下行:

MyDate.calibrate(1233189138181);

其中数字是自1970年1月1日以来的当前时间(以毫秒为单位)。您还可以使用自己喜欢的AJAX框架并让它调用上面的函数。或者您可以使用建议的解决方案JimmyP。我已经重写了JimmyPs解决方案以包含在我的解决方案中。只需在上面的函数中复制并粘贴以下内容:

    this.calibrate_json = function (data) {
        if (typeof data === "object") {
            this.calibrate (new Date(data.datetime).valueOf() );
        } else {
            var script = document.createElement("script");
            script.type="text/javascript";
            script.src=(data||"http://json-time.appspot.com/time.json?tz=UTC") +
                "&callback=MyDate.calibrate_json";
            document.getElementsByTagName('head')[0].appendChild(script);
        }
    }
    this.calibrate_json(); //request calibration with json

请注意,如果从 MyDate 更改函数名称,则必须更新 script.src this.calibrate_json 中的回调

说明:

Mydate.offset 是服务器时间和客户端时钟之间的当前偏移量,以毫秒为单位。

Mydate.calibrate(x); 是一个设置新偏移量的函数。它期望输入是自1970年1月1日以来的当前时间(以毫秒为单位)。如果服务器和客户端时钟之间的差异小于60秒,则将使用客户端时钟。

Mydate.now()是一个返回具有当前校准时间的日期对象的函数。

Mydate.calibrate_json(data)是一个函数,它将url带到返回日期时间回复的资源,或带有当前时间的对象(用作回调)。如果没有提供任何内容,它将使用默认URL来获取时间。网址必须带有问号“?”在它。

如何使用当前时间每秒更新元素的简单示例:

setInterval(
    function () {
        var element = document.getElementById("time");
        if (!element) return;
        function lz(v) {
            return v < 10 ? "0" + v : v;
        }
        var time = MyDate.now();
        element.innerHTML = time.getFullYear() + "-" +
            lz(time.getMonth() + 1) + "-" +
            lz(time.getDate()) + " " +
            lz(time.getHours()) + ":" +
            lz(time.getMinutes()) + ":" +
            lz(time.getSeconds())
        ;
},1000);

答案 6 :(得分:2)

我偶然发现了那些无法访问服务器端的人的解决方案。 An answer问题Getting the default server time in jQuery?

基本上,您可以通过对“/”执行AJAX HEAD请求来获取“Date”标头。并非所有服务器都支持此功能,并且可能需要一些jiggery-pockery才能使其与特定服务器一起使用。

Check out the real answer了解详情。

答案 7 :(得分:0)

我们使用了EarthTools的API取得了很大的成功:

EarthTools

该服务返回XML,其中包含当前GMT和&amp ;;时区偏移(提供纬度和经度时)。我们在ASP.NET页面的VB后端使用WebClient和XMLDocument来读取&amp;解释XML。

答案 8 :(得分:0)

您可以在PHP中执行此操作

<?php
$json = file_get_contents( "http://json-time.appspot.com/time.json?tz=GMT" );
$obj = json_decode($json);
$timenow= $obj->{'datetime'};
$hournow= $obj->{'hour'}; 
$minutenow= $obj->{'minute'}; 
$secondnow= $obj->{'second'}; 
?>

$timenow包含您的完整日期&amp;时间:“星期一,2012年3月5日01:57:51 +0000”,$hournow:“1” $minutenow:“57”。

答案 9 :(得分:0)

由于与James's答案相关的服务似乎不再起作用,我找到了另一个可以用于此目的的良好的休息API,并且它工作正常。 源代码是这个站点:timeapi,您可以使用的代码就是这样(使用API​​提供的jQuery库和jsonp回调):

 $.getJSON("http://www.timeapi.org/utc/now.json?callback=?",function(json){
       //console.log(json)
       alert(json.dateString);
 });

有了这个,你就会有像

那样的日期和时间
  September 02, 2016 09:59:42 GMT+0100

如果你想在javascript中操作它,要有时间,只需在Date对象中转换它:

  new Date(json.dateString)

因此,例如,您可以这样写:

   $.getJSON("http://www.timeapi.org/utc/now.json?callback=?",function(json){

         var now = new Date(json.dateString);
         var hours = now.toLocaleTimeString();

         alert(hours)

    });
以这种方式,您将获得准确的当地时间。

答案 10 :(得分:0)

IMO,最简单的解决方案是启动AWS Lambda(或Google无服务器)并通过API网关附加它,为您提供时间服务器而无需管理任何基础架构。我的Lambda代码:

import datetime
import json

def lambda_handler(event, context):
   dt = datetime.datetime.utcnow()

   return {
      'statusCode': 200,
      'body': json.dumps({
      'iso_time': dt.strftime('%Y-%m-%dT%H:%M:%SZ')
   })
}

答案 11 :(得分:-1)

如果您的javascript是从Web服务器提供的,那么您可以使用此简单功能从此服务器请求时间。如果服务器在HTTP响应中返回Date标头,它将起作用。

function getServerTime()
{
    var req = new XMLHttpRequest();
    req.open('GET', document.location, false);
    req.send(null);
    return new Date(req.getResponseHeader("Date"));
}

暂停缓存这可能会返回错误的时间。要解决此问题,您可以使用随机网址:

req.open('GET', "/time?r=" + Math.floor(Math.random()*10000000), false);