最近、仕事で日本以外のタイムゾーンに関する仕事をしていて、いろいろ知識が自分の中で溜まってきたのでアウトプットすることにしました。
こんな感じで進めていこうかと思います。
- タイムゾーンとは
- サマータイムとは
- タイムゾーン情報のデータ
タイムゾーンとは
「時差」って言葉はきいたことがあると思います。
たとえば、2017/03/04 現在、東京とハワイの時差は19時間です。
では、この時差はどういうふうに設定されるかというと、地域ごとに協定世界時(以後UTC)からの差分が設定されており、そこから計算します。
たとえば、東京は UTC+09:00 が設定されており、ハワイは UTC-10:00 が設定されています。
ですので、この値からハワイは、東京の 19時間より前の時刻になっているということがわかり、東京の時計が20時を示してある瞬間、ハワイの時計では1時を示しています。
そして、大阪、札幌もこの東京と同じ日時設定のルールにしたがっており、こういうときに、「大阪、札幌、東京は同じタイムゾーンに所属する」といえます。
参考: 「時間帯(標準時) - Wikipedia」
さて、この UTC からの差分なのですが、日本の場合は常に +09:00 なので馴染みがないのですが、地域ごとには政治により特定の期間だけ UTC からの差分が変わったりします。
そして、この特定の期間だけ UTC からの差分が変わるルールの代表例としてはサマータイムがあります。
サマータイムとは
Daylight Saving Time(DST) とも呼ばれたりします。
これは具体的にどんな感じかというと、特定の期間だけ UTC のオフセットが1時間多くなります。
たとえば、アメリカ合衆国のニューヨークは通常は UTC-05:00 なのですが、サマータイム期間中は UTC-04:00 になります。
つまり、東京(UTC+09:00)とニューヨークの時差が通常は14時間なのにサマータイム期間中は時差が13時間になります。
さて、このサマータイムがエンジニアにとってやっかいなのは、通常期間のときからサマータイムに切り替わるとき、サマータイムから通常の期間に切り替わるときです。
通常期間からサマータイムに切り替わるときは1時間時計を進めます。
ニューヨークでは 2007 年以降、毎年3月第2日曜の2時にそれが発生します。
2017/03/12 01:59 -05:00
↓ (1分後)
2017/03/12 03:00 -04:00
つまり、2時台の1時間飛ばされるので、この日は1日24時間ではなく23時間になります。
また、サマータイムから通常期間に切り替わるときは、特定の1時間を2度繰り返します。
ニューヨークでは 2007 年以降、毎年11月第1日曜の2時にそれが発生します。
2017/11/05 01:00 -04:00
↓ (59分後)
2017/11/05 01:59 -04:00
↓ (1分後)
2017/11/05 01:00 -05:00
↓ (1時間後)
2017/11/05 02:00 -05:00
つまり、1時間を繰り返すので、この日は1日24時間ではなく25時間になります。
参考: 「夏時間」
タイムゾーン情報のデータ
プログラミング言語のライブラリや OS がサマータイムを計算するためには、各タイムゾーンはいつからサマータイムを始めるなどのデータが必要になります。
自分が把握している範囲だと、このタイムゾーンのデータは2種類あります。
Windows OS がもっているデータと tz database です。
Windows OS がもっているデータ
1つ目のタイムゾーンのデータは、Microsoft が提供している Windows 内にあるデータです。
レジストリの HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones に存在するようです。
タイムゾーンIDは以下のような感じです。
(UTC+09:00) 大阪、札幌、東京 -> Tokyo Standard Time
(UTC-05:00) 東部標準時 (米国およびカナダ) -> Eastern Standard Time
このタイムゾーン情報のデータは以下などのように Windows Update で更新されるようです。
参考: 「2016 年 6 月 DST およびタイム ゾーンの Windows 用更新プログラム」
tz database
2つ目のタイムゾーンのデータは、tz database です。
UNIX や Java ランタイムではこのデータを使用しています。
タイムゾーンIDは以下のような感じです。
(UTC+09:00) 大阪、札幌、東京 -> Asia/Tokyo
(UTC-05:00) 東部標準時 (米国およびカナダ) -> America/New_York
ID はアジアやヨーロッパの地方名のあとに都市名を記載する形になっています。
tz database はテキストファイルで読むことができます。
このサイトの Data Only Distribution と書かれているファイル(tzdatayyyyX.tar.gz)から確認できます。
たとえば、America/New_York は上記 tar.gz 内の northamerica というファイルにかかれており、以下に定義されています。
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/New_York -4:56:02 - LMT 1883 Nov 18 12:03:58
-5:00 US E%sT 1920
-5:00 NYC E%sT 1942
-5:00 US E%sT 1946
-5:00 NYC E%sT 1967
-5:00 US E%sT
GMTOFF は GMT or UTC(?) からのオフセットが書かれています。
RULES はサマータイムなどの情報が定義されているルール名があります。
FORMAT は JST や EST などの標準時などが書かれており、「%s」は後述の RULES に当てはまった場合の変数が格納されたりします。
UNTIL はいつまでこのオフセット、ルールを使うかが明記されています。
次に、上記の例で記載された「US」ルールをみてみます。
# New South Wales
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule US 1918 1919 - Mar lastSun 2:00 1:00 D
Rule US 1918 1919 - Oct lastSun 2:00 0 S
Rule US 1942 only - Feb 9 2:00 1:00 W # War
Rule US 1945 only - Aug 14 23:00u 1:00 P # Peace
Rule US 1945 only - Sep lastSun 2:00 0 S
Rule US 1967 2006 - Oct lastSun 2:00 0 S
Rule US 1967 1973 - Apr lastSun 2:00 1:00 D
Rule US 1974 only - Jan 6 2:00 1:00 D
Rule US 1975 only - Feb 23 2:00 1:00 D
Rule US 1976 1986 - Apr lastSun 2:00 1:00 D
Rule US 1987 2006 - Apr Sun>=1 2:00 1:00 D
Rule US 2007 max - Mar Sun>=8 2:00 1:00 D
Rule US 2007 max - Nov Sun>=1 2:00 0 S
このルールでは主にサマータイムの開始、終了が記載されています。
FROMとTOはサマータイム、通常時の開始、終了の年が記載されています。
IN ON ATには切り替えの日時、SAVE にはどれくらい時刻をズラスかが記載され
LETTER/S はこの値が前述の Zone の定義内の FORMAT の %s に格納されます。
なので、前述の America/New_York の Zone 定義ですと、LETTER/S が S の場合は、FORMAT の値が「EST」(Eastern Standard Time)になりますし、D の場合は、「EDT」(Eastern Daylight Time)になります。
2008年以降に関する記載は以下の部分ですね。
Rule US 2007 max - Mar Sun>=8 2:00 1:00 D
Rule US 2007 max - Nov Sun>=1 2:00 0 S
3月8日から最初の日曜2時にはEST(標準のUTC-05:00)になり、11月1日から最初の日曜2時にEDT(サマータイムのUTC-04:00)になります。