Ruby 2.7 adds Time#ceil and Time#floor methods


Ruby 2.7 has added new methods for Time:

Time#floor

There are cases where we want to truncate decimals in order to compare or save times with different accuracy. Ruby adds Time#floor to truncate the specified decimal places i.e. rounding down the decimal part of Time to the specified digit.

In mathematics and computer science, the floor function is the function that takes as input a real number x and gives as output the greatest integer less than or equal to x

Ruby 2.7 now allows to perform this floor operation with specification of precision:

t = Time.utc(2010,3,30, 5,43,"25.123456789".to_r)
t.iso8601(10)
#=> "2010-03-30T05:43:25.1234567890Z"

# Specify precision (number of digits) to the argument
t.floor(0).iso8601(10)
#=> "2010-03-30T05:43:25.0000000000Z"
t.floor(1).iso8601(10)
#=> "2010-03-30T05:43:25.1000000000Z"
t.floor(2).iso8601(10)
#=> "2010-03-30T05:43:25.1200000000Z"
...
t.floor(9).iso8601(10)
#=> "2010-03-30T05:43:25.1234567890Z"
t.floor(10).iso8601(10)
#=> "2010-03-30T05:43:25.1234567890Z"

The default precision value that is passed to the function is 0:

t.floor.iso8601(10)
#=> "2010-03-30T05:43:25.0000000000Z"

t = Time.utc(1999,12,31, 23,59,59)
(t + 0.4).iso8601(3)
#=> "1999-12-31T23:59:59.400Z"
(t + 0.4).floor.iso8601(3)
#=> "1999-12-31T23:59:59.000Z"

(t + 1.5).iso8601(3)
#=> "2000-01-01T00:00:00.500Z"
(t + 1.5).floor.iso8601(3)
#=> "2000-01-01T00:00:00.000Z"

Time#ceil

Since Time#floor was introduced, the complementary Time#ceil was also added to control decimal precision and rounding up the decimal part of Time to the specified digit.

t = Time.utc(2010,3,30, 5,43,"25.0123456789".to_r)
t.iso8601(10)
#=> "2010-03-30T05:43:25.0123456789Z"

# Specify precision (number of digits) to the argument
t.ceil(0).iso8601(10)
#=> "2010-03-30T05:43:26.0000000000Z"
t.ceil(1).iso8601(10)
#=> "2010-03-30T05:43:25.1000000000Z"
t.ceil(2).iso8601(10)
#=> "2010-03-30T05:43:25.0200000000Z"
...
t.ceil(7).iso8601(10)
#=> "2010-03-30T05:43:25.0123457000Z"
t.ceil(8).iso8601(10)
#=> "2010-03-30T05:43:25.0123456800Z"
t.ceil(9).iso8601(10)
#=> "2010-03-30T05:43:25.0123456790Z"
t.ceil(10).iso8601(10)
#=> "2010-03-30T05:43:25.0123456790Z"

The default precision value that is passed to the function is 0:

t.ceil.iso8601(10)
#=> "2010-03-30T05:43:26.0000000000Z"

t = Time.utc(1999,12,31, 23,59,59)
(t + 0.4).iso8601(3)
#=> "1999-12-31T23:59:59.400Z"
(t + 0.4).ceil.iso8601(3)
#=> "2000-01-01T00:00:00.000Z"

(t + 1.5).iso8601(3)
#=> "2000-01-01T00:00:00.500Z"
(t + 1.5).ceil.iso8601(3)
#=> "2000-01-01T00:00:01.000Z"

Time#floor and Time#ceil act as good ways to compare time in smaller scale and desired precision in applications that would care about and rely on times in microseconds, etc and below.