Blog

When talking time zones: Bogota != Eastern Time (US & Canada)!

Ive been using the timezone localization technique of asking the browser when the page loads what the browsers timezone offset from UTC is, and posting that back to the server and storing it in the session.  However recently I noticed that with the event of Daylight Savings Time, this was no longer working, because my time would come up an hour off here in Virginia.

nn

After much faffing about, I finally figured it out.  On the server I would ask for the set of timezones that matched the offset, and grab the first one and put that in the session:

nn

[sourcecode]nresult = ActiveSupport::TimeZone.all.select{|t|t.utc_offset == gmtoffset}.firstnsession[:time_zone] = result.namen[/sourcecode]

nn

The list of named time zones returned when the browser is in Charlottesville, Virginia are: Bogota, Eastern Time (US & Canada), Indiana (East), Lima, Quito.

nn

So when I use Bogota as the timezone, and ask Rails to show the time localized:

nn

[ruby]nTime.now.in_time_zone(session[:time_zone])n[/ruby]

nn

I get back the time without taking into account daylight savings wrong. I started trying to figure out if the browser was in a DST zone using this JavaScript code: http://www.michaelapproved.com/articles/daylight-saving-time-dst-detect/ and while it seems very promising, it still wasnt quite giving me what I want.

nn

Finally, I realized it…. By arbitrarily grabbing the first time zone in the list, I was showing time in Bogota, Columbia. But if I chose Eastern Time (US & Canada) then I do get a localized time that takes into account day light savings!

nn

So right now I have this method:

nn

[ruby]nresult = ActiveSupport::TimeZone.all.select{|t| t.utc_offset == gmtoffset && t.name.include?(“US”)}.firstnsession[:time_zone] = result.namen[/ruby]

nn

Obviously this is pretty hardcoded to just work in the US, and isnt a real solution. Id love to hear other ideas! Part of me wonders if I should just display all times in UTC in HTML, and have some sort of client side JavaScript that localizes the time display?

nn

My full set of code:nJavascript in my index.html.erb view:n[javascript]n// Calls the server and sets the users time.nEvent.observe(window, load, function(e) {nvar now = new Date();nvar gmtoffset = TimezoneDetect();n//use ajax to set the time zone here.nvar set_time = new Ajax.Request( “home”, :action => “gmtoffset”%>?gmtoffset=+gmtoffset, {nonSuccess: function(transport) {n//alert(“Response” + transport.responseText);n}n});n});

nn

// http://www.michaelapproved.com/articles/daylight-saving-time-dst-detect/

nn

function TimezoneDetect(){nvar dtDate = new Date(`1/1/ + (new Date()).getUTCFullYear());nvar intOffset = 10000; //set initial offset high so it is adjusted on the first attemptnvar intMonth;nvar intHoursUtc;nvar intHours;nvar intDaysMultiplyBy;

nn

//go through each month to find the lowest offset to account for DSTnfor (intMonth=0;intMonth

nn

//To ignore daylight saving time look for the lowest offset.n//Since, during DST, the clock moves forward, itll be a bigger number.nif (intOffset > (dtDate.getTimezoneOffset() * (-1))){nintOffset = (dtDate.getTimezoneOffset() * (-1));n}n}

nn

return intOffset;n}

nn

[/javascript]

nn

home_controller.rb action:n[ruby]ndef gmtoffsetngmtoffset = params[:gmtoffset].to_i*60 if !params[:gmtoffset].nil? # notice that the javascript version of gmtoffset is in minutes 😉

nn

result = ActiveSupport::TimeZone.all.select{|t| t.utc_offset == gmtoffset && t.name.include?(“US”)}.firstnsession[:time_zone] = result.name

nn

render :update do |page|npage.replace_html time_of_chat_starting, :partial=> super_short_timenpage.visual_effect :highlight, `time_of_chat_startingnendnendn[/ruby]

nn

Rendered partial helper view _super_short_time.erb:n[ruby]nn[/ruby]

nn