ruby_time

Time comparison in Ruby

| 6 Comments

I believe every ruby developer has faced time comparison issue at least once and tests are one of the possible areas where it may happen. RSpec message like this may confuse:

What’s wrong?

Investigation

Let’s create two Time objects:

At the first glance, they are equal. But it’s not true:

The issue occurs because ruby Time makes comparison with fractions of seconds. We may use to_f method to see the difference between t1 and t2:

or to_r method to get rational numbers:

Summary

If you don’t care about milliseconds, you may compare timestamps using to_i method:

or make a new Time object from timestamps to have better RSpec failure messages:

But even better to use fixed times in our tests.

Share
* Railsware is a premium software development consulting company, focused on delivering great web and mobile applications. Learn more about us.
  • Maxime Garcia

    Or instead of rounding to the second, you embrace a difference of less a second :
    expect(t1).to be_within(1.second).of(t2)

    • http://shime.github.com/ Hrvoje Šimić

      1.second is from ActiveSupport, so this will not work in plain old Ruby.

      I prefer to use the technique Lionel mentioned above, just nicely format the time and then compare strings.

      RSpec::Matchers.define :be_the_same_time_as do |expected|
      match do |actual|
      expect(expected.strftime("%d-%m-%Y %H:%M:%S")).to eq(actual.strftime("%d-%m-%Y %H:%M:%S"))
      end
      end

      describe "time comparison" do
      it "passes for equal time" do

      expect(Time.now).to be_the_same_time_as Time.now
      end
      end

      • http://emaxime.com/ Maxime Garcia

        irb(main):001:0> t1 = Time.now
        => 2014-04-14 23:08:45 +0200
        irb(main):002:0> t1.to_f
        => 1397509725.5656137
        irb(main):003:0> Time.now – t1
        => 12.845386198

        As be_within matcher works with the minus function :
        expect(t1).to be_within(1).of(t2)

        The “.second” is not necessary.

  • Lionel Tan

    Great explanation and solution to how to solve Time comparisons.

    I used to do it by casting it to a string like below:

    a, b = Time.now, Time.now

    a_to_s = a.strftime(‘%Y-%m-%d %H:%M:%S’)
    b_to_s = b.strftime(‘%Y-%m-%d %H:%M:%S’)

    a_to_s == b_to_s

  • http://blog.plicatibu.com/ Marcio Andrey Oliveira

    You may do the following (assuming t1 and t2 are Time instances)


    require 'date'

    t1.to_date == t2.to_date

  • Ahmad hamza

    Hi i m comparing time like this “if a.start_time<= client.start" but a.start_time has the value "1970-01-01 09:00:00 UTC" and "2000-01-01 09:00:00 UTC". How to change that a.start_time ? Any idea

Want to get more of Railsware blog?

RSS FEED

We're always ready to help!

CONTACT US