The maximum precision of times in Ruby is in the nanosecond range. So 0.000000001 second. This is the same for Time, as for DateTime.
However, Ruby on Rails has a different understanding of the end of the day when it comes to the nanoseconds.
Times in Rails
Ruby on Rails has extended the time classes with useful functionalities. For example, end_of_day:
DateTime.now.end_of_day # => Sun, 20 Nov 2016 23:59:59 +0100 Time.now.end_of_day # => 2016-11-20 23:59:59 +0100
Attention! Whenever the time zone is relevant, Time.current is your friend.
The problem in Rails
Since Time as well as DateTime deal with nanoseconds:
DateTime.now.nsec # => 249095319 Time.now.nsec # => 483323251
It is assumed that the end of a day is the same for objects of both classes:
RSpec.describe '#end_of_day' do it 'returns the same milliseconds as DateTime' do expect(Time.now.end_of_day.nsec).to eq(DateTime.now.end_of_day.nsec) end end
But that is not true:
1) #end_of_day returns always same milliseconds expected: 0 got: 999999999 1 example, 1 failure
The problem: the end of a day for Time is exactly 999999999 nanoseconds later than it is for DateTime.
This difference seems somewhat unexpected, but is actually wanted. The implementation at both classes:
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 173 def end_of_day change( :hour => 23, :min => 59, :sec => 59, :usec => Rational(999999999, 1000) ) end # File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 113 def end_of_day change(:hour => 23, :min => 59, :sec => 59) end
Therefore it is recommended to favor Time over DateTime when it comes to the end of day. Because according to DateTime a time between 23:59:59 and 24:00:00 is undefined: it is neither before the end of the day nor after the beginning of a day:
(DateTime.tomorrow.beginning_of_day - 0.1.second) < DateTime.now.end_of_day # => false
The same applies to all time transitions. So all day endings (#end_of_month and #end_of_year), but also #end_of_hour and #end_of_minute.
Update - 2017-03-05:
The Rails Core Team has fixed the inconsistency. The PR #28242 has been merged. It is expected that DateTime will also set the usec for all end_of methods with Rails version 5.1.