Ruby 2.6 の変更点 - Time

Ruby2.6アドベントカレンダーの18日目の記事です。

qiita.com

Time

タイムゾーンサポート

https://bugs.ruby-lang.org/issues/14850

Time.new とか Time#getlocal は UTCからの時差を文字列("+09:00"等)か数値(秒数)で指定することができました。

2.6 ではこれに加えてタイムゾーンオブジェクトを指定することができるようになりました。

タイムゾーンオブジェクトは特定のクラスのインスタンスではなく、#local_to_utc, #utc_to_local メソッドを持ち、それらがTimeクラスのようなオブジェクトを返すようなものであれば良いです。

timezone.gem の Timezone::Zone や tzinfo.gem の TZInfo::Timezone が該当します。もちろん自分でそのようなオブジェクトを作成しても構いません。

Time.new(2018, 12, 18, 1, 2, 3, '+09:00') #=> 2018-12-18 01:02:03 +0900
Time.new(2018, 12, 18, 1, 2, 3, 32400)    #=> 2018-12-18 01:02:03 +0900

require 'timezone'
tz = Timezone['Asia/Tokyo']
Time.new(2018, 12, 18, 1, 2, 3, tz)       #=> 2018-12-18 01:02:03 +0900

require 'tzinfo'
tz = TZInfo::Timezone.get('Asia/Tokyo')
Time.new(2018, 12, 18, 1, 2, 3, tz)       #=> 2018-12-18 01:02:03 +0900

Time.at:in キーワード引数でタイムゾーンを指定できるようになってます。

Time.at(1545062523)                      #=> 2018-12-18 01:02:03 +0900
Time.at(1545062523, in: Timezone['UTC']) #=> 2018-12-17 16:02:03 +0000

タイムゾーンオブジェクトについて、詳しくはtime.c のコメントを読んでください。

東京五輪時間

試しに「東京五輪時間」オブジェクトを作ってみました。

# 東京五輪時間
# 6月から9月の間はJSTよりも2時間早くなる
class TokyoOlympicTimezone
  def olympic?(time)
    time.mon >= 6 && time.mon <= 9
  end
  def local_to_utc(time)
    time - (olympic?(time) ? 11*60*60 : 9*60*60)
  end
  def utc_to_local(time)
    time + (olympic?(time) ? 11*60*60 : 9*60*60)
  end
end

tz = TokyoOlympicTimezone.new

# 6/1〜9/30はUTCとの時差が11時間でそれ以外は9時間
Time.new(2020,  5, 31, 0, 0, 0, tz)  #=> 2020-05-31 00:00:00 +0900
Time.new(2020,  6,  1, 0, 0, 0, tz)  #=> 2020-06-01 00:00:00 +1100
Time.new(2020,  9, 30, 0, 0, 0, tz)  #=> 2020-09-30 00:00:00 +1100
Time.new(2020, 10,  1, 0, 0, 0, tz)  #=> 2020-10-01 00:00:00 +0900

# 日本標準時の朝5時は東京五輪時間の朝7時
t = Time.new(2020, 8, 1, 5, 0, 0, '+09:00') #=> 2020-08-01 05:00:00 +0900
Time.at(t, in: tz)                          #=> 2020-08-01 07:00:00 +1100