DateTimeで時差を指定する

DateTimeに時差を設定したいときは第7引数に時差を与えます。

# DateTime.new([year[, mon[, mday[, hour[, min[, sec[, offset[, start]]]]]]]])
# offsetが時差
DateTime.new(2000, 10, 1, 0, 0, 0, 'GMT+09')
# => Sun, 01 Oct 2000 00:00:00 +0900

このときoffsetに与える形式は、他にもいろいろ。

DateTime.new(2000, 10, 1, 0, 0, 0, '+09')
DateTime.new(2000, 10, 1, 0, 0, 0, '+9')
DateTime.new(2000, 10, 1, 0, 0, 0, '+09:00')
DateTime.new(2000, 10, 1, 0, 0, 0, '+9.0')
# => Sun, 01 Oct 2000 00:00:00 +0900

不正な文字列を与えると、時差なしのインスタンスが生成されます。

DateTime.new(2000, 10, 1, 0, 0, 0, 'invalid')
# => Sun, 01 Oct 2000 00:00:00 +0000

ちなみにこの時差、実は文字列以外でも与えられるのですが、
文字列以外で与える場合には注意が必要です。

offset = 9.0/24 # => 0.375
offset.class    # => Float
date_time = DateTime.new(2000, 10, 1, 0, 0, 0, offset)
# => Sun, 01 Oct 2000 00:00:00 +0900
# ここまではOKに見える

DateTime.new(2010, 10, 2, 0, 0, 0) - date_time
# 3653.375

こんな感じで、時差に与えられたオブジェクトをDateTimeの演算の際に利用しています。
下手するとどんどん値がずれていきます。
あぁ、大変!


ということで、文字列以外から時差を与えたい場合は以下のようにするとよさげです。

offset = Rational(9, 24)
date_time = DateTime.new(2010, 10, 1, 0, 0, 0, offset)
# => Sun, 01 Oct 2000 00:00:00 +0900

DateTime.new(2010, 10, 2, 0, 0, 0) - date_time
# => Rational(11, 8)