The WegoWise Development Blog

Timezones Are Hard: A Presentation

| Comments

In this post I will describe an interesting presentation that one of the WegoWise team gave at work. But before I do that I need to give some context.

Prologue

Toward the end1 of every week the WegoWise development team takes time out to hold a small hour-long "conference". We call it, creatively enough, Mini-conference, or just mini-conf. Mini-conf is a very informal, very optional occasion for developers to present on various topics that are loosely related to software development2. The purpose of Mini-conf is to share information or techniques, and also simply to provide an occasion for us to hang out3. Our team is completely remote and although we see each other on video chat during standups and pairing sessions we don't otherwise get many opportunities to all be "in the same room" for an extended period of time.

Here are some topics that have come up during mini-conf:

  • Jeff - Using JRuby, i.e. 'Software as a platypus'
  • Janet - Notes from Burlington Ruby Conference
  • Joe - Everything You Wanted to Know About Joe's Workflow but Were Afraid to Ask
  • Dan - Introduction to Compass: more than just a bunch of mixins
  • Nathan - Learn this one weird trick to decrease your Vim startup time 97.62%
  • John - BEES! (a statistical analysis of the chance that a Git ref will have the string 'bee' in it.)
  • Barun - A primer on color theory
  • Jed - Search & Replace Across Files in Vim

As you can see, the topics range from information that is directly useful to our daily work, to tips about useful tools and ways to improve our software environments, to presentations about concepts from other technologies or domains that can provide us with new perspectives. The topics aren't always completely serious, but there is usually something that we can take away and apply. We will often have two or three presentations per mini-conf, although sometimes one presentation will take up the whole hour or go even longer.

What follows is the shortest presentation we have ever had at Mini-conf.

The Presentation

This presentation was given by Nathan and goes as follows:

Timezones are Hard

... unless you use Date.current and Time.current.

The end.

Epilogue

Despite its brevity, this was one of the more useful and memorable presentations we've had at Mini-conf. Let me explain.

The issue this presentation addresses, if you are not familiar with it, is that in Rails datetime columns are usually stored in the database as UTC and converted to a local timezone that is set in the application configuration files. If you save a new datetime to the database it will automatically be converted from the application time back to UTC.

The problem comes in when the application server (or a developer's computer) is in a different timezone than the one that is set for the application, for example if the application is set to Eastern Time and the server is located in Central Time. In this case if you use Time.now in your code you will get an instance of Time with the time zone offset for Central Time. This can lead to a variety of subtle problems, mostly to do with intermittent tests but potentially leading to serious bugs in production as well. The worst of these bugs involve Date.today, because Date does not know about timezones. Consider this somewhat realistic accounting bug:

class Invoice < ActiveRecord::Base
def overdue?
(Date.today - issued_at.to_date) >= 10
end
end
# test file
describe Invoice do
let(:invoice) { create(:invoice) }
describe '#overdue?' do
it 'is overdue if 10 or more days have gone by' do
contract.issued_at = 10.days.ago
contract.overdue?.should eq(true)
end
end
end

So the issue here is that this test will fail between 11PM and midnight CDT, if the computer running the test is in CDT and the application is configured for EDT. Let's say it is midnight EDT on the 29th of August. This means that it is 11PM on the 28th for the computer in CDT. As a result the statement Date.today will return the date as the 28th. But the statement 10.days.ago will use the Rails application timezone, because these methods come from active_support. So the issued_at date for the contract will be the 19th, but today's date will be the 28th, and less than 10 days will have elapsed.

Or something. Timezones are hard. The point is that you can avoid this confusion in Rails code by just using the active_support methods Date.current and Time.current instead of Date.today and Time.now to always get the current time or date in the application timezone.

Also, team-building is hard, especially when everybody is remote. One thing that can help is to set aside some time during the week for people to hang out and share what they've learned with their colleagues.

The end.


  1. Mini-confs were initially held at the end of the workday on Friday, but our team is highly distributed and this meant that some developers in places like, say, Spain, had to log into their computers late on a Friday night to participate.

  2. Sometimes instead of a presentation we will just take an article or hot button issue and have a conversation for the hour.

  3. Using, of course, Google Hangouts.

Comments