-
-
Save jarkko/2134102 to your computer and use it in GitHub Desktop.
1.9.3p125 :003 > Time.zone = "Pacific Time (US & Canada)" | |
=> "Pacific Time (US & Canada)" | |
1.9.3p125 :004 > Time.zone | |
=> (GMT-08:00) Pacific Time (US & Canada) | |
1.9.3p125 :005 > Time.zone.parse("2012-03-25 03:29") | |
=> Sun, 25 Mar 2012 04:29:00 PDT -07:00 | |
1.9.3p125 :006 > Time.zone.parse("2012-03-24 03:29") | |
=> Sat, 24 Mar 2012 03:29:00 PDT -07:00 | |
1.9.3p125 :007 > Time.zone = "UTC" | |
=> "UTC" | |
1.9.3p125 :008 > Time.zone | |
=> (GMT+00:00) UTC | |
1.9.3p125 :009 > Time.zone.parse("2012-03-25 03:29") | |
=> Sun, 25 Mar 2012 04:29:00 UTC +00:00 | |
1.9.3p125 :010 > Time.zone.parse("2012-03-24 03:29") | |
=> Sat, 24 Mar 2012 03:29:00 UTC +00:00 |
Ok, it gets even weirder. Seems it will do the jump both during the missing hour in my system TZ and the current Time.zone:
1.9.3p125 :015 > Time.zone.parse("2012-03-11 02:29")
=> Sun, 11 Mar 2012 03:29:00 PDT -07:00
1.9.3p125 :028 > Time.zone.parse("2012-03-11 03:29")
=> Sun, 11 Mar 2012 03:29:00 PDT -07:00
1.9.3p125 :029 > Time.zone.parse("2012-03-12 02:29")
=> Mon, 12 Mar 2012 02:29:00 PDT -07:00
However, if I switch Time.zone to my actual system timezone, this issue goes away:
1.9.3p125 :022 > Time.zone = "EET"
=> "EET"
1.9.3p125 :023 > Time.zone
=> (GMT+02:00) EET
1.9.3p125 :024 > Time.zone.parse("2012-03-25 03:29")
=> Sun, 25 Mar 2012 04:29:00 EEST +03:00
1.9.3p125 :025 > Time.zone.parse("2012-03-11 02:29")
=> Sun, 11 Mar 2012 02:29:00 EET +02:00
And just to lay it out, I reproduced the issue with Rails 3.0 and 3.2.2, both with Ruby 1.8.7 and 1.9.3.
Found the reason. Time.zone.parse uses by default Time.parse, which internally uses the system timezone to determine the time. Thus, regardless of the chosen Time.zone, it will base the jump to DST on the system clock. On the other hand ActiveSupport::TimeWithZone takes care of the same thing for the current Time.zone, which means every year we have two missing hours instead of only one.
I think this would be fixed by just comparing time.hour
to date_parts[:hour]
(if it exists), and if they don't match, fall back to DateTime.parse. This bug can't really happen when the hour isn't specified in the time string, so the fact that DateTime.parse doesn't take an optional now argument shouldn't matter.
I'll have to cook up a patch with tests for this.
I added an issue for this: rails/rails#5559
...and a pull request: rails/rails#5560
The issue here is that Pacific Time went to DST already on March 11th. UTC obviously is always the same. So it seems that Time.zone.parse will take the time for the one-hour jump (and only that) from my system TZ.
Note that this is not a general DST one-hour push, it only happens for the one hour that does not exist during the switch to DST: