Forum: Ruby on Rails Very simple Date math goes randomly bonkers

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
2adcab94830cc4abd3610984fbe5225c?d=identicon&s=25 Matt Darby (mdarby)
on 2008-12-08 19:56
(Received via mailing list)
I have a "timesheet" in my app that simply displays the week range
based on a passed in date (params[:date]).
The view iterates through the Date::ABBR_DAYNAMES and shows a link to
the corresponding date.

Trouble is that about 40% of the time the calculated dates go bonkers.
Am I missing something?

Model:
  # Get a date range of the week that a particular date falls in
  # This is broken out like mad for diagnostics
  def self.get_work_week_date_range(date)
    monday   = date.monday
    sunday   = monday - 1.day
    eow      = date.end_of_week
    saturday = eow - 1.day

    dates = [sunday, saturday]

    logger.info
(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
    logger.info(">>>>> #{date}.monday = #{monday}")
    logger.info(">>>>> #{monday}-1.day = #{sunday}")
    logger.info(">>>>> #{date}.end_of_week = #{eow}")
    logger.info(">>>>> #{eow}-1.day = #{saturday}")
    logger.info(">>>>> #{date} == [#{dates[0]}, #{dates[1]}]")
    logger.info
(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")

    dates
  end

Logger output:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>> 2008-12-08.monday = 2008-12-08
>>>>> 2008-12-08-1.day = 2008-12-07
>>>>> 2008-12-08.end_of_week = 2008-12-14
>>>>> 2008-12-14-1.day = 2008-12-13
>>>>> 2008-12-08 == [2008-12-07, 2008-12-13]
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

... n times later ...
2505b282d57c29be797dc35b245adb4c?d=identicon&s=25 Philip Hallstrom (Guest)
on 2008-12-08 20:16
(Received via mailing list)
On Dec 8, 2008, at 10:55 AM, Matt Darby wrote:

>
> I have a "timesheet" in my app that simply displays the week range
> based on a passed in date (params[:date]).
> The view iterates through the Date::ABBR_DAYNAMES and shows a link to
> the corresponding date.

What do you pass to get_work_week_date_range?  Is it a string?  Or an
instance of Date?  Or Time?

If it worked once it should always work.  Which suggests that maybe
you're passing in something different from time to time?  One time a
Date, one time a Time?

Maybe?

Put together a test and explicitly pass the *same* argument (class and
value) and see if you can duplicate it.
2adcab94830cc4abd3610984fbe5225c?d=identicon&s=25 Matt Darby (mdarby)
on 2008-12-08 20:30
(Received via mailing list)
> What do you pass to get_work_week_date_range?  Is it a string?  Or an  
> instance of Date?  Or Time?

I pull the date in from the params hash, and immediately parse it to a
Date:
Date.parse(params[:date]) rescue Date.today

> If it worked once it should always work.  Which suggests that maybe  
> you're passing in something different from time to time?  One time a  
> Date, one time a Time?

You're right, that's why I've pounded my head against the wall for a
week!
This method is only called from one other method, and I've extracted
it really only for testing.

> Put together a test and explicitly pass the *same* argument (class and  
> value) and see if you can duplicate it.

All tests pass :(

  it "should know how to get the week based on a date" do
    TimeCard.get_work_week_date_range(Date.parse("2008-08-05")).should
== [Date.parse("2008-08-03"), Date.parse("2008-08-09")]
    TimeCard.get_work_week_date_range(Date.parse("2008-01-01")).should
== [Date.parse("2007-12-30"), Date.parse("2008-01-05")]
    TimeCard.get_work_week_date_range(Date.parse("2008-02-29")).should
== [Date.parse("2008-02-24"), Date.parse("2008-03-01")]
    TimeCard.get_work_week_date_range(Date.parse("2007-02-28")).should
== [Date.parse("2007-02-25"), Date.parse("2007-03-03")]
  end
81b61875e41eaa58887543635d556fca?d=identicon&s=25 Frederick Cheung (Guest)
on 2008-12-08 21:15
(Received via mailing list)
On Dec 8, 6:55 pm, Matt Darby <m...@matt-darby.com> wrote:

>
>
> >>>>> 2008-12-08.monday = 2008-12-08
> >>>>> 2008-12-08-1.day = 1772-05-19
> >>>>> 2008-12-08.end_of_week = 3428-04-08
> >>>>> 3428-04-08-1.day = 3191-09-18
> >>>>> 2008-12-08 == [1772-05-19, 3191-09-18]

Perhaps the key thing to note is that 1772-05-19 is about 236 years
and 7 months ago, which (get your calculators out) is about 86400, ie
the number of seconds in a day. Whereas on an instance of Time, +/- 1
means +/- 1 second, on instances of Date/DateTime +/- means +/- 1
second. That is I suspect the basic problem.

On newer versions of rails, things like 1.day are smart enough to do
the right thing whether or not you add a date or a Time to them (the +
method on Date is overriden to check if the argument is a thing like
1.day).
Somewhere this has gone wrong. If you have any plugins that mess with
dates (or if you've being doing stuff like that yourself) then I'd
have a look at those - it could be something like once some random
model is loaded some extensions to Date are pulled in at that point
and from then onwards calculations are borked.

Fred
2adcab94830cc4abd3610984fbe5225c?d=identicon&s=25 Matt Darby (mdarby)
on 2008-12-08 21:41
(Received via mailing list)
> Perhaps the key thing to note is that 1772-05-19 is about 236 years
> and 7 months ago, which (get your calculators out) is about 86400, ie
> the number of seconds in a day. Whereas on an instance of Time, +/- 1
> means +/- 1 second, on instances of Date/DateTime +/- means +/- 1
> second. That is I suspect the basic problem.

Man, good call.

> On newer versions of rails, things like 1.day are smart enough to do
> the right thing whether or not you add a date or a Time to them (the +
> method on Date is overriden to check if the argument is a thing like
> 1.day).

I'm using 2.2.2, but...

> Somewhere this has gone wrong. If you have any plugins that mess with
> dates (or if you've being doing stuff like that yourself) then I'd
> have a look at those - it could be something like once some random
> model is loaded some extensions to Date are pulled in at that point
> and from then onwards calculations are borked.

... I do monkeypatch Date, but I ensured that I wasn't actually
overriding any existing method.

Thanks for you help Fred, this smells like the right track.
2adcab94830cc4abd3610984fbe5225c?d=identicon&s=25 Matt Darby (mdarby)
on 2008-12-08 23:05
(Received via mailing list)
It was the facets/time library. It was loaded in a totally separate
part of the app, in a method that had not much to do with anything.

Thanks again Frederick; that one got your a WWR recommendation ;)
This topic is locked and can not be replied to.