Very simple Date math goes randomly bonkers

0 views
Skip to first unread message

Matt Darby

unread,
Dec 8, 2008, 1:55:58 PM12/8/08
to Ruby on Rails: Talk
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 ...

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>> 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]
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Philip Hallstrom

unread,
Dec 8, 2008, 2:15:25 PM12/8/08
to rubyonra...@googlegroups.com

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.

Matt Darby

unread,
Dec 8, 2008, 2:29:40 PM12/8/08
to Ruby on Rails: Talk
> 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

Frederick Cheung

unread,
Dec 8, 2008, 3:14:19 PM12/8/08
to Ruby on Rails: Talk


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 = 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 ...
>
>
>
> >>>>> 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

Matt Darby

unread,
Dec 8, 2008, 3:40:53 PM12/8/08
to Ruby on Rails: Talk
> 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.

Matt Darby

unread,
Dec 8, 2008, 5:04:13 PM12/8/08
to Ruby on Rails: Talk
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 ;)
Reply all
Reply to author
Forward
0 new messages