This post contains two parts:

  1. Timezone in Rails App
  2. Timezone in the browser


Timezone in Rails

Rails provides great tools for working with time zones but there's still a lot of things that can go wrong. This post aims to shed some light on these gotchas and provide solutions to the most common problems.

Rails almost has you covered all the time, but I’ve learnt the hard way that I can’t get away without knowing when and how Rails is helping me. There are so many timezone factors we need to consider:

  • Database Timezone
  • Production Server Timezone
  • Local Dev Machine Timezone
  • Framework Timezone

So what tools do we have at our disposal as Rails developers?

config.time_zone = 'Eastern Time (US & Canada)' # rails application timezone
config.active_record.default_timezone = :local  # controls the timezone datetime is converted to prior saving to DB

The most important one is the config.time_zone configuration in your config/application.rb file. This sets the application timezone. ActiveRecord will help you convert from and to UTC and the timezone of your choice.

Another one is the config.active_record.default_timezone configuration in your config/application.rb file, This controls which timezone DB entries are stored in. It can be either :utc or :local. And :utc is default. If you set it to :local, ActiveRecord will help you convert to and from system local and the timezone of your choice when setting and retrieving from the database.

In almost all scenarios, we don't want to change this value, and we want to keep UTC as the default timezone for Database.

If all you’re doing is receiving user data through a form and use Active Record to persist it you’re good to go. But what about actually doing something with the time information before persisting it? That’s when it becomes tricky.

When parsing time information it’s important to pay extra attention to timezone. It’s always a good practice to use the methods that use the timezone specified in our rails application config. Let’s look at a couple of methods that parse date and time:

Methods Description
Time.current uses timezone from rails application config
Time.now uses timezone from system locale
Time.zone.xxx uses timezone from rails application config
Time.strptime(xx, xx).in_time_zone uses timezone from rails application config
Time.strptime(xx, xx) uses timezone from system locale
Date.current uses timezone from rails application config
Date.today uses timezone from system locale
String.to_time uses timezone from system locale
String.in_time_zone uses timezone from rails application config
Looking carefully, you'll discover that the naming of the methods that adopt rails application configured timezone has a set of common patterns:

  1. we should use the .current method whenever available
  2. we should use the zone object as an intermediate object whenever available
  3. we could use .in_time_zone on any value to reset its timezone to rails application config

Timezone in Browser (JS Date API)

The JS Date API is tricky and extra attention is required when creating a Date object from string:

The Date constructor will always return a Date object in browser's local time, but the argument string is taken care of differently when it is provided in different formats.
format Result Description
new Date('2013-02-22') ‘Feb 21 2013 …’ this treats argument as UTC time
new Date('2013/02/22') ‘Feb 22 2013 …’ this treats argument as local time
new Date('02/22/2013') ‘Feb 22 2013 …’ this treats argument as local time
new Date('22 Feb 2013') ‘Feb 22 2013 …’ this treats argument as local time


Summary

Timezone issues are hard to discover and tricky to deal with. We should always keep timezones in our minds when dealing with date and time.

The main takeaways from this article are:

  1. In Rails, always use the methods that takes application configured timezone into consideration.
  2. In Browser, pay extra attention to the string format of the argument supplied to JavaScript Date() constructor.