我们正在构建一个 Rails 应用程序,需要在多个时区显示日期(更重要的是计算日期)。
谁能告诉我如何在 Rails 2.3(.5 或 .8)中使用用户时区
我见过的最具包容性的文章详细介绍了用户时区的工作原理,如下:http://wiki.rubyonrails.org/howtos/time-zones http://wiki.rubyonrails.org/howtos/time-zones...虽然尚不清楚这是何时编写的或针对什么版本的 Rails。具体来说,它指出:
“Time.zone - 实际用于显示目的的时区。这可以手动设置以根据每个请求覆盖 config.time_zone。”
关键术语是“显示目的”和“基于每个请求”。
在我的本地机器上,这是真的。但在生产方面,这两种情况都不是真的。设置 Time.zone 在请求结束后仍然存在(对于所有后续请求),并且还会影响 AR 保存到数据库的方式(基本上将任何日期视为已经在 UTC 中,即使它不是),从而保存完全不合适的值。
我们在生产环境中使用乘客运行 Ruby Enterprise Edition。如果这是我的问题,我们需要切换到 JRuby 还是其他东西?
为了说明这个问题,我现在在我的 ApplicationController 中添加了以下操作:
def test
p_time = Time.now.utc
s_time = Time.utc(p_time.year, p_time.month, p_time.day, p_time.hour)
logger.error "TIME.ZONE" + Time.zone.inspect
logger.error ENV['TZ'].inspect
logger.error p_time.inspect
logger.error s_time.inspect
jl = JunkLead.create!
jl.date_at = s_time
logger.error s_time.inspect
logger.error jl.date_at.inspect
jl.save!
logger.error s_time.inspect
logger.error jl.date_at.inspect
render :nothing => true, :status => 200
end
def test2
Time.zone = 'Mountain Time (US & Canada)'
logger.error "TIME.ZONE" + Time.zone.inspect
logger.error ENV['TZ'].inspect
render :nothing => true, :status => 200
end
def test3
Time.zone = 'UTC'
logger.error "TIME.ZONE" + Time.zone.inspect
logger.error ENV['TZ'].inspect
render :nothing => true, :status => 200
end
它们产生以下结果:
Processing ApplicationController#test (for 98.202.196.203 at 2010-12-24 22:15:50) [GET]
TIME.ZONE#<ActiveSupport::TimeZone:0x2c57a68 @tzinfo=#<TZInfo::DataTimezone: Etc/UTC>, @name="UTC", @utc_offset=0>
nil
Fri Dec 24 22:15:50 UTC 2010
Fri Dec 24 22:00:00 UTC 2010
Fri Dec 24 22:00:00 UTC 2010
Fri, 24 Dec 2010 22:00:00 UTC +00:00
Fri Dec 24 22:00:00 UTC 2010
Fri, 24 Dec 2010 22:00:00 UTC +00:00
Completed in 21ms (View: 0, DB: 4) | 200 OK [http://www.dealsthatmatter.com/test]
Processing ApplicationController#test2 (for 98.202.196.203 at 2010-12-24 22:15:53) [GET]
TIME.ZONE#<ActiveSupport::TimeZone:0x2c580a8 @tzinfo=#<TZInfo::DataTimezone: America/Denver>, @name="Mountain Time (US & Canada)", @utc_offset=-25200>
nil
Completed in 143ms (View: 1, DB: 3) | 200 OK [http://www.dealsthatmatter.com/test2]
Processing ApplicationController#test (for 98.202.196.203 at 2010-12-24 22:15:59) [GET]
TIME.ZONE#<ActiveSupport::TimeZone:0x2c580a8 @tzinfo=#<TZInfo::DataTimezone: America/Denver>, @name="Mountain Time (US & Canada)", @utc_offset=-25200>
nil
Fri Dec 24 22:15:59 UTC 2010
Fri Dec 24 22:00:00 UTC 2010
Fri Dec 24 22:00:00 UTC 2010
Fri, 24 Dec 2010 15:00:00 MST -07:00
Fri Dec 24 22:00:00 UTC 2010
Fri, 24 Dec 2010 15:00:00 MST -07:00
Completed in 20ms (View: 0, DB: 4) | 200 OK [http://www.dealsthatmatter.com/test]
Processing ApplicationController#test3 (for 98.202.196.203 at 2010-12-24 22:16:03) [GET]
TIME.ZONE#<ActiveSupport::TimeZone:0x2c57a68 @tzinfo=#<TZInfo::DataTimezone: Etc/UTC>, @name="UTC", @utc_offset=0>
nil
Completed in 17ms (View: 0, DB: 2) | 200 OK [http://www.dealsthatmatter.com/test3]
Processing ApplicationController#test (for 98.202.196.203 at 2010-12-24 22:16:04) [GET]
TIME.ZONE#<ActiveSupport::TimeZone:0x2c57a68 @tzinfo=#<TZInfo::DataTimezone: Etc/UTC>, @name="UTC", @utc_offset=0>
nil
Fri Dec 24 22:16:05 UTC 2010
Fri Dec 24 22:00:00 UTC 2010
Fri Dec 24 22:00:00 UTC 2010
Fri, 24 Dec 2010 22:00:00 UTC +00:00
Fri Dec 24 22:00:00 UTC 2010
Fri, 24 Dec 2010 22:00:00 UTC +00:00
Completed in 151ms (View: 0, DB: 4) | 200 OK [http://www.dealsthatmatter.com/test]
上面应该清楚的是,对 /test 的第二次调用显示 Time.zone 设置为 Mountain,即使它不应该。
此外,检查数据库发现,在 test2 之后运行的测试操作保存了日期为 2010-12-22 15:00:00 的 JunkLead 记录,这显然是错误的。