レシピ1.8 夏時間のチェック

問題

現在のロケールの時刻が夏時間かどうかを知りたい。

解決
 Timeオブジェクトを生成し、そのisdstメソッドをチェックする。

Time.local(2006,1,1)                   # => Sun Jan 01 00:00:00 EST 2006
Time.local(2006,1,1).isdst           # => false
Time.local(2006,10,1)                 # => Sun Oct 01 00:00:00 EDT 2006
Time.local(2006,10,1).isdst         # => true

解説
 UTC時間を表す Timeオブジェクトは、 isdstが呼び出されると常にfalseを返す。何故なら、UTCは一年中同じ時間だからだ。他のTimeオブジェクトは、Time オブジェクトの生成に使われたロケールの時間を調べる。通常は、オブジェクトを生成したコンピュータのシステムロケールである。ロケールの設定を変更する方法については、レシピ1.7を参照のこと。次のコードは、アメリカの夏時間に関連するルールの一部を具体的に示している。

eastern = Time.local(2006, 10, 1)           # => Sun Oct 01 00:00:00 EDT 2006
eastern.isdst                                          # => true

ENV[' TZ '] 'US/Pacific'
pacific = Time.local(2006, 10, 1)            # => Sun Oct 01 00:00:00 PDT 2006
pacific.isdst                                          # => true

# ナバホ居留地を除き、アリゾナ州では夏時間を使用しない
ENV[' TZ '] 'America/Phoenix'
arizona = TIme.local(2006, 10, 1)            # => Sun Oct  01 00:00:00 MST 2006
arizona.isdst                                          # => faluse

# 最後に、元のタイムゾーンに戻す
ENV[' TZ '] = nil

 Timeクラスに使用されているCライブラリは、特定のタイムゾーンロケールの歴史にまたがる、複雑な時間ルールに対処している。例えば、アメリカで夏時間が制定されたのは1918年のことだが、その後間もなく、ほとんどのロケールで廃止された。Cライブラリが使用する「zoneinfo」ファイルには、他の多くのルールとともに、この情報が含まれている。

# 夏時間は1918年3月31日に施行された
Time.local(1918, 3, 31).isdst                  # => faluse
Time.local(1918, 4, 1).isdst                    # => true
Time.local(1919, 4, 1).isdst                    # => true

# 連邦法は1919年に廃止されたが、
# 一部の地域では夏時間を使用し続けていた
ENV[' TZ '] = 'US/Pacific'
Time.local(1920, 4, 1)                             # => Thu Apr 01 00:00:00 PAT 1920

ENV[' TZ '] = nil
Time.local(1920, 4, 1)                             # => ThuApr 01 00:00:00 EDT 1920

# 第二次世界大戦中に再び夏時間が導入された
Time.local(1942, 2, 9)                             # => Mon Feb 09 00:00:00 EST 1942
Time.local(1942, 2, 10)                           # => Tue Feb 10 00:00:00 EWT 1942
# EWTは”Eastern War Time”の略

 アメリカでは、2007年から夏時間を3月から11月までに拡大する法案が2005年に可決された。zoneinfoファイルがどれくらい古いかによっては、2007年以降の日付に対して生成されるTimeオブジェクトに新しい法律が反映されない可能性がある。

Time.local(2007, 3, 13)                 # => Tue Mar 13 00:00:00 EDT 2007
# コンピュータによっては、この時間がESTであると誤解するかもしれない

 これは一般的な観念を例証している。議員たちは法案を可決させることしか眼中にない。従って、Timeオブジェクトが1年以上先の時間を表すとしたら、isdstが正確であることを当てにすべきではない。実際にその時刻になった時、そのロケールでは夏時間のルールが変更されているかもしれない。
 DateクラスにはCライブラリが使用されておらず、タイムゾーンロケールを全く認識しないため、夏時間のことも認識しない。



参照

・レシピ1.7
・「zoneinfo」データベースに含まれている情報(http://www.twinsun.com/tz/tz-link.htm