夏時間導入における電算システムの対応

夏時間が導入された場合、電算システムにおいて必要となる対応をまとめます。なお、「夏時間に対応しない」としても、改修が不要とは限りません。

なお、本稿はUnix系およびWindowsのみを取り上げます。汎用機における夏時間の扱いについては、知見がないため取り上げません。

背景1: 電算システムにおける時刻の一般的な取り扱い

まずは、コンピュータがどのように時刻を扱うか、簡単におさらいします。

コンピュータが「現在時刻」を得るには、 1. システムクロック、 2. タイムゾーンデータベース 3. タイムゾーン設定 の3つのリソースを用います。

システムクロック: OSは、UTC(いわゆるグリニッジ標準時)の1970年1月1日0時ちょうどから、現在までに経過した秒数を、システムクロックとして提供します。うるう秒を無視すれば *1 、システムクロックを用いて、UTCの現在日付・現在時刻が算出できます。

タイムゾーンデータベース: 我々がふだん使っている時刻系(地方時)は、一般にUTCからずれています。たとえば、2018年8月のカリフォルニアでは、UTCから7時間遅れた地方時が用いられ、11月上旬以降は、UTCから8時間遅れた地方時が用いられます。一方、2018年時点の日本では、一年を通してUTCから9時間進んだ地方時が用いられます。ある地域で用いられる地方時は、法令の改廃や領土の割譲によっても変わります。このように、ある地域で適用される地方時の履歴をまとめたデータベースがタイムゾーンデータベースです。一般的に用いられるタイムゾーンデータベースは、ICANNが管理するtz database (tzdata) です。

タイムゾーン設定: システムクロックとタイムゾーンデータベースを用いて「現在時刻」を得るためには、「どの地域における時刻を得るか」の情報が必要です。「どの地域」を表すのがタイムゾーン識別子です。たとえば日本の地方時を用いる場合には、タイムゾーン識別子として「Asia/Tokyo」を指定します。Windowsでは、これを「日付と時刻」の画面から設定します。

背景2: タイムゾーンの取り扱いの諸相

同一のコンピュータの中でも、プログラムによって、異なるタイムゾーンデータベースやタイムゾーン設定が使われる場合があります。また、タイムゾーンデータベースを用いず、UTCからのズレをプログラム内でハードコードしている場合もあります。このような場合は、得られる「現在時刻」がプログラムごとに異なることになります。

OS提供のAPI: Windows APIのGetLocalTime関数、あるいは標準Cライブラリのlocaltime関数を使うと、OSが管理するタイムゾーンデータベース・OSのタイムゾーン設定を使った地方時が得られます。ふだんデスクトップで目にする時刻は、OS提供のAPIを用いている場合が多いでしょう。

Java: Oracle JDK / OpenJDKでは、OSが管理するタイムゾーンデータベースとは別に、独自のタイムゾーンデータベースを用います。このデータベースはtzupdaterツールで更新されます。また、ZoneIdオブジェクトを指定することで、OSのタイムゾーン設定とは独立に、任意のタイムゾーンにおける地方時が扱えます。たとえば、America/Los_Angelsタイムゾーンで運用されているシステム上のJavaアプリケーションで、Asia/Tokyoの地方時が扱えます。

Python: datetime.now関数は、無引数で呼び出すと、OSが提供する地方時における現在時刻を得ます。一方、タイムゾーンオブジェクトを引数に指定することで、任意のタイムゾーンにおける時刻が得られます。このタイムゾーンオブジェクトは標準で提供されていないため、プログラム内で定義するか、あるいはpytzライブラリから取得する必要があります。pytzライブラリを用いる場合、その更新はpipやsetuptoolsなどのパッケージマネージャによって行われます。

固定のUTCオフセット: 日本では長年、UTCから9時間進んだ地方時のみが用いられています。このため、UTCと地方時との相互変換において、9時間進める処理、9時間遅らせる処理が、プログラム内にハードコードされていることがしばしばです。

上記の組み合わせ: システム内、あるいはプログラム内で、上記の組み合わせが用いられている場合があります。たとえば、ブラウザのJavaScriptでOS提供の地方時が用いられて、サーバ側のJavaプログラムではJavaタイムゾーンデータベースが用いられる場合。あるいは、OS提供のlocaltime関数を用いているにもかかわらず、プログラムの一部分が、UTCとのズレが9時間であることを仮定した処理を行っている場合などです。

以降は、夏時間が導入された時に顕在化する可能性があるシステム上の課題について、例示的に述べます。

課題1: 存在しない時刻への対応

