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


105

我的created_at时间戳记存储在UTC中:

>> Annotation.last.created_at
=> Sat, 29 Aug 2009 23:30:09 UTC +00:00

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

Annotation.last.created_at.in_eastern_time

Answers:


191

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

因此,对于您的特定示例

Annotation.last.created_at.in_time_zone('Eastern Time (US & Canada)')

7
或者您也可以使用小时识别码now.in_time_zone(3)
fl00r 2011年

8
created_at.in_time_zone("EST")较短
奥兰多2012年

51
“ EST” =“东部标准时间”,因此在夏令时期间将是错误的。“东部时间(美国和加拿大)”确定您是否使用夏令时。
jhiro009 2012年

1
请注意,in_time_zone方法是ActiveSupport的一部分,因此它内置在Rails中,但不是Ruby stdlib的一部分。如果您有Rails应用程序,那就没问题。如果您有一个简单的Ruby应用程序,则需要确保需要积极的支持。
Gayle 2013年

链接到此方法的文档在这里:apidock.com/rails/DateTime/in_time_zone
Naved Khan

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

在这里阅读更多关于此的信息


1
如今有一个不错的Time.use_zone方法。
freemanoid

9

如果您将此添加到您的 /config/application.rb

config.time_zone = 'Eastern Time (US & Canada)'

那你就可以

Annotation.last.created_at.in_time_zone

获取指定时区的时间。


如果我们在application.rb中配置时区,则无需调用“ .in_time_zone”。Rails会自动为我们执行此操作,需要调用Annotation.last.created_at
Vishal

3

如果您配置了 /config/application.rb

config.time_zone = 'Eastern Time (US & Canada)'

Time.now.in_time_zone

DateTime.now.in_time_zone

2

将您的时区设置为东部时间。

您可以在config / environment.rb中设置默认时区

config.time_zone = "Eastern Time (US & Canada)"

现在,您提取的所有记录都将在该时区中。如果您需要不同的时区,请说说基于用户时区,您可以在控制器中使用before_filter进行更改。

class ApplicationController < ActionController::Base

  before_filter :set_timezone

  def set_timezone
    Time.zone = current_user.time_zone
  end
end

只要确保您将所有时间都以UTC格式存储在数据库中,一切都会变得很美好。


如果您正在运行杂种,瘦身或乘客之类的应用服务器,这有关系吗?他们运行多个实例,我相信单线程吗?我可能错了,很想知道!
nitecoder 2010年


可能不是在09年?
nitecoder

2
@jpwynn:据此:github.com/rails/rails/commit/…自5年多以来线程安全。您的问题有任何来源或示例吗?
Pascal

1
一个线程可以服务多个会话。您只需在用户登录时设置一次即可,例如,最后登录的用户将为会话使用同一线程的所有用户设置时区。因此,您必须使用before_filter为每次页面加载的每个用户设置它。
jpw
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.