Skip to content

Dates and Times in Rails

Larry Reid edited this page Jul 5, 2017 · 4 revisions

This is a cheat-sheet for dates and times Rails.

Background

What to Do in Your Application

  • Leave the Rails server time zone as the host's time zone. There are enough things to confuse you without this additional variable

  • You need to be careful how you get the current date or time. Only certain ways use the Rails application time zone. The first two articles above have good summaries of this topic

  • You need to be careful if you parse times, for the same reason as above

  • You will need a preferred time zone for each user. In app/controllers/application_controller.rb, do this:

    def user_time_zone
      current_user.time_zone
    end
    

    User#time_zone returns a Rails ActiveSupport::TimeZone object. More on it later.

  • Make sure that all controllers are using the user's time zone:

    around_action :use_user_time_zone, if: :current_user
    
    def use_user_time_zone(&block)
      Time.use_zone(user_time_zone, &block)
    end
    

    The around_action executes the controllers in a block, so the time zone gets unset after your action completes. It's possible to confuse Rails (apparently) if you just do a before_action.

  • In testing, you should use a time zone that is neither the server's time zone, nor the time zone of the client where you're testing from. You're more likely to uncover problems where the time zone is not getting set correctly, if the tests run in a time zone that's different from your workstation and your server. I like to use Samoa's time zone, as it's one I'm not likely to ever actually be in.

This approach requires extra thinking in setting up and checking the test data, but that's sort of the point.

Testing Time Zones

  • For unit tests that will be testing time-related functionality, do this:
test "demo time test" do
  Time.use_zone(ActiveSupport::TimeZone["Samoa"]) do
    # Write your test here
  end
end
  • For other types of tests, you have to arrange for user_time_zone to return the right value for your test. The around_action in ApplicationController will then handle it for you

Testing Time-Related Events

Sometimes you need to test time-related events. For example, you need to test that the application generates a reminder when the current time is 24 hours before the scheduled time of some event. Rails has some simple built-in support (as of Rails 4.1): http://api.rubyonrails.org/v5.1.1/classes/ActiveSupport/Testing/TimeHelpers.html.

Using the built-in support, you could write a test case that sets the "time" to 24 hours before the start time of the event (which might be in a fixture, for example). Then you can always test the code without worrying about having to change the test data.

There is also the timecop gem, which has extensive support for mucking with the time. One of the things timecop can do is simply freeze the time, which is useful in some cases. Note, however, that freezing the time is incompatible with Capybara testing, as it messes with Capybara's handling of asynchronous events in the browser.

General Date and Time Programming

There are some general tips and tricks about programming dates and times, but I'll have to leave that for another day.

Home

[Collaborating on Projects](Using GitHub to Collaborate on We Enhance IT Projects)

Clone this wiki locally