在Rails中将时间从一个时区转换为另一个时区

Tom*_*man 103 ruby datetime ruby-on-rails

我的created_at时间戳以UTC格式存储:

>> Annotation.last.created_at
=> Sat, 29 Aug 2009 23:30:09 UTC +00:00
Run Code Online (Sandbox Code Playgroud)

如何将其中一个转换为"东部时间(美国和加拿大)"(考虑到夏令时)?就像是:

Annotation.last.created_at.in_eastern_time
Run Code Online (Sandbox Code Playgroud)

Ste*_*eet 190

使用DateTime类的in_time_zone方法

Loading development environment (Rails 2.3.2)
>> now = DateTime.now.utc
=> Sun, 06 Sep 2009 22:27:45 +0000
>> now.in_time_zone('Eastern Time (US & Canada)')
=> Sun, 06 Sep 2009 18:27:45 EDT -04:00
>> quit
Run Code Online (Sandbox Code Playgroud)

所以对于你的特定例子

Annotation.last.created_at.in_time_zone('Eastern Time (US & Canada)')
Run Code Online (Sandbox Code Playgroud)

  • "EST"="东部标准时间",因此在夏令时期间会出错."东部时间(美国和加拿大)"会为您确定是否为DST. (49认同)
  • `created_at.in_time_zone("EST")`更短 (8认同)
  • 或者你可以使用小时识别`now.in_time_zone(3)` (7认同)
  • 请注意 in_time_zone 方法是 ActiveSupport 的一部分,因此它内置于 Rails 中,但不是 Ruby stdlib 的一部分。如果你有一个 rails 应用程序,没问题。如果您有一个直接的 Ruby 应用程序,您需要确保需要积极的支持。 (2认同)

ops*_*dao 17

虽然这是一个老问题,但值得一提.在之前的回复中,建议使用before_filter来暂时设置时区.

永远不应该这样做,因为Time.zone将信息存储在线程中,它可能会泄漏到该线程处理的下一个请求.

相反,您应该使用around_filter来确保在请求完成后重置Time.zone.就像是:

around_filter :set_time_zone

private

def set_time_zone
  old_time_zone = Time.zone
  Time.zone = current_user.time_zone if logged_in?
  yield
ensure
  Time.zone = old_time_zone
end
Run Code Online (Sandbox Code Playgroud)

在这里阅读更多相关信息

  • 现在有一个很好的 [Time.use_zone](https://apidock.com/rails/Time/use_zone/class) 方法。 (2认同)

Eif*_*ion 8

如果你把它添加到你的 /config/application.rb

config.time_zone = 'Eastern Time (US & Canada)'
Run Code Online (Sandbox Code Playgroud)

那你就可以了

Annotation.last.created_at.in_time_zone
Run Code Online (Sandbox Code Playgroud)

获取指定时区的时间.