Ruby – How to calculate the offset, in hours, of a given timezone from UTC in ruby

rubytimezone

I need to calculate the offset, in hours, of a given timezone from UTC in Ruby. This line of code had been working for me, or so I thought:

offset_in_hours = (TZInfo::Timezone.get(self.timezone).current_period.offset.utc_offset).to_f / 3600.0

But, it turns out that was returning to me the Standard Offset, not the DST offset. So for example, assume

self.timezone = "America/New_York"

If I run the above line, offset_in_hours = -5, not -4 as it should, given that the date today is April 1, 2012.

Can anyone advise me how to calculate offset_in_hours from UTC given a valid string TimeZone in Ruby that accounts for both standard time and daylight savings?

Thanks!


Update

Here is some output from IRB. Note that New York is 4 hours behind UTC, not 5, because of daylight savings:

>> require 'tzinfo'
=> false
>> timezone = "America/New_York"
=> "America/New_York"
>> offset_in_hours = TZInfo::Timezone.get(timezone).current_period.utc_offset / (60*60)
=> -5
>> 

This suggests that there is a bug in TZInfo or it is not dst-aware


Update 2

Per joelparkerhender's comments, the bug in the above code is that I was using utc_offset, not utc_total_offset.

Thus, per my original question, the correct line of code is:

offset_in_hours = (TZInfo::Timezone.get(self.timezone).current_period.offset.utc_total_offset).to_f / 3600.0

Best Answer

Yes, use TZInfo like this:

require 'tzinfo'
tz = TZInfo::Timezone.get('America/Los_Angeles')

To get the current period:

current = tz.current_period

To find out if daylight savings time is active:

current.dst?
#=> true

To get the base offset of the timezone from UTC in seconds:

current.utc_offset
#=> -28800 which is -8 hours; this does NOT include daylight savings

To get the daylight savings offset from standard time:

current.std_offset
#=> 3600 which is 1 hour; this is because right now we're in daylight savings

To get the total offset from UTC:

current.utc_total_offset
#=> -25200 which is -7 hours

The total offset from UTC is equal to utc_offset + std_offset.

This is the offset from the local time where daylight savings is in effect, in seconds.