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 outlining

how 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:

Hi, I'm Glenn! 👋 I've spent most of my career working with or at startups. I'm currently the Director of Product @ Ockam where I'm helping developers build applications and systems that are secure-by-design. It's time we started securely connecting apps, not networks.

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.