Search code examples
rubydatetimecomparison

DateTime comparison and math in Ruby


I'm trying to writing a class to do some math with DateTime. In the actual situation I receive the DateTimes like this:

2015-08-26T12:10:54Z
2015-08-31T05:07:01Z
2016-01-05T10:57:02Z
2016-01-05T10:57:04Z

I need to take these times and compare them with the actual time, roughly like this:

dif = time - Time.now

Then I need to take the result of the math above and see if it is equal or greater than 45 minutes, roughly like this:

threshold = 00:45:00
if dif >= threshold
  puts dif
  #do something
else
  #do something else
end

Normally the difference will be calculated using same day timestamps, but rarely it could face something like the passage from a day to another.

I tested the following code:

irb(main):001:0> t1 = Time.now
 => 2016-01-08 18:53:58 +0000
irb(main):002:0> t2 = Time.now
 => 2016-01-08 18:54:09 +0000
irb(main):003:0> dif = t2.to_f - t1.to_f
 => 10.176163911819458

But then I couldn't turn this result back to a readable time, like 00:00:11.

What is the best way to do the math so when the code shows the difference it comes in the correct format like 00:14:59?


Solution

  • There is a Time library which you can require and then it will extend the default Time class with extra methods, like #parse.

    require 'time'
    t1 = Time.parse('2015-08-26T12:10:54Z') #trusting the heuristic to match this as ISO8601 type date
    t2 = Time.parse('2016-01-05T10:57:02Z')
    
    > t2 - t1 
    => 11400368.0 #difference in seconds
    

    As the time is now in seconds, you can easily check for a difference threshold of 45*60. However you have to be very careful to use the same timezone on both date.

    You gave an example with Time.now however it will be calculated from your local timezone while the dates you have provided are in UTC (with the "Z" at the end). Subtracting them can give you different result when Daylight Saving is active or inactive in your timezone.

    If every date you check against the Time.now is in UTC, you should use Time.now.utc instead.

    To calculate a time difference you can use the Time.utc(0) as base.

    > Time.utc(0)
    => 0000-01-01 00:00:00 UTC
    > Time.utc(0) + 11400368.0
    => 0000-05-11 22:46:08 UTC
    

    You can easily extract the hour:minutes:seconds from here.