もしサマータイムが実施されていたら

オリンピックに合わせて?サマータイム導入という話が持ち上がりましたが、無事に収束して何よりです。
ところで、もしサマータイムが実施されていたら、時間を扱うプログラムはどのような影響があるのでしょうか?

サマータイム対応仕様を考えてみる

例として、以下のようなソフトウェアを考えてみます。
勤怠管理みたいなやつです。

日付:
開始:
終了:

時間:

開始から終了までは9時間ということがわかります。

日付:
開始:
終了:

時間:

終了が開始より前の場合、翌日とみなします。
この場合は深夜0時をまたいだ時間を返します。
ロジックはこんな感じでしょうか。

 

function get_timespan(開始時間, 終了時間)
{
    if (開始時間 > 終了時間) {
        return 終了時間 + 24時間 - 開始時間;
    } else {
        return 終了時間 - 開始時間;
    }
}

日付は入力できますが、計算には関係ありませんね。
ところで、このプログラムは1日が24時間であることが前提になっていますが、サマータイムが実施されると、この前提が崩れます。

日本で実施されていたサマータイム

日本では戦後の一時期にサマータイムが実施されていましたが、GHQによる占領統治の終了とともに、廃止されました。
https://ja.wikipedia.org/wiki/夏時刻法

  • 1948年(昭和23年) - 五月の第一土曜日の翌日(日曜)から九月の第二土曜日まで
  • 1949年(昭和24年) - 四月の第一土曜日の翌日(日曜)から九月の第二土曜日まで
  • 1950年(昭和25年) - 五月の第一土曜日の翌日(日曜)から九月の第二土曜日まで
  • 1951年(昭和26年) - 五月の第一土曜日の翌日(日曜)から九月の第二土曜日まで
  • 1952年(昭和27年)以降 - 廃止

どのようなものだったかは、Unixのdateコマンドで確認することができます。

$ date --date='1951/05/05 09:00:00'
1951年  5月  5日 土曜日 09:00:00 JST
$ date --date='1951/05/06 09:00:00'
1951年  5月  6日 日曜日 09:00:00 JDT

1951年5月6日を境にJSTからJDTに変わっていますが、この日が夏時間への切り替えが行われた日です。
もう少し詳しく見てみましょう。

$ date --date='1951/05/05 23:59:59'
1951年  5月  5日 土曜日 23:59:59 JST
$ date --date='1951/05/06 00:00:00'
date: `1951/05/06 00:00:00' は無効な日付です

「無効な日時です」と怒られてしまいましたが、夏時間開始と同時に時計を1時間進めるため、この日の0時から1時は存在しません。

1951/05/05 1951/05/06
23:00〜23:59 1:00〜1:59 2:00〜2:59

次は夏時間終了の日です。

 

$ date --date='1951/09/08 23:59:59'
1951年  9月  8日 土曜日 23:59:59 JDT
$ date --date='1951/09/09 00:00:00'
1951年  9月  9日 日曜日 00:00:00 JST

1秒しか進んでいないように見えますが、実は1時間(と1秒)が経過しています。

1951/09/08 1951/09/09
23:00〜23:59 0:00〜1:59 0:00〜1:59 1:00〜1:59

9月9日に0時が2回出現しています。
最初のほうが夏時間0:00JDTで、次が0:00JSTです。
どうやら日付と時刻の指定だけではどっちの0時か区別がつかないようです。

もう一度仕様(と設計)を考えてみる

夏時間チェックボックスとエラーチェックを追加しました。

日付:
開始: 夏時間
終了: 夏時間

時間: 終了時刻が無効です!!

UTCとローカルタイム

こういう場合には、内部処理はすべてUTCに変換して計算すると決まっています。
.NETの場合、DateTime構造体のメソッドを使います。

DateTime 開始UTC時刻 = 開始時刻.ToUniversalTime();
DateTime 終了UTC時刻 = 終了時刻.ToUniversalTime();
TimeSpan 時間 = 終了UTC時刻 - 開始UTC時刻

さいごに

サマータイムは関係なくても、複数のタイムゾーンで使う可能性のあるアプリケーションは、内部処理はUTCにしておかないと後が大変です。