如何在Ruby中更改DateTime的时区?

Dan*_*ley 25 ruby timezone datetime ruby-on-rails ruby-on-rails-3

在保持时区不变的同时读取,写入和序列化日期和时间变得令人讨厌.我正在使用Ruby(和Rails 3.0)并试图改变DateTime的时区.(到UTC)但不是时间本身.

我要这个:

t = DateTime.now
t.hour
-> 4
t.offset = 0
t.hour
-> 4
t.utc?
-> true
Run Code Online (Sandbox Code Playgroud)

我最接近的是这个,但它并不直观.

t = DateTime.now
t.hour
-> 4
t += t.offset
t = t.utc
t.hour
-> 4
t.utc?
-> true
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法?

Ale*_*mer 38

使用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
Run Code Online (Sandbox Code Playgroud)

  • 更有帮助的是实际链接到答案.我认为就是这个:http://stackoverflow.com/questions/5941613/are-the-date-time-and-datetime-classes-necessary/14007547#14007547 (7认同)
  • 对于它的价值,.change似乎也可以在2.3中获得. (2认同)
  • **请注意:**这将改变所代表的绝对时间. (2认同)

Sam*_*Sam 10

使用数字偏移,例如'+1000',由于夏令时,不会全年工作.Checkout ActiveSupport :: TimeZone. 更多信息在这里

  • 提供使用"ActiveSupport :: TimeZone"而不是仅链接到文档的示例是首选. (6认同)

mae*_*ics 9

我会改用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
Run Code Online (Sandbox Code Playgroud)

虽然,根据Phrogz评论,如果您只想以独立于位置的方式存储时间戳,那么只需使用当前的UTC时间:

Time.now.utc
Run Code Online (Sandbox Code Playgroud)


Phr*_*ogz 9

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
Run Code Online (Sandbox Code Playgroud)

编辑:此答案不考虑通过评论提供的信息来解释另一个答案,即希望在时区更改后报告的"小时"相同.


小智 6

正如@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)
Run Code Online (Sandbox Code Playgroud)