Date arithmetic in Ruby is possible because Ruby’s time objects are stored internally as numbers. Additions to dates and differences between dates are handled by adding to and subtracting the underlying numbers. Time and DateTime objects are a bit different. Time is a wrapper for the Unix or POSIX standard time defined as the number of seconds elapsed since midnight of January 1, 1970, that is Time.at(0), and DateTime is a Ruby implementation. Subtracting two Time object gives the distance in seconds as a floating-point number. Subtracting two Date or DateTime objects gives the number of days.

>> t1 = Time.local(2009,12,2)
=> Wed Dec 02 00:00:00 +0100 2009
>> t2 = Time.local(2009,12,1)
=> Tue Dec 01 00:00:00 +0100 2009
>> t1-t2
=> 86400.0

86400 is the number of seconds in a day: 60*60*24. The same lines for Date or DateTime objects result in a number of days:

>> d1 = Date.new(2009,12,2)
=> Wed, 02 Dec 2009
>> d2 = Date.new(2009,12,1)
=> Tue, 01 Dec 2009
>> (d1-d2).to_i
=> 1

Rails offers also nice ‘ago’ and ‘from_now’ functions in ActiveSupport that allow computing lengths of time in a more human-readable way:

Date.today           # => Thu, 25 Dec 2008
Date.yesterday       # => Wed, 24 Dec 2008
DateTime.now         # => Thu, 25 Dec 2008
1.day.ago            # => Wed, 24 Dec 2008
1.day.from_now       # => Fri, 25 Dec 2008

These functions also work with weeks and months:

1.week.ago            # => Thu, 18 Dec 2008
1.week.from_now       # => Thu, 01 Jan 2009
1.month.ago           # => Tue, 25 Nov 2008
1.month.from_now      # => Sun, 25 Jan 2009

and with terms:

(2.hours + 40.minutes).from_now   # => Thu, 25 Dec 2008 17:40:00
4.minutes                         # => 240 seconds
12.hours                          # => 43200 seconds
3.weeks.from_now                  # => Thu, 15 Jan 2008 15:00:00
3.weeks                           # => 21 days
Advertisements