timezone
夏時間
サマータイム
DST
zoneinfo

サマータイム導入には反対だが「日本夏時間」を試してみた

はじめに

東京オリンピックの暑さ対策としてサマータイム導入の検討が騒がれている。システム屋としては日本に夏時間の導入は全力で反対するが、キーワードで「夏時間で2時間早くする」というものがあった。2時間のサマータイムは聞いたことないわけで気になって試してみた。

Time Zone Database

ご存知の通りUNIX系のOS(LinuxとかBSD, etc..)では、時差つまりタイムゾーンをTime Zone Database (tz database, aka. zoneinfo)を使って管理している。Time Zone Database は、/usr/share/zoneinfo にある。

なお以下の記事の例ではFreeBSDを利用して試しているが、Linuxや Macでもまったく同様である。

$ ls /usr/share/zoneinfo
Africa          Australia       Etc             MST             WET
America         CET             Europe          MST7MDT         posixrules
Antarctica      CST6CDT         Factory         PST8PDT         zone.tab
Arctic          EET             HST             Pacific
Asia            EST             Indian          SystemV
Atlantic        EST5EDT         MET             UTC
$

Time Zone Database には、過去を含めて時差と夏時間の情報があるわけだが、はたして2時間のサマータイムは導入できる構造なのか。

ウィキペディアの「夏時間」を見てみる

実際に Time Zone Database をいじる前に、改めてウィキペディアの「夏時間」を読むと、こんな記述があった。

ただし、オーストラリアのロード・ハウ島では夏時間と通常の時間の差が1時間でなく30分である。

おお!30分!! なので zoneinfo では 1時間でないサマータイムをサポートしていることは容易に推測できる。

Time Zone Database の入手

元々Time Zone Database (以下 zoneinfo)はアーサー・デイヴィッド・オルソン(Arthur David Olson)さんが個人的に管理していたが、今はIANAが情報をまとめてデータベースを更新している。このあたりはウィキペディアのtz databaseにまとめられている。

ということで最新の Time Zone Database は IANA の Time Zone Database のページからダウンロードできるので拾ってきて展開してみる。

$ tar xf tzdb-2018e.tar.lz
$ ls
tzdb-2018e
$ ls tzdb-2018e | wc
      67      67     742
$

思っていたよりたくさんのファイルがあり、zic(zoneinfoコンパイラ)等の関連ユーティリティのソースや、BSDのstrftimeのソース、それらのman等も含まれていた。Time Zone Database そのものはテキストファイルであり、zic コマンドで変換して zoneinfo として利用する。

ちなみにデータベースの情報など大部分はパブリックドメインである。一部のソースやmanはBSDからそのまま持ってきているので、それらについてはBSDライセンスとなる。

ロード・ハウ島の例

ウィキペディアに記載のあるロード・ハウ島の情報は、australasia のファイルにあるが、該当部分は次のように定義されている。

# Lord Howe Island
# Rule  NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
Rule    LH      1981    1984    -       Oct     lastSun 2:00    1:00    -
Rule    LH      1982    1985    -       Mar     Sun>=1  2:00    0       -
    =============== 中略 ===============
Rule    LH      2008    max     -       Apr     Sun>=1  2:00    0       -
Rule    LH      2008    max     -       Oct     Sun>=1  2:00    0:30    -
Zone Australia/Lord_Howe 10:36:20 -     LMT     1895 Feb
                        10:00   -       AEST    1981 Mar
                        10:30   LH      +1030/+1130 1985 Jul
                        10:30   LH      +1030/+11

過去には1時間のサマータイムが実施されたことがあるが、2008年以降10月の第1日曜日から4月の第1日曜日の午前2時を切り替え時間として 30分の夏時間で運用されていることがわかる。

日本のzoneinfoを変更してみる

日本時間の情報は asia というファイルの中に以下のように定義されており、戦後に実施された夏時間の情報もちゃんと含まれている(コメント部を削って引用)。

# Japan
# Rule  NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
Rule    Japan   1948    only    -       May     Sat>=1  24:00   1:00    D
Rule    Japan   1948    1951    -       Sep     Sun>=9   0:00   0       S
Rule    Japan   1949    only    -       Apr     Sat>=1  24:00   1:00    D
Rule    Japan   1950    1951    -       May     Sat>=1  24:00   1:00    D
# Zone  NAME            GMTOFF  RULES   FORMAT  [UNTIL]
Zone    Asia/Tokyo      9:18:59 -       LMT     1887 Dec 31 15:00u
                        9:00    Japan   J%sT

明治時代の情報まで記録されているのには驚いた。

これを書き換えて、次の2行を # Zone の行の前に追加してみた。2018年以降、6月1日の午前2時 から 10月1日の午前2時までが夏時間という設定である。

