Whitethunder

Just Another Boring Tech Blog

Time Zone Sensitive Code in Rails

| Comments

At Goldstar, we help people go out more to live entertainment across several time zones. When we list a new show in New York City and it’s supposed to be displayed on our site at midnight on December 1st, we want it to be displayed when it’s midnight in New York City on December 1st, and not wait until it’s midnight in Los Angeles. Rails hasn’t done a great job of making it obvious how to do this, so I hope to make it obvious how we’ve done it successfully using Rails.

TL;DR: if you’re doing time zone sensitive stuff, use Time.zone, followed by .now or .now.to_date; or use the Rails helpers like 1.hour.ago.

Since we are based in California, we use Pacific Time in our app. This is set in our app’s config/environment.rb (config/application.rb for Rails 3.x):

1
config.time_zone = 'Pacific Time (US & Canada)'

Our time zone is now set to Pacific Time, which is evidenced by:

1
2
  > Time.zone
 => #<ActiveSupport::TimeZone:0x1c865d0 @tzinfo=#<TZInfo::DataTimezone: America/Los_Angeles>, @utc_offset=-28800, @current_period=nil, @name="Pacific Time (US & Canada)">

However, Time.now and Date.today use the OS’s time zone. Since I am in Mountain Time, I get -0700. Pacific Time folks wouldn’t think anything was amiss:

1
2
3
4
  > Time.now
 => Wed Dec 14 09:52:36 -0700 2011
  > Date.today.to_time
 => Wed Dec 14 00:00:00 -0700 2011

How to Use the App’s Time Zone

If you want a date or time in the app’s current time zone, use Time.zone.now or the Rails helpers like 1.hour.ago:

1
2
3
4
  > Time.zone.now
 => Wed, 14 Dec 2011 08:52:36 PST -08:00
  > 1.hour.ago
 => Wed, 14 Dec 2011 07:52:36 PST -08:00

You can switch Rails’ time zone if you know the right incantation (for a full list, look here):

1
2
  > Time.zone = 'America/New_York'
 => "America/New_York"

You’ll notice that Time.zone.now uses Rails’ time zone correctly when you’ve changed it:

1
2
  > Time.zone.now
 => Wed, 14 Dec 2011 11:52:37 EST -05:00

In case you’re curious, you can change the OS’s time zone if you know the right incantation as well:

1
2
3
4
  > ENV['TZ'] = 'EST'
 => "EST"
  > Time.now
 => Wed Dec 14 11:56:23 -0500 2011

One problem we kept having at Goldstar was a failing build after certain hours of the day, since our app and CI server run in Pacific Time but some of our tests test shows in other time zones.

Homework

So with your new-found time zone knowledge, here’s an exercise for you. Can you spot the bug with this spec:

1
2
3
4
5
6
7
8
9
10
11
12
describe "thinger" do
  before :each do
    @event = Factory(:event)
  end

  it "should return the thinger for this event if its thinger_on is today" do
    Time.use_zone(@event.timezone) do
      @thinger = Thinger.create!(:event => @event, :thinger_on => Time.now.to_date)
    end
    @event.thinger.should == @thinger
  end
end

ANSWER KEY: :thinger_on is using Time.now.to_date, which after a certain hour of the day, depending on your OS’s time zone, will fail. Totally lame. Time.zone.now.to_date is what was intended here.

Attracting Talented Rubyists

| Comments

Chances are that if you work with a team that does Ruby development, you don’t just have trouble finding good Ruby programmers, you have trouble finding available Ruby programmers period. I attend 2-3 Ruby programming related conferences per year, and at each one it seems that everyone is employed, most of them happily, and every other presentation someone announces, “I’m from X company and oh by the way WE’RE HIRING OMG PLEASE COME WORK FOR US!!!”

As a Rubyist, this is awesome. We’re in high demand, even in a bad economy. As someone that has assisted in searching for good Rubyists, it’s terrible. You spend many weeks and even months searching for just one person who is a cut above the rest. And when you find someone, you know they have many options so no ordinary job offer will do.

I’ve been a full-time Rubyist for a few years now. I’ve worked in circumstances that were awesome and in circumstances that had me looking for any available opportunity to find something better. I want to share what these things were, more or less in order of importance. And while this list is written with the Rubyist in mind, these principles for the most part apply to hiring programmers and retaining them in general.

Trust and Ownership

