Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails timezone from offset

Tags:

So it seems rails has pretty nice support for timezones, but I've run into a requirement that I'm hoping has already been solved and I'm just not seeing it in the api.

I'd like to be able to find a TimeZone based on an offset. The reason being I'm hooking up to an api that gives me back the users time zone as an offset and don't want to necessarily reinvent the wheel turning that offset into a Rails TimeZone so the rest of the app can use it properly.

Any suggestions? Thanks for the help!

like image 475
Kelend Avatar asked May 26 '11 16:05

Kelend


2 Answers

You can get a timezone using the [] method on ActiveSupport::TimeZone. You can either pass a timezone name, hour offset or second offset. For instance:

ActiveSupport::TimeZone["America/Los_Angeles"]                                => (GMT-08:00) America/Los_Angeles ActiveSupport::TimeZone[-8]                                => (GMT-08:00) America/Los_Angeles 

But keep in mind that an offset is not equivalent to a timezone since multiple timezones can be on the same offset on any one day.

like image 163
Pan Thomakos Avatar answered Dec 28 '22 17:12

Pan Thomakos


The problem with the accepted answer is that it unfortunately does not handle cases where two different timezones have the same utc offset.

For example -7 could be referring to Arizona or Denver which are two DIFFERENT times zones ("America/Phoenix" and "America/Denver"), because Arizona does not observe daylight savings time.

ActiveSupport::TimeZone[-7] returns only one of those two valid timezones.

I needed the same functionality in the slightly simpler case of a database of USA zipcodes which includes a UTC hours offset and Y/N field indicating if it participates in daylight savings time, so West coast USA zipcodes in this database all have "-8" and "Y".

I could not find a built-in Rails method to do it, so I manually created a lookup hash where the key is the UTC & DST fields catenated, eg, "#{utc}#{dst}" and the value is the timezone name. This method could work for utc offsets such as "5.5" (India) as well.

In the method that does the lookup is given the utc and dst values, I specify a default timezone (USA west coast for example) in the case where the hash lookup returns nil because an unexpected value such as "-5N" (since the east coast does not have any non-DST states that should never occur).

But the same method could be applied globally by creating a hash that represented all the possible timezone with both Y and N values for daylight savings time.

class MyZip  HOUR_DST_TO_TIMEZONE_NAME = {   "-5Y" => "Eastern Time (US & Canada)",   "-6Y" => "Central Time (US & Canada)",   "-7Y" => "Mountain Time (US & Canada)",   "-7N" => "Arizona",   "-8Y" => "Pacific Time (US & Canada)",   "-9Y" => "Alaska",   "-10N" => "Hawaii"   }  def self.timezone_name_from_zip_hour_dst(utc, dst)   key = "#{utc}#{dst}"    return HOUR_DST_TO_TIMEZONE_NAME[key] || MyZip.unknown_timezone_name end ... 
like image 31
jpw Avatar answered Dec 28 '22 17:12

jpw