Rule    Japan   2018    max     -       Jun     1        2:00   2:00    D
Rule    Japan   2018    max     -       Oct     1        2:00   0       S
# Zone  NAME            GMTOFF  RULES   FORMAT  [UNTIL]
Zone    Asia/Tokyo      9:18:59 -       LMT     1887 Dec 31 15:00u
                        9:00    Japan   J%sT

あとは zic でファイルをコンパイルすれば、日本夏時間を含む zoneinfo の出来上がり。システム標準のものを書き換えるわけにもいかないので、/tmp に出力した。asia に含まれている、一部のヨーロッパやインドエリアの zoneinfo も一緒に生成されているのがわかる。

$ /usr/sbin/zic -d /tmp asia
$ ls /tmp
Asia            Europe          Indian
$ ls -l /tmp/Asia/Tokyo
-rw-r--r--  1 minmin  wheel  884 Aug  8 12:44 /tmp/Asia/Tokyo
$ 

生成結果を手っ取り早く確認するには、TZ環境変数を利用すればよい。

$ date ; TZ=:/tmp/Asia/Tokyo date
Wed Aug  8 12:45:11 JST 2018
Wed Aug  8 14:45:11 JDT 2018
$

この通り、修正した日本用のzoneinfoを利用すると、2時間進んだ夏時間に変更できることが分かった。

出来た Tokyo を /etc/localtime にコピーするか、/etc/localtime のシンボリックリンクを書き換えてこのファイルを参照するようにすれば、2時間進んだサマータイムを導入したシステムとなる(実際に実行したわけでは無い)。

$ sudo cp /tmp/Asia/Tokyo /etc/localtime
Password:
$ 

切りの良い時間ばかりでは面白くないので、SAVEのフィールドを 1:37 として試したのが、次の例である。

$ date ; TZ=:/tmp/Asia/Tokyo date
Wed Aug  8 12:47:35 JST 2018
Wed Aug  8 14:24:35 JDT 2018

また -1:00 を設定し夏に1時間遅れるようにしてみると、正しく1時間遅れる結果となった。

$ date ; TZ=:/tmp/Asia/Tokyo date
Wed Aug  8 12:48:24 JST 2018
Wed Aug  8 11:48:24 JDT 2018
$

結果は省略するが、1:00:05 のように秒まで設定すれば、秒単位の変更も問題なくできる。

まとめ

Time Zone Databaseは、柔軟な時差、サマータイムに対応できる構造であり、サマータイムとして2時間進める設定も簡単に導入できることがわかった。実際の多くのシステムでは、zoneinfo の更新は OS のアップデートに頼ることになるはずである。しかしながら自分で書き換えることは簡単であり、任意の時刻に任意の時差を設定することで、夏時間との切り替え時点でのアプリケーションの挙動確認にも応用できることがわかった。

追記: システムのサマータイムへの対応

zoneinfoで対応できるシステムの時刻変更は、サマータイムの対応に必要なシステム全体の変更項目の極一部でしかない。サマータイムの対応では、アプリケーションの時刻の扱い、zoneinfoなんてものを知らない制御系システム、通信で利用される時刻などをどうするかの問題の方が遥かに大きい。

追記 その2: TZ環境変数

TZ で zoneinfo のファイルを指定する場合は、: (コロン)で始めるのが正式のようなので修正した。実際は多くの実装でコロンが無くても動作し、事実マニュアルにもコロンが無い場合の挙動について記載されている。

追記 その3: 2時間のサマータイム

一連の話題の中で2時間のサマータイムを実施した国があるというのを見かけたので、調べてみた。といってもやってることは簡単でzoneinfoのデータベースからSAVEが2時間になっている部分をgrepで拾い出すだけである。なお次の例の、egrep での検索文字列の空白部分は TAB である。

$ egrep '^Rule.*        2:00    .$' *
europe:Rule     France  1942    only    -       Mar      9       0:00   2:00   M
europe:Rule     France  1943    only    -       Mar     29       2:00   2:00   M
europe:Rule     France  1944    only    -       Apr      3       2:00   2:00   M
europe:Rule     France  1945    only    -       Apr      2       2:00   2:00   M
europe:Rule     Germany 1947    only    -       May     11      2:00s   2:00   M
europe:Rule     Port    1943    only    -       Apr     17      22:00s  2:00   M
europe:Rule     Port    1944    1945    -       Apr     Sat>=21 22:00s  2:00   M
europe:Rule     Spain   1938    only    -       Apr     30      23:00   2:00   M
$

この通りヨーロッパの 4つの国で見つかったが、時代的にはコンピュータが利用されるより前の話だ。ざっくりeurope のファイルを見た感じだと、1時間ずらした上でさらに1時間ずらして結果的に2時間進んだ運用を行ったように見える(勘違いしてるかも)。