Reputation: 19247
In a scheduling method, I need to take a (local_date, local_time, and local_time_zone), and return the corresponding utc time accounting for whether Daylight Saving time is in effect on that date.
I do not want to change Time.zone since while threadsafe, it has the entirely unexpected result of persisting across multiple requests - a Bad Thing.
The following (0800 Pacific time) does NOT work because they return the same time in UTC (16:00) even though the first day (Oct 1) IS in daylight saving time and the second day (Dec 1) is NOT in daylight savings time, so the UTC should be different
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
I had hoped that the .utc method would take into account whether the daylight saving is in effect, but it doesn't.
I'm not sure if I should be using a Time object, a DateTime object, and TimeWith Zone, etc.
===
Note: There IS a way to do it using the Chronic gem (below). But I would like to use the built-in Ruby Date and Time methods to get the same (eg, correct) result:
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
Upvotes: 2
Views: 1789
Reputation: 19247
Found it on another SO thread: the trick is to put the time (and zone) into a format usable by 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
ANOTHER METHOD (probably better):
ActiveSupport::TimeZone["Pacific Time (US & Canada)"].parse("2012-12-1 8am").utc
After some playing around it looks like we were right to be wary of changing Time.zone simply to create a time in a certain zone -- setting Time.zone can 'stick' over multiple requests (in the same thread). So if you have two different windows open to a rails app, and are viewing two different accounts, setting Time.zone for the account in one window can actually change the Time.zone in the other window for the other account.
Upvotes: 1
Reputation: 408
I recently went through something similar and found Time.zone.local to work fine taking daylight savings into account. I'm not sure about US daylight savings, but here in Australia daylight savings kick in on the 6th October 2013.
The following code seems to work fine for me:
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
Are you sure your dates / time zones are correct? Seems that Pacific Time experiences daylight savings in November according to this page: http://www.timeanddate.com/worldclock/timezone.html?n=137
Upvotes: 0