In Ruby, on Halloween:
Date.today - 6.months + 6.months != Date.today
Do we need to update Ruby's date implementation? Do other languages have the same issue?
A year is divided into 12 months in the modern-day Gregorian calendar. The months are either 28, 29, 30, or 31 days long.
There are two calendars--one for normal years with 365 days, and one for leap years with 366 days. Leap years are divisible by 4.
This happens if you do it to any month that doesn't have 31 days (i.e. 3 months would work just fine, but 1 month, or 6, or 8 would all make this happen).
If you do Date.today - 1.month
, it looks like Rails sees that 9/31/2011 isn't a valid date, so it kicks it back an extra day to make it a valid date. However, when you go one month forward from the end of September, it'll leave it at 10/30/2011 since that's a valid date. Basically, Rails just tries to increment (or decrement) the month field and as long as it's a valid date, it won't adjust the day field.
One way to work around this is to use the .end_of_month
(or .beginning_of_month
) method on a Date
object in Rails to make sure you're consistently getting the end or beginning of a month.
No, this is expected and this isn't unique to Ruby either - try it in SQL, for example.
(Today - 6 months)
is the last day (30th) of April - because there is no 31st. It's only the months we're dealing with, not a precise number of days.
Add 6 months to April 30th and you get October 30th.
Which, as you know is != October 31st.
This is a weird feature of ActiveSupport time extensions.
> 6.months == 180.days
=> true
but when you do date math with months, they are considered calendar months, not 30-day periods. Check this out:
> Date.today - 180.days + 180.days
=> Mon, 31 Oct 2011
See https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/time/calculations.rb#L277 and dig further from there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With