サンプル・プログラム
date2.html | サンプル・プログラム(1) |
normalizeDateTime.html | サンプル・プログラム(2) |
世界時と地方時
Dateオブジェクト
Dateオブジェクトの生成には、いくつかの方法がある。
まず、引数を何も指定しないで new Date() とすると、現在日時を格納したDateオブジェクトを生成する。このオブジェクトは生成した時点の日時を格納しており、そのままプログラムが動き続けても、時計のように日時が更新されていくわけではない。
次に、引数に年, 月, 日を指定して new Date(2024, 1, 29) とすると、2024年2月29日午前0時(地方時)を格納する。ここで、第2引数の月は0~11の整数を渡すことに留意されたい。つまり、1月なら0、2月なら1‥‥12月なら11を渡す。
3番目は、日付や時刻を文字列として渡す方法である。日時の表記には様々な形式があるが、うまく渡せるかどうかをサンプル・プログラムを使ってみてみよう。
Dateオブジェクトに日時を文字列として渡し、toLocaleStringメソッドを使って地方時を画面に表示するプログラムである。
サンプル・プログラム(1)の実行例
48: let dtText = '';
49: let dt;
50:
51: //現在日時
52: document.getElementById('dt0A').innerHTML = '';
53: let dt0 = new Date();
54: document.getElementById('dt0B').innerHTML = dt0.toLocaleString();
55: //現在日時
56: document.getElementById('dt0C').innerHTML = '';
57: document.getElementById('dt0D').innerHTML = dt0.getFullYear() + '年' + (dt0.getMonth() + 1) + '月' + dt0.getDate() + '日 ' + dt0.getHours() + '時' + dt0.getMinutes() + '分';
58: //指定年月日
59: document.getElementById('dt1A').innerHTML = '2024, 1, 29';
60: let dt1 = new Date(2024, 1, 29);
61: document.getElementById('dt1B').innerHTML = dt1.toLocaleString();
62: //指定年月日 (ISO 8601形式)
63: dtText = '2024-02-29';
64: document.getElementById('dt2A').innerHTML = "'" + dtText + "'";
65: let dt2 = new Date(dtText);
66: document.getElementById('dt2B').innerHTML = dt2.toLocaleString();
67: //指定年月日 (スラッシュ区切り)
68: dtText = '2024/02/29';
69: document.getElementById('dt3A').innerHTML = "'" + dtText + "'";
70: let dt3 = new Date(dtText);
71: document.getElementById('dt3B').innerHTML = dt3.toLocaleString();
72: //指定年月日時分秒 (ISO 8601形式)
73: dtText = '2024-02-29T12:00:00Z';
74: document.getElementById('dt4A').innerHTML = "'" + dtText + "'";
75: let dt4 = new Date(dtText);
76: document.getElementById('dt4B').innerHTML = dt4.toLocaleString();
77: //指定年月日時分秒 (ISO 8601形式)
78: dtText = '2024-02-29T12:00:00+09:00';
79: document.getElementById('dt5A').innerHTML = "'" + dtText + "'";
80: let dt5 = new Date(dtText);
81: document.getElementById('dt5B').innerHTML = dt5.toLocaleString();
82: //指定年月日 (スラッシュ区切り)
83: dtText = '2024/02/29 12:00:00';
84: document.getElementById('dt6A').innerHTML = "'" + dtText + "'";
85: let dt6 = new Date(dtText);
86: document.getElementById('dt6B').innerHTML = dt6.toLocaleString();
87: //指定年月日 (ドット区切り)
88: dtText = '2024.02.29';
89: document.getElementById('dt7A').innerHTML = "'" + dtText + "'";
90: let dt7 = new Date(dtText);
91: document.getElementById('dt7B').innerHTML = dt7.toLocaleString();
92: //指定年月日 (英語)
93: dtText = 'February 29, 2024';
94: document.getElementById('dt8A').innerHTML = "'" + dtText + "'";
95: let dt8 = new Date(dtText);
96: document.getElementById('dt8B').innerHTML = dt8.toLocaleString();
97: //指定年月日 (日本語)
98: dtText = '2024年3月2日';
99: document.getElementById('dt9A').innerHTML = "'" + dtText + "'";
100: let dt9 = new Date(dtText);
101: document.getElementById('dt9B').innerHTML = dt9.toLocaleString();
102: }
Windows版Chromeでは、'2024/02/29' や '2024.02.29'、'February 29, 2024' も正しい日時として扱われるが、たまたま扱えているだけで、すべてのJavaScript処理系(ブラウザ)で正しく扱えるとは限らない。
また、'2024-02-29' と '2024/02/29' の結果(地方時)が異なっている点に注意したい。
'2024-02-29' は ISO 8601形式 で2024年2月29日UTC0時を意味するので、地方時(日本標準時)はプラス9時で2024年2月29日9時となる。一方、'2024/02/29' は地方時0時と解釈される。
ただし、前述の通り、'2024/02/29' はたまたま扱えているだけなので、他のJavaScript処理系(ブラウザ)では異なる結果になるかもしれない。
いずれにしても、Dateオブジェクトに日時文字列を渡すときには、かならず ISO 8601形式にして渡すようにしよう。
ISO 8601形式による表記
ISO 8601 表記 | 日本語表記 |
---|---|
2018 | 西暦2018年 |
2018-07 | 西暦2018年7月 |
2018-07-12 | 西暦2006年7月12日 |
2018-07-12T23:20Z | 西暦2006年7月12日23時20分UTC |
2018-07-21T23:20:52Z | 西暦2006年7月21日23時20分52秒UTC |
2018-07-21T23:20:50.32Z | 西暦2006年7月21日23時20分50.32秒UTC |
2018-07-19T16:10:40.22-08:00 | 西暦2006年7月19日16時10分40.22秒 (米太平洋標準時間;UTCから-8時間の時差) |
2018-07-19T16:10:40.22+09:00 | 西暦2006年7月19日16時10分40.22秒 (日本標準時間;UTCから+9時間の時差) |
2006-01-01T08:59:60+09:00 | 西暦2006年1月1日8時59分60秒 (日本標準時間;閏秒を示す) |
サマータイム
たとえばイギリスでは、毎年3月の最終日曜日1時(UTC)から10月の最終日曜日1時(UTC)までの期間、UTCより1時間だけ早めるイギリス夏時間(BST;British Summer Time)を実施している。現在、サマータイムを導入している国は、ヨーロッパを中心に約70カ国ある。
一方、アラスカでは、毎年4月の第一日曜日2時から10月の最終日曜日2時までをアラスカ夏時間(AKDT;Alaska Daylight Time)としている。
このように、国や地域によってサマータイムの期間が異なる。
さらに、イギリスでは、第二次大戦中の1940年2月15日(木)2時(UTC)から1945年10月7日(日)2時(UTC)までの間、2時間のサマータイムを行っていた。
このように、サマータイムは1時間とは限らないこと、そして年代によっては期間や時間が異なる。ある時期にサマータイムを廃止した国もあるし、新規に導入した国もある。
わが国も、GHQの指導により、1948年4月28日に夏時刻法を公布し、サマータイムを導入した時期がある。実施期間は、1948年5月2日(日)0時~9月12日(日)1時、1949年4月3日(日)0時~1949年9月11日(日)1時、1950年5月7日(日)0時~1950年9月10日(日)1時、1951年5月6日(日)0時~1951年9月8日(土)1時という変則的なものだった。
このようにローカルな条件が多いため、ISO 8601 ではサマータイムを定義しておらず、時差で表現することを推奨している。
ISO 8601 表記 | 日本語表記 |
---|---|
2018-03-25T01:30Z | 西暦2018年3月25日01時30分UTC |
2018-03-25T02:30+01:00 | 西暦2018年3月25日02時30分 (イギリス夏時間BST;UTCから+1時間の時差) |
正規化処理
たとえば「2024年2月29日9時30分」という日時は、
2024/2/29 9:30などの様々な表記がある。これを ISO 8601形式 である '2024-02-29T09:30:00+09:00' に正規化するには一筋縄ではいかない。残念ながら、JavaScriptの標準関数、メソッドに正規化のための手段は用意されていない。
2024.02.29 09:30
2024年2月29日午前9時半
February 29 2024, 9.30am
そこで、gooラボのクラウドサービス「時刻情報正規化API」を利用してみることにした。JavaScriptでクラウドサービスを利用する方法については、「第7章 WebAPIとjQuery」をご覧いただきたい。
サンプル・プログラム(2)の実行例
定義域と値域
Dateオブジェクトは、内部的に日時データを 1970年1月1日UTC0時をゼロとしたミリ秒の数値データとして格納している。数値データである以上は、「2.4 数値型の範囲と誤差」で説明したように、上限値と下限値がある。つまり、定義域がある。
JavaScriptのECMA-262規格によれば、1970年1月1日UTC0時から前後1億日を格納できると定義されている。西暦になおすと、紀元前271,821年4月20日から西暦275,760年9月13日まで Dateオブジェクトで扱うことができるということになる。
歴史上の出来事を扱う限り、Dateオブジェクトで十分そうだ。だが、ユーザーは何を入力するか分からない。悪意のある第三者が、定義域を逸脱したデータを無理矢理に入力し、プログラムの停止や、データの摂取や改竄を目論むこともある(インジェクション)。
そこで、日付・時刻をキーボードから入力したり、ファイルやインターネットのコンテンツを参照したり、他システムからデータ連携するときには、計算処理に入る前に、「1.6 入力、バリデーション、関数」で紹介したバリデーションを実施することをおすすめする。
参考サイト
- 国際原子時と協定世界時:ぱふぅ家のホームページ
- 明石市立天文科学館と人丸前駅は日本標準時子午線の上に建つ:ぱふぅ家のホームページ
- 7.4 POSTへの対応 - 第7章 WebAPIとjQuery:ぱふぅ家のホームページ