如何在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 

有没有更好的方法?

使用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 

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

 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 

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

我会改用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 

正如@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) 

如果有人(像我一样)有字符串格式的时区,如“太平洋时间(美国和加拿大)”

这是我找到的最佳方式:

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

您可以通过在配置文件(config / application.rb)中添加以下行来指定要在应用中使用的时区:config.time_zone =’Mumbai’

你可以在这里找到相同的官方文档: http : //api.rubyonrails.org/classes/ActiveSupport/TimeZone.html

另一个选择是你“猴子补丁”“日期时间”类。