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

Eric PughApril 21, 2010

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.

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:

[sourcecode] result = ActiveSupport::TimeZone.all.select{|t|t.utc_offset == gmtoffset}.first session[:time_zone] = result.name [/sourcecode]

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

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

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

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.

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!

So right now I have this method:

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

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?

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

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

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

//go through each month to find the lowest offset to account for DST for (intMonth=0;intMonth < 12;intMonth++){ //go to the next month dtDate.setUTCMonth(dtDate.getUTCMonth() + 1);

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

return intOffset; }


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

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

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

Rendered partial helper view _super_short_time.erb: [ruby] <%= super_short_time(Time.now.in_time_zone(session[:time_zone])) %> [/ruby]

More blog articles:

We empower great search teams!

We help teams that use Solr and Elasticsearch become more capable through consulting and training.

Services Training