Ruby2.6アドベントカレンダーの18日目の記事です。
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