Joe Frambach Joe Frambach - 2 months ago 14
Ruby Question

1.year.from_now is also one day ahead

Today's date is 2016-09-19. I add one year to it, and I expect the result to be 2017-09-19. Instead, I get 2017-09-20. One year plus one day ahead. Is this behavior as intended?

$ rails c
2.3.1 :001 > Time.now.to_date.iso8601
=> "2016-09-19"
2.3.1 :002 > 1.year.from_now.to_date.iso8601
=> "2017-09-20"

Answer

since or its alias from_now calculate the offset based on Time.current which is equivalent to Time.zone.now – both return a ActiveSupport::TimeWithZone instance:

Time.current  #=> Mon, 19 Sep 2016 19:56:34 SST -11:00
Time.zone.now #=> Mon, 19 Sep 2016 19:56:35 SST -11:00

Time.now on the other hand returns an ordinary Time instance in your system's timezone, which can differ from the Rails timezone:

Time.now #=> 2016-09-20 08:56:36 +0200

To avoid confusion, you should always use Time.current / Time.zone.now when working within Rails. You can however pass another "base time" to since:

1.year.since(Time.now) #=> 2017-09-20 08:56:37 +0200

Or, because you are working with dates:

1.year.since(Date.today) #=> Wed, 20 Sep 2017

There is also Date.current which is equivalent to Time.zone.today:

1.year.since(Date.current) #=> Wed, 19 Sep 2017