【问题标题】:Getting the current GMT world time获取当前 GMT 世界时间
【发布时间】:2009-01-28 21:58:40
【问题描述】:

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

不是你电脑的时间像:

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

但是真正准确的世界时间?

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

我从 google 进行的所有搜索都返回 (new Date).getHours()

编辑:

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

【问题讨论】:

    标签: javascript


    【解决方案1】:

    您可以使用 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);
    });
    

    【讨论】:

    • 哇,这比我的回答简单多了。但缺点是你必须完全信任这个网站,否则他们会在你的页面上运行任意代码。
    • 你说得对,Shiny 先生...我认为这个 API 非常值得信赖,它由 Google 托管,由 Simon Willison(共同创建 Django 的人)创建 :)
    • JasonS,我又为你加分了 :)
    • API 工作正常,但今晚它停止了,因为它已经超出了 Google 当天的配额。免费 AppEngine 帐户的配额仅为每天 130 万个请求。
    • 现在给出 404 错误Remote Address:74.125.200.141:80 Request URL:http://json-time.appspot.com/time.json?tz=GMT&callback=json1439373722068 Request Method:GET Status Code:404 Not Found
    【解决方案2】:

    首先,要获得准确的 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 之类的 url。这比自己做这件事更容易,因为 json-time.appspot.com 服务器作为 GMT 时间的来源,并以允许您解决同源策略的方式提供此数据。我会建议简单的网站。但是它有一个主要缺点:json-time.appspot.com 站点可以在您的用户页面上执行任意代码。这意味着,如果该站点的运营商想要分析您的用户或劫持他们的数据,他们可以轻松做到这一点。即使您信任运营商,您也需要相信他们没有被黑客入侵或入侵。对于商业站点或任何具有高可靠性问题的站点,我建议您自己托管时间解决方案。

    编辑 2JimmyP'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 函数,该函数可以随时间做任何事情。此示例的服务器端编程是一个单独的问题。

    【讨论】:

    • 有用的理论(不是开玩笑,也不是贬低):) 但我该怎么做呢?我 == javascript 中的菜鸟
    • 一个示例或教程链接会很棒,有了这个答案,您将得到这个问题的正确答案:)
    • @fmsf:由于您是菜鸟,因此最好使用 JimmyP 的答案。我的回答涉及在服务器上编程,提供代码示例并非易事。
    • 仅供参考,json-time 网站现已失效。
    【解决方案3】:

    你为什么不发送每一页的时间?例如在 html 中的某处:

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

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

    【讨论】:

    • 我想时间会由服务器用 PHP 给出的,不是吗?它真的很聪明。编辑:或者更好的是,将其直接放在 JS 变量中,这样可以减少处理延迟。
    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

      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')); ?>
      })
      

      【讨论】:

        【解决方案6】:

        就像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 更改函数名称,则必须更新 this.calibrate_jsonscript.src 行中的回调em>。

        解释:

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

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

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

        Mydate.calibrate_json(data) 是一个函数,它可以将 url 带回返回 datetime 回复的资源,或者带当前时间的对象(用作回调)。如果未提供任何内容,它将使用默认 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);
        

        【讨论】:

          【解决方案7】:

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

          基本上,您可以通过向“/”发出 AJAX HEAD 请求来获取“日期”标头。并非所有服务器都支持这一点,它可能需要一些复杂的操作才能使其与特定服务器一起使用。

          Check out the real answer了解更多详情。

          【讨论】:

            【解决方案8】:

            IMO,最简单的解决方案是启动 AWS Lambda(或 Google Serverless)并通过 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')
               })
            }
            

            【讨论】:

              【解决方案9】:

              我们已成功使用 EarthTools 的 API:

              EarthTools

              该服务返回带有当前 GMT 和时区偏移等信息的 XML(当提供纬度和经度时)。我们在 ASP.NET 页面的 VB 后端使用 WebClient 和 XMLDocument 来读取和解释 XML。

              【讨论】:

                【解决方案10】:

                由于与James's 答案相关的服务似乎不再起作用,我找到了另一个可以用于此目的的好休息 API,它工作正常。 来源是这个站点:timeapi,你可以使用的代码就是这个(使用 jQuery 库和 API 提供的 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)
                
                    });
                

                通过这种方式,您将获得准确的本地时间(以小时为单位)。

                【讨论】:

                • API 似乎已经死了
                【解决方案11】:

                你可以在 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 包含您的完整日期和时间:"Mon, 05 Mar 2012 01:57:51 +0000", $hournow: "1" $minutenow:“57”。

                【讨论】:

                  【解决方案12】:

                  如果您的 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"));
                  }
                  

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

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

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2010-10-05
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-06-15
                    • 2013-07-28
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多