Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I calculate the offset, in hours, of a given timezone from UTC in ruby?

Tags:

timezone

ruby

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 
like image 697
esilver Avatar asked Apr 01 '12 05:04

esilver


People also ask

How do you calculate UTC offset?

(GMT-5:00) Eastern Time (US & Canada)Add the local time offset to the UTC time. For example, if your local time offset is -5:00, and if the UTC time is shown as 11:00, add -5 to 11. The time setting when adjusted for offset is 06:00 (6:00 A.M.). Note The date also follows UTC format.

How is timezone offset calculated?

You have to divide the longitude, in degrees, by 15 to find the appropriate time zone, in hours. For example: At 150 degrees west (or 150° W) longitude, the time should be 150 degrees divided by 15 degrees = 10 hours behind UTC, or UTC-10.


1 Answers

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.

like image 86
joelparkerhenderson Avatar answered Oct 13 '22 00:10

joelparkerhenderson