Correctly handling multiple time zones in ruby on rails
Dec 06, 2007
A recent client I was working for had the unfortunate situation where we'd
both independently assumed we understood the requirements, without realising
a missing piece of complexity. It was around time zones. The system was
implemented with a cut-off date being US EST, but most of their clientele
are in LA so it needed to be US PST. What is a developer to do?
Well it turns out that timezone_fu will come to the rescue.
Installing time zone support into your rails app
Getting timezone_fu working with an existing rails app is a cinch, the only
dependency is on the TZInfo package, so best you
grab that now:
sudo gem install tzinfo
And the install the plugin in your rails app:
./script/plugin install http://www.thrivesmart.com/open_source/timezone_fu
Now before we do anything, make sure that we are defaulting to UTC time inenvironment.rb:
ENV['TZ'] = 'UTC'
Migrating your models so they know about time zones
Next, take your model that you want to apply your dates to. In my scenario it
was an election which had a start and end date for when voting could occur. First
thing I needed to do was to add a field to record the time zone that the dates
were to be handled in:
class AddTimezoneToElections
And then amend my model definition in election.rb to add in the time zone
helper:
class Election [:start_at, :end_at],
:default_timezone => "America/Los_Angeles",
:time_format => "%I:%M %p on %A %d %B %Y"
end
Storing and retrieving time zones in your rails app
The wonderful thing about this setup is that dates saved or retrieved from the
model using the normal attribute accessors will displayed in the local time (as
determined by whatever you save in the timezone field). I've also used all of
the attributes to show their usage, but you can safely leave efault_timezone and
ime_format off if you desire. The latter is a strftime string format outlininghow to format the string, so we can get something like:
>> @election.display_end_at
=> "08:10 PM on Wednesday 20 February 2008"
Unfortunately though the strftime method used by the display_attribute helpers
still thinks that the timezone is in UTC format (I'll hopefully get around to a
patch shortly), so within my views to display the date with the timezone it is
actually more like:
Previously I led the Terraform product team @ HashiCorp, where we launched Terraform Cloud and set the stage for a successful IPO. Prior to that I was part of the Startup Team @ AWS, and earlier still an early employee @ Heroku. I've also invested in a couple of dozen early stage startups.