正確な残り日数カウントダウンをJavascriptのみで実装する

Javascript
この記事は約6分で読めます。

この記事は、8年前に書かれました。

はじめに

最近、伊勢志摩サミットの情報をニュースなどでよくみかけますね。
クライアントワークで、サミットまでの日数カウントダウンをトップページに表示したいという要望がありました。
サーバーサイドプログラムを使用出来ないクライアントです。Javascirptは使用可能ですが、正確な日時を取得したい場合、サーバーの日時を利用したほうがより安全です。
ローカル側のPC環境の日時がずれているとも限りません。
その際、いろいろと悩んで実現した方法を覚え書きとして残しておきます。

正確な日時とは

サーバーサイドプログラムであれば、以下のように簡単に取得できます。

<?php
$today = date("Y-m-d H:i:s");
print_r($today);
?>
2016-01-12 11:32:21

ウェブサーバーの時間は大体NTPサーバーと同期して正確な日時を刻んでいることと思います。
しかしJavascirptの場合、基本的にローカルPCの日時を取得しますので、ずれている場合もゼロではありません。
以下、Javascriptでの現在日時取得です。

let d = new Date();
console.log(d) // Tue Jan 12 2016 11:32:22 GMT+0900 (日本標準時)

さて、Javascriptでもローカル環境に依存しない正確な現在日時を取得するにはどのようにすればよいのでしょうか。
何か方法がないか調べることにしました。そこで一筋の光が見えてきました。

以下のコマンドを使用すると、サーバのレスポンスヘッダの時刻を取得できるようです。

xhr.getResponseHeader('Date')

サーバーの現在日時さえ取得できればいいので、何らかのダミーファイルにAjaxでアクセスし、レスポンスヘッダからサーバーの現在日時を取得し、それを利用しようということです。

jQueryでAjaxを使用

Ajaxを使用したいのでjQueryをインクルードします。

<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>

AjaxでダミーのHTMLにアクセスしてサーバーの現在日時を取得するスクリプトは以下のようになります。最も重要なのが14行目です。

var startDate;//現在日時
var endDate1; //伊勢サミット 開催日
var diff1;//日数差

$(function () {
  $.ajax({
    type: "GET",
    url: "dummy.html",
    cache: false,
    dataType: "html",

    success: function (data, status, xhr) {
      try {
        startDate = new Date(xhr.getResponseHeader("Date"));
      } catch (e) {
        console.log(e);
        myError();
      }

      if (startDate) {
        dateDiff();
      } else {
        myError();
      }
    },

    error: function () {
      myError();
    }
  });
});

取得した日付をゴニョゴニョする関数を書きます。9行目で、現在日時とサミット開催日との差を求めています。
console.logでどのように日付が取得できているかを確認しましょう。

function dateDiff() {
  console.log("Today:" + startDate);
  $("#startDate").text(startDate);

  endDate1 = new Date("May 26,2016 00:00:00");
  console.log("endDate1:" + endDate1);
  $("#endDate1").append(String(endDate1));

  diff1 = Math.ceil((endDate1 - startDate) / (24 * 60 * 60 * 1000));
  console.log("diff1:" + diff1);

  $("#diff1").append(diff1);
}

function myError() {
  $("#diff1").append("取得できません");
}

cosole.logで以下のように表示されました。

Today:Tue Jan 12 2016 11:32:22 GMT+0900 (日本標準時)
endDate1:Thu May 26 2016 00:00:00 GMT+0900 (日本標準時)
diff1:135

最後にHTMLを準備します。

<h1>伊勢サミット </h1>
<p id="endDate1">開催日:</p>
<p>開催まで あと <span id="diff1"></span>日</p>

サーバーの現在日時を取得するために使用するdummy.htmlを準備します。中身はなんでも構いません。HTMLとして体裁が整っていれば問題ありません。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis" />
<title>サーバータイムスタンプ取得用</title>
</head>
<body>
<h1>サーバータイムスタンプ取得用</h1>
</body>
</html>

HTMLに反映されるとこのようになりました。

まとめ

サーバーサイドプログラムでないとできないと思い込んでいましたが、やはり決めつけるのはよくありませんね。Javascriptでもサーバー日時を取得することができることが今回分かりました。
今後、いろいろと役に立つ場面があるかもしれません。