Techioz Blog

ActiveSupport::TimeWithZone を使用して UTC をユーザー定義のタイムゾーンに変換する

概要

Rake タスクの一部として、UTC 時間をユーザーのタイムゾーンの同等の時間に変換する必要があります。私がやりたいのは、UTC タイムスタンプを午前 0 時に変更し、ユーザーのタイムゾーンで午前 0 時になるようにタイムスタンプを再作成することです。

UTC 時間を変換する

Wed, 01 Mar 2017 00:00:00 UTC +00:00

夏時間 (春/夏) を適用する場合は、東部夏時間 (EDT) まで

Wed, 01 Mar 2017 04:00:00 UTC +00:00
zone = ActiveSupport::TimeZone.new("Eastern Time (US & Canada)")
time = "Wed, 01 Mar 2017 00:00:00 UTC +00:00"
time.in_time_zone(zone)
=> Tue, 28 Feb 2017 19:00:00.000000000 EST -05:00

Rails はすべてのタイムスタンプを UTC に変換し直すため、上記の内容はデータベースに Wed, 01 Mar 2017 00:00:00 UTC +00:00 として保存されます。ただし、ユーザーのタイムゾーンでの本当の 1 日の始まりであるため、2017 年 3 月 1 日水曜日 04:00:00 UTC +00:00 を取得する必要があります。

解決策

ActiveSupport::TimeZone#parse を使用して、タイムゾーンに関連する文字列を解析できます。 「UTC +00:00」のようなタイムゾーン指定子は必ず省略してください。

zone = ActiveSupport::TimeZone.new("Eastern Time (US & Canada)")

time = zone.parse("Wed, 01 Mar 2017 00:00:00")
#=> Wed, 01 Mar 2017 00:00:00.000000000 EST -05:00

time.utc
#=> 2017-03-01 05:00:00 UTC

utc への最後の呼び出しは説明のみを目的としており、Rails はデータベースの時間を節約するときにこの変換を自動的に実行します。

数値入力の場合:

time = zone.local(2017, 3, 1)
#=> Wed, 01 Mar 2017 00:00:00.000000000 EST -05:00