この記事は ex-mixi Advent Calendar 2017 22 日目のエントリーです。

こんにちは、sota2502です。

mixiには2008年の新卒で入り、2015年の6月まで、なので7年3ヶ月在籍していました。
一貫してSNS mixiのサービスに関わっていて、その中で、メッセージ → 日記 → つぶやき → ページ → コミュニティと担当サービスを変えていました。

その後、10ヶ月ほど税務関連のシステム開発を行い、現在はFiNCでヘルスケア関連のシステム開発に携わっています。

今回は、mixiとFiNCの間に在籍した会社で直面した日本のサマータイム問題について書きました。

日本のサマータイム問題(1948-1951年)

これは以前 Qiitaにも記事を書きました。

あるユーザーの誕生日をdatetimeでMySQLに保存しておき、それをTomcatのアプリがXHRでブラウザに返して、JavaScriptでDateオブジェクトにして表示していました。

しかし、このとき、例えば 1951-05-07 00:00:00 をUnixTimeにしてブラウザに返し、JavaScriptでDateにすると 1951-05-06 になるという現象に遭遇しました。

これは1948年から1951年のGHQ統治下でサマータイムが導入されており、このサマータイムの調整のために、ある時点で1時間分調整が入りUnixTimeが1時間ずれます。

そのため、さきほどの 1951-05-07 00:00:00 のUnixTimeはJavaScriptでは 1951-05-06 23:00:00 と解釈されます。
このときJava側の変数のTimeZoneは JST ではなく JDT となります。

Ruby

Java以外の、他の言語ではどうなってるかが気になったので調べました。

まずはRubyです。

p Time.local(1951, 5, 7, 0, 0, 0).zone
=> "JDT"

ということでサマータイムに対応しています。

もう少し詳しく見ていきます。

(0..3).each do |hour|
  dt = Time.local(1951, 5, 6, hour, 0, 0)
  p [dt, dt.zone, dt.dst?]
end
=> [1951-05-06 00:00:00 +0900, "JST", false]
   [1951-05-06 01:00:00 +0900, "JST", false]
   [1951-05-06 03:00:00 +1000, "JDT", true]
   [1951-05-06 03:00:00 +1000, "JDT", true]

1951-05-06 02:00:00 でサマータイムになります。

Perl

今度はPerlで見ていきます。
ここではDateTimeを使っています。

use strict;
use warnings;

use DateTime;

foreach my $hour (0..3) {
  eval {
    printf "1951-05-06 %02d:00:00\n", $hour;
    my $dt = DateTime->new(
      year => 1951,
      month => 5,
      day => 6,
      hour => $hour,
      minute => 0,
      second => 0,
      time_zone => 'Asia/Tokyo',
    );
    printf "%s, %s\n", $dt->time_zone->name, $dt->is_dst;
  };
  print $@ if ( $@ );
}

結果は以下のようになります。

1951-05-06 00:00:00
Asia/Tokyo, 0
1951-05-06 01:00:00
Asia/Tokyo, 0
1951-05-06 02:00:00
Invalid local time for date in time zone: Asia/Tokyo
1951-05-06 03:00:00
Asia/Tokyo, 1

PerlのDateTimeでも JDT を扱ってはくれています。

しかし、1951-05-06 02:00:00 を与えるとオブジェクトの生成に失敗しました。

コードを追っていくと DateTime::TimeZone でoffsetを算出する際に、_spans_binary_searchで JDTJST ごとに持っているrangeと与えられた時間の比較してoffsetを決定しているのですが、 1951-05-06 02:00:00の場合はこのoffsetの取得に失敗し、 最終的にTimeZoneオブジェクトが作れなくなっていました。

まとめ

真面目にタイムゾーンについて考えたのは サハラ砂漠にマラソン しにいって以来でした。

いやー、タイムゾーンってホントに奥が深いですね!

時間の関係で他の言語については調べられませんでしたが、いつか他の言語での扱いも調べたいと思います。


明日は hnakagawa さんのエントリです。

よろしくお願いします。