web-dev-qa-db-ja.com

RubyでDateTimeのタイムゾーンを変更するにはどうすればよいですか?

タイムゾーンを一定に保ちながら、日付と時刻の読み取り、書き込み、シリアル化を行うのは面倒です。 Ruby(およびRails 3.0))を使用していて、DateTimeのタイムゾーンを(UTCに)変更しようとしていますが、時刻自体は変更していません。

これ欲しい:

t = DateTime.now
t.hour
-> 4
t.offset = 0
t.hour
-> 4
t.utc?
-> true

私が来た最も近いものはこれですが、直感的ではありません。

t = DateTime.now
t.hour
-> 4
t += t.offset
t = t.utc
t.hour
-> 4
t.utc?
-> true

もっと良い方法はありますか?

27

Rails 3を使用して、DateTime.change()を探しています

dt = DateTime.now
=> Mon, 20 Dec 2010 18:59:43 +0100
dt = dt.change(:offset => "+0000")
=> Mon, 20 Dec 2010 18:59:43 +0000
38
Alex Kremer

数値オフセットを使用します。 「+1000」は夏時間のため、一年中機能しません。 ActiveSupport :: TimeZoneをチェックアウトします。 詳細はこちら

10
Sam
d = DateTime.now
puts [ d, d.zone ]
#=> 2010-12-17T13:28:29-07:00
#=> -07:00

d2 = d.new_offset(3.0/24)
puts d2, d2.zone
#=> 2010-12-17T23:28:29+03:00
#=> +03:00

編集:この回答は、別の回答へのコメントによって提供された情報を説明していません。これは、タイムゾーンの変更後、報告された「時間」が同じであることを望んでいるということです。

9
Phrogz

代わりに Time オブジェクトを使用します。そのため、現在のローカル時間を取得してから、UTCオフセットだけインクリメントし、次のようにUTCに変換します。

t = Time.now # or Time.parse(myDateTime.asctime)
t # => Thu Dec 16 21:07:48 -0800 2010
(t + t.utc_offset).utc # => Thu Dec 16 21:07:48 UTC 2010

ただし、Phrogzコメントによると、場所に依存しない方法でタイムスタンプを保存するだけの場合は、現在のUTC時間を使用します。

Time.now.utc
9
maerics

@ Samが指摘したように、オフセットを変更するだけでは不十分で、エラーが発生します。 DSTクロックの進行に耐えるために、変換は次の方法で行う必要があります。

d = datetime_to_alter_time_zone
time_zone = 'Alaska'

DateTime.new
  .in_time_zone(time_zone)
  .change(year: d.year, month: d.month, day: d.day, hour: d.hour, min: d.min, sec: d.sec)
6
kogitoja

「私のような」誰かが「太平洋標準時(米国およびカナダ)」のような文字列形式のタイムゾーンを持っている場合

これが私が見つけた最良の方法より:

datetime.change(ActiveSupport::TimeZone[time_zone_string].formatted_offset(false)