冬時間から夏時間に移行する時には、地方時において存在しない時刻が発生します。たとえば、冬時間の午前2時から夏時間の午前4時に移行する時、その日は2時台と3時台の時刻がまるまる存在しないことになります。

地方時の2時半に起動される日次処理があるとします。夏時間への移行日には、2時半という時刻が存在しないため、この処理がいつ実行されるべきか、そもそも実行されるべきか、検討する必要があります。仮に夏時間の4時ちょうどに起動したい場合、スケジューラがそのような設定に対応しているか調査する必要があります。

例として、cronieパッケージのcronコマンドは、夏時間への移行の際に日次処理の実行タイミングがスキップされた場合は、移行直後にジョブが実行されます。

課題2: 重複する時刻への対応

夏時間から冬時間に移動する時には、地方時において同じ表記の時刻が2度発生します。たとえば、夏時間の午前4時から冬時間の午前2時に移行する時、2時台の時刻と3時台の時刻は2回ずつ発生します。

時刻をユーザに入力させるようなシステムでは、これが問題となります。たとえば労務管理システムにおいて、勤務開始時刻が2時半と入力されたとき、これが夏時間の2時半か、冬時間の2時半かを、なんらかの方法で知る必要があります。

システムがログファイルを出力する時、ログ行の書式によっては、出力されたログがいつ時点のものか、一意に特定できなくなる可能性があります。たとえば「2019-10-27T02:30:00 INFO ...」のようなログ行は、この日が冬時間への移行日にあたる場合、夏時間・冬時間どちらの時刻のものか判別できません。このような場合、たとえば「2019-10-27T02:30:00+09:00 INFO ...」のようにUTCからのズレを出力したり、UTCでの時刻表記に変更したりするなどの対応が必要となるでしょう。

また日次処理の起動についても検討が必要です。毎日2時半にスケジュールされる日次処理について、それが夏時間の2時半と冬時間の2時半の二回実行されるべきか、どちらか一度だけであるべきか、といったことです。

課題3: 時刻表記の逆行

夏時間から冬時間への移行の際、時刻表記が巻き戻ることが問題を生む可能性があります。

たとえば、地方時の時刻表記を出力するファイル名の先頭に付しており、ファイル名のソートによって時刻順の並び替えが可能であると仮定している場合などです。

課題4: 1日の長さが22時間〜26時間で変動する

1日の長さが24時間であることを仮定しているシステムは、問題を生む可能性があります。

たとえば、1日のリクエスト数を24で割ることで1時間あたりのリクエスト数を算出している場合、夏時間への移行・冬時間への移行の際は、計算結果が不正になります。

同様の問題は、本質的にはうるう秒挿入の際も起こり得ます。しかしながら、うるう秒挿入の際の変動がたかだか1秒であるのに対して、夏時間・冬時間への移行は、変動幅が大きいため、問題が顕在化しやすくなります。

課題5: 夜間の長さが変動する

午後6時から午前6時までの時間は、通常12時間であるのに対して、夏時間移行の際は10時間、冬時間移行の際は14時間に変動します。

これによって、たとえば夏時間移行の際に、朝までに終わっているべき夜間処理が完了しない、といった問題が起きる可能性があります。

また、労務管理システムにおける勤務時間やインターバル時間の算出においても、改修が必要になるかもしれません。

課題6: システム間・システム内の時刻の不整合

上述したとおり、システムを構成するプログラムや、プログラム内の部分ごとにタイムゾーンの扱いが異なる場合には、不整合が発生し得ます。

課題7: 「夏時間に対応しない」ための対応

あるシステムが「夏時間に対応しない」ことを決めた場合、つまり「UTC+9時間の固定オフセットで運用する」ことを決めた場合には、タイムゾーンデータベースに依存しないようにプログラムを改修したり、タイムゾーンデータベースをアップデートしないように設定を変更したりする必要があります。

またこのシステムが、他システムと連携している場合には、システム間でほぼ確実に時刻の不整合が発生することも認識する必要があります。たとえば、ユーザがブラウザを通じてシステムに対して処理を行う場合、システムの扱う時刻とJavaScriptのDateオブジェクトの時刻にはズレが生じます。また、ログ解析を共通の基盤として運用している場合、「夏時間に対応しない」システムのログ出力の取り扱いには注意が必要でしょう。

*1:2018年時点で、システムクロックからUTCへの変換は、うるう秒がないものとみなす場合が大半です。しかしながら、アメリカやEUにおける調達基準の見直しによって、この状況は変わるかもしれません。参考: https://www.theregister.co.uk/2018/07/19/windows_leap_second/