首页 > 解决方案 > 转换 Rails ActiveRecord 时间戳的时区

问题描述

我在我的 Rails 项目中扩展了 Time 类,这样我就可以轻松地在纽约获得时间:

/lib/extensions.rb

class Time
  # Get NYC time:
  def nyc
    self.in_time_zone('Eastern Time (US & Canada)')
  end
end

测试一下,看起来不错:

time_a = Time.now.utc.nyc
=> Sun, 21 Apr 2019 18:42:12 EDT -04:00

问题是当我从数据库中提取时间戳时:

time_b = object.created_at.in_time_zone('Eastern Time (US & Canada)')
=> Sun, 21 Apr 2019 17:22:04 EDT -04:00
time_c = object.created_at.nyc
=> Sun, 21 Apr 2019 17:22:04 UTC +00:00

超级迷茫。当我在控制台中使用 in_time_zone 时,将时间戳转换为 EDT 有效,但在我使用扩展时无效?即使我的扩展方法适用于我在控制台中创建的时间对象?这里发生了什么事?


注意: Rails 中的 Time 实例实际上是ActiveSupport::TimeWithZone.“TimeWithZone 实例实现与 Ruby Time 实例相同的 API,因此 Time 和 TimeWithZone 实例可以互换。” - ActiveSupportTimeWithZone

标签: ruby-on-railsrubyactiverecordtimezone

解决方案


您需要修补 ActiveSupport::TimeWithZone 而不是 Time,例如

class ActiveSupport::TimeWithZone
  def nyc
    in_time_zone('Eastern Time (US & Canada)')
  end
end

Time.zone.now.nyc # => Mon, 22 Apr 2019 06:44:41 EDT -04:00
User.last.created_at.nyc # => Sun, 21 Apr 2019 13:34:45 EDT -04:00

https://api.rubyonrails.org/classes/ActiveSupport/TimeWithZone.html

(编辑:我之前说的是“DateTime”而不是“ActiveSupport::TimeWithZone”)


推荐阅读