A Rubyist doesn’t want to be confined to strict orders and processes. He wants to be creative and own his work. Don’t micro-manage. It’s not going to improve anything. If the thought of a programmer taking creative freedoms is frightening to you, consider how it would feel to have your management style dictated to you. Encouraging programmers to collaborate and solve problems together ought to be enough to alleviate your fears and produce the results that you both want.

Profit Sharing/Bonuses

Let’s be honest, businesspeople. That great idea you have won’t go anywhere without someone to market it, sell it, and build it. You have this great dream of getting rich off of your marvelous idea, but you’re not going to do it alone. So share the wealth and a Rubyist will be happy to build awesome things for you. You could try setting up a profit sharing arrangement. You could offer bonuses tied to good performance. You could offer awesome perks like overnight getaways for 2, restaurant gift certificates, bring in a masseuse, etc.

Sane Hours

Don’t make a Rubyist work more than 40 hours a week. If he does it of his own accord, that’s probably ok, but make sure that your expectation is limited to 40 hours. You might think to yourself, “Well I’ve had this guy writing code for me for a year now and he always does 60-80 hour weeks.” And then one day he tells you he’s taking a job somewhere else, and the likely reason is because he’s burnt out. We may be a little socially awkward sometimes, but we do have lives outside of work, even if that life is playing Starcraft or even watching videos of other people playing Starcraft.

Keep them Challenged

Along the lines of getting burnt out, a Rubyist wants to be interested in what he’s doing. A good way to do this is to give him new challenges. It doesn’t have to be constant glamourous work, but if you’ve got him spending a lot of time cleaning up messes in production or fixing the CI server on a regular basis, you ought to give him a break from it, even if he’s the best at it. Let him have a chance at being a project or team lead. Let him refactor or rewrite a poorly-written section of the app between projects. Just don’t let him get stuck in a rut that he can’t get himself out of or chances are he won’t be around very long.

Talk to Them

When was the last time you asked your developers if they love what they do? Do you have any idea what gets them going each day or what frustrates them? Do you give them regular feedback on their work? Building a relationship where you talk about things like this will go really far with a Rubyist. You can help them improve and they can help you manage better.

Be Agile

Agile methodologies are much more programmer-friendly than Waterfall. It also delivers better results faster when followed correctly. If you aren’t already Agile, get someone to train you and your team.

Training and Conferences

Speaking of training, Rubyists want to learn. We don’t want to be working the exact same job with the exact same skills for the next 10 years. We’re passionate about what we do. We want to get better every day and sending us to trainings and conferences will help us do that and make us happy. Let your team choose what conference they most want to go to and pay for them to go. Your team will learn, bond, get away from the office for a few days, and come back refreshed with new insights.

Good Equipment

Don’t be cheap with the equipment you buy them. Get really good laptops. Get big monitors. Let them choose their preferred peripherals. Get them nice headphones. It’s best if you let them choose all their own stuff but if you need to standardize, make sure you standardize on something good.

Allow Work-from-home

Commuting is a waste of time. We’d rather be writing code. I’m not suggesting that all Rubyists want to work from home all the time, but working from home a day or two a week is a nice break from the commute, or even that annoying PM who always wants to pretend he fits in with the geeks. If you find it a little inconvenient, only allow it on days where it’s more convenient.

Make Open Source Contributions

The Ruby community is all about sharing and giving back. You’re using software that is open source at your company. Well, that software didn’t magically appear one day. Some generous people gave their time and effort to create it, and now you’re benefiting from it financially. Unless you’re sending money their way, the best way to pay them back is to open source some of your code. If your company won’t or can’t do that, then let your Rubyists spend some time making open source contributions to worthy projects of their choice.

Don’t Use Phrases Like “Rock Star” or “Code Ninja”

When you post a job listing for a Rubyist, don’t use lame cliche catch phrases. As soon as you start using the average strategies that everyone else uses, you get average Rubyists. Quality Rubyists want to see and do things they haven’t done before. Give them a programming challenge or a puzzle to solve or something interesting.

Conclusion

You might think that a lot of this is expensive or unrealistic, but you’re wrong. One great Rubyist can do the work of 5 average Rubyists, but I bet you wouldn’t pay him the salary of 5 average Rubyists. He probably wouldn’t expect it either, so it’s well worth it to do what it takes to make him happy. And once you have a team of happy Rubyists, when you need to find another one, it will be easier to do because we talk about our jobs all the time to other Rubyists. And awesome Rubyists tend to talk to other awesome Rubyists, so your recruiting efforts will become much easier down the road.