[Ruby] How to get the next value of the Time object?

1 minute read

Overview

When dealing with Time objects in Ruby, I hit a boundary problem. If you do it normally, you won’t have that much of a problem using the Range object, but I stumbled over something unusual.

Environment

Ruby: 2.6.2 Rails: 5.1.2

The problem I was addicted to in the first place

Time.now.end_of_day
=> 2020-05-15 23:59:59 +0900

I want to take the next value of this.

  • Because end_of_day is easy to understand, I only use it, and I do not want the beginning and end of a certain day. The next value of the Time object until you get tired of it

This was the first thing I came up with.

Time.now.end_of_day + 1
=> 2020-05-16 00:00:00 +0900

But this is wrong

(Time.now.end_of_day + 1).iso8601(3)
=> "2020-05-16T00:00:00.999+09:00"

You can’t use + 1 because it adds 1 second until you get tired of it, and does not move to the next value.

When I was fishing the Time class, I found a method that looked very similar https://docs.ruby-lang.org/ja/latest/method/Time/i/succ.html

Time.now.end_of_day.succ
(pry):109: warning: Time#succ is obsolete; use time + 1
=> 2020-05-16 00:00:00 +0900

However, it seems that he is doing the same thing as + 1 because he is angry when he uses it because it is outdated. No good.

Solution

After all I did not know the good way, so I pushed it

As for the problem of the example, I have seen only the decimal 9 digits

(Time.now.end_of_day + 1).iso8601(10)
=> "2020-05-16T00:00:00.9999999990+09:00"

In other words, add 1 nanosecond

(Time.now.end_of_day + 1/1000000000.0).iso8601(9)
=> "2020-05-16T00:00:00.000000000+09:00"

did it!

bonus

Time.now.iso8601(10)
=> "2020-05-15T19:56:55.4979370000+09:00"

Time.new(2020, 5, 16, 16, 59, 59.3).iso8601(9)
=> "2020-05-16T16:59:59.299999999+09:00"

Time.parse("2020-05-16T16:59:59.3+09:00").iso8601(9)
=> "2020-05-16T16:59:59.300000000+09:00"

Time.parse("2020-05-16T16:59:59.35555555555555555555+09:00").iso8601(20)
=> "2020-05-16T16:59:59.35555555555555555555+09:00"

It was no good

Conclusion

  • The number of fractional seconds in the Time object can be infinite
  • Therefore, there is no concept of the next value
  • However, it depends on how to generate the Time object, so if you pull it from the DB, you cannot force it if you consider the number of significant digits.
  • In the first place, it should be compared without using the Range object in the first place