views:

133

answers:

2

Hello,

I have a very strange issue with Daylight Savings Time (DST) in my app. For some reason, whenever I receive a time from the table, it doesn't adjust itself for DST. For example, if I create a new Time in the console, in the appropriate time zone, write it to the database, and then try to retrieve it from the database, it comes back as one hour earlier.

Here's an exameple:

Here, we can see that using the console, creating a new Time at 15:00 EST is equal to 19:00 UTC (since adjusted for DST, which makes it -0400 instead of the usual -0500):

ruby-1.8.6-p114 > Time.zone
 => #<ActiveSupport::TimeZone:0x12b1b68 @name="UTC", @tzinfo=nil, @utc_offset=0> 
ruby-1.8.6-p114 > Time.zone = "Eastern Time (US & Canada)"
 => "Eastern Time (US & Canada)" 
ruby-1.8.6-p114 > Time.zone.parse("15:00")
 => Thu, 09 Sep 2010 15:00:00 EDT -04:00 
ruby-1.8.6-p114 > Time.zone.parse("15:00").utc
 => Thu Sep 09 19:00:00 UTC 2010 
ruby-1.8.6-p114 > Time.zone.parse("15:00").dst?
 => true 

Now, I try to write that same time to the database, and retrieve it back:

ruby-1.8.6-p114 > b = Book.new
 => #<Book id: nil, return_time: nil, created_at: nil, updated_at: nil> 
ruby-1.8.6-p114 > b.return_time = Time.zone.parse("15:00")
 => Thu, 09 Sep 2010 15:00:00 EDT -04:00 
ruby-1.8.6-p114 > b.save
 => true 
ruby-1.8.6-p114 > result = Book.find(:last).return_time
 => Sat Jan 01 19:00:00 UTC 2000 
ruby-1.8.6-p114 > result.zone
 => "UTC" 
ruby-1.8.6-p114 > result.in_time_zone
 => Sat, 01 Jan 2000 14:00:00 EST -05:00 
ruby-1.8.6-p114 > result.dst?
 => false 

My environment.rb has this:

config.time_zone = 'UTC'

And application_controller.rb has this:

before_filter :set_user_time_zone

def set_user_time_zone
if current_user
  Time.zone = current_user.time_zone
else
  Rails.logger.error '[Time.zone.now.to_s][ERROR]: Missing current_user from in set_user_time_zone!'
end

end

Any ideas as to what could be happening here and how to fix it? I've been at this for days now, so really, any help would be greatly appreciated!

Thank you very much.

+1  A: 

I'm not sure what version of Rails you're using, but I had the same problem in 2.1.2. It seems the time zone library included just doesn't work half the year, but the developers didn't think it was worth switching; hopefully they've rethought that decision by now.

In any case, we ended up using the tzinfo_timezone plugin, which computes UTC offsets correctly during daylight savings time.

bnaul
Thank you very much for the tip. I looked into some of the Rails code to try and figure out what was going on, and it looks like v2.3.5 (the version I'm using) already using tzinfo. The problem turned out to be what Phil said: when the Time value gets saved to the table, the date gets changed to January 1st, 2000, which isn't in DST... argh! It's fixed now though, thank you!
mikep
+1  A: 

It looks like you're only saving the time portion; note how the date part goes from Thu, 09 Sep 2010 to Sat, 01 Jan 2000. Since the DST calculation depends on the date, this is probably where you're losing the information. (January 1st is not in DST, so assuming that date, the DST calculation is correct). You probably need to save a DATETIME in the database, not just TIME.

Phil
You're absolutely right Phil, thank you very much! :)
mikep