2

在调度方法中,我需要取一个(local_date、local_time 和 local_time_zone),并返回相应的 UTC 时间,以说明夏令时是否在日期生效。

我不想更改 Time.zone ,因为虽然线程安全,但它具有跨多个请求持续存在的完全出乎意料的结果 - 一件坏事。

以下(0800 太平洋时间)不起作用,因为它们在 UTC(16:00)中返回相同的时间,即使第一天(10 月 1 日)是夏令时,第二天(12 月 1 日)不是夏令时时间,所以UTC应该不同

Time.new(2012, 10, 1, 8, 0, 0, ActiveSupport::TimeZone['Pacific Time (US & Canada)'].utc_offset).utc
# 2012-10-01 16:00:00 UTC <<<< should be 15:00

Time.new(2012, 12, 1, 8, 0, 0, ActiveSupport::TimeZone['Pacific Time (US & Canada)'].utc_offset).utc
# 2012-12-01 16:00:00 UTC 

我曾希望 .utc 方法会考虑夏令时是否有效,但事实并非如此。

我不确定是否应该使用 Time 对象、DateTime 对象和 TimeWith Zone 等。

===

注意:有一种方法可以使用 Chronic gem(如下)。但我想使用内置的 Ruby 日期和时间方法来获得相同的(例如,正确的)结果:

Chronic.time_class =ActiveSupport::TimeZone["Pacific Time (US & Canada)"]
Chronic.parse("10/1/2012 0800").utc
# 2012-10-01 15:00:00 UTC 
Chronic.parse("12/1/2012 0800").utc
# 2012-12-01 16:00:00 UTC 
4

2 回答 2

1

在另一个 SO 线程上找到它:诀窍是将时间(和区域)放入 Time.parse 可用的格式:

Time.parse("2012-10-1 8:00:00 Pacific Time (US & Canada)").utc
# 2012-10-01 15:00:00 UTC 

Time.parse("2012-12-1 8:00:00 Pacific Time (US & Canada)").utc
# 2012-12-01 16:00:00 UTC

另一种方法(可能更好):

ActiveSupport::TimeZone["Pacific Time (US & Canada)"].parse("2012-12-1 8am").utc

在玩了一些之后,看起来我们对更改 Time.zone 只是为了在某个区域创建时间保持警惕是正确的——设置 Time.zone 可以“坚持”多个请求(在同一个线程中)。因此,如果您为 Rails 应用程序打开了两个不同的窗口,并且正在查看两个不同的帐户,则在一个窗口中为该帐户设置 Time.zone 实际上可以更改另一个帐户在另一个窗口中的 Time.zone。

于 2012-11-05T07:16:14.553 回答
0

我最近经历了类似的事情,发现 Time.zone.local 考虑到夏令时可以正常工作。我不确定美国的夏令时,但澳大利亚的夏令时将于 2013 年 10 月 6 日开始。

以下代码对我来说似乎工作正常:

1.9.3-p194 :009 > Time.zone = 'Sydney'
 => "Sydney" 
1.9.3-p194 :010 > Time.zone.local(2013, 10, 1, 0, 0, 0).utc
 => 2013-09-30 14:00:00 UTC 
1.9.3-p194 :011 > Time.zone.local(2013, 10, 10, 0, 0, 0).utc
 => 2013-10-09 13:00:00 UTC 

您确定您的日期/时区正确吗?根据此页面,太平洋时间似乎在 11 月经历夏令时: http ://www.timeanddate.com/worldclock/timezone.html?n=137

于 2012-11-05T04:01:40.483 回答