[Cosmo-dev] cosmo.datetime.Date questions

Matthew Eernisse mde at osafoundation.org
Mon Jan 22 22:02:03 PST 2007


Moving this from the bug comment to the list to get some discussion.

Bobby reopened bug 7715, because we have some questions we need to 
answer before we can decide about what it means to 'fix' the problem. 
I'll try to describe in a bit of detail what the problem actually is by 
looking at Bobby's points below.

> a) the behavior is still undefined. Saying that they behave 
> "exactly as JS Date" functions is not good enough - especially 
> as it doesn't seem to be the case - creating a new Cosmo date 
> and then setting the date to Feb behaves differently than a 
> "normal" Date.

Foolishly, for one brief, shining moment, I thought I could fix the 
issue by adding a no-arg case for the constructor function, since I 
hadn't handled it explcitly -- and it made the Feb. problem go away! 
Sadly, I was just playing the denial game -- it actually fixed zilch.

The behavior of the setter methods is actually very well defined. And 
unfortunately -- at least in this case -- they really do behave 
*exactly* like the native JS Date setters. In fact, that is precisely 
the problem.

The example here is setting the month to Feb.

The Cosmo date in the service call is getting instantiated with no args, 
so the behavior before my change today in r3431 was to create a Cosmo 
date of 12/31/1899. (Okay, so the year is weird, that that's not what 
caused the problem. It's the fact that the initial date of the month is 
the 31st.)

Watch:

js> var d = new Date('12/31/1899');
js> d;
Sun Dec 31 1899 00:00:00 GMT-0600 (CST)
js> d.setMonth(1);
-2235232800000
js> d;
Fri Mar 03 1899 00:00:00 GMT-0600 (CST)

The setter is smart, so it knows that the 31st is not a valid date in 
February (zero-based months, so '1' is Feb.). You can't have 
'2/31/1899,' so it wraps the date around to the equivalent date in March 
-- '3/3/1899.'

According to the console, the setters for event dates are getting called 
in this order:

setMonth
setYear
setSeconds
setDate
setHours
setMinutes

That's why February events are going away -- the date is instantiated as 
12/31, and changing the month to Feb. pushes the date into March before 
setDate is even called. And of course, when you go into March, those 
events aren't retrieved in the initial query for events, so they don't 
show up there either.

The old CosmoDate was just a dumb bag of attributes, and a no-arg 
instantiation would just create an empty object. This is not so with the 
native JS Date -- call it with no args, and it creates a Date object set 
to the current date and time. The new Cosmo date code works the same way.

With the old CosmoDate, the setters would happily set the numbers to 
whatever value you wanted. You could have set the month value to 666 if 
you wanted to. But you can't do that with native JavaScript Dates, and 
you can't do that with the new code in cosmo.datetime.Date.

> b) the unit tests still fail (even ones that don't use the setters
> in Safari) If unit tests are failing, the bug is still open - 
> either the unit tests have to be changed to reflect a new 
> understanding (accompanied by documentation) of what the code is 
> supposed to do, or the code has to be changed to make the tests 
> pass.

More documentation would indeed be helpful. There are definitely some 
fuzzy areas around how it handles instantiation  (e.g., the no-arg 
case), and things like what happens when you change the timezone.

But from what I can see from the above data, and the tests that I 
originally wrote, the setters are behaving exactly as expected -- 
assuming 'expected' means "exactly the way the native JavaScript Date 
setters behave given a certain date." As far as I can see, any 
documentation we could come up with for that would be a regurgitation of 
the standard JS docs for Date.

> c) Since no code is using these setters, what are we getting from 
> them except the danger that someone might use them, in which case 
> they might break stuff?

The point of this change was to have a fully functioning Date object to 
use in the client-side code -- one that would have the same API as the 
JavaScript Date object, but that wouldn't be retarded about timezones.

There are already numerous places in the code that involve jumping back 
and forth between Cosmo dates and native JS Dates to get access to some 
of the intelligence of the JS Date object. With the new Cosmo date code, 
all that stuff works like you'd expect with a Date, and you don't have 
to have any of that stuff sitting out in the app code.

At least right now, it seems like the only thing that is broken is the 
service call, because it's using passing no args to the constructor and 
then setting attributes one-by-one with setters -- instead of passing 
the attributes in as params the way you would instantiating a native JS 
Date.

Basically it looks like we have three choices:

1. Back out the changes, and return the Cosmo dates to being pretty much 
plain hashes.

Advantages
The original code for the service call would work perfectly.

Disadvantages
We would continue using throwaway native JS Dates in our app code in 
cases where the dumb attributes are not sufficient. Timezone data in the 
Cosmo dates would not work with those ad-hoc Dates in an integrated way. 
Some modest amount of work would be needed to revert the code and test.

2. Stick to the raw attribute values for the service call and anywhere 
else we need to serialize/deserialize instead of trying to use the setters.

Advantages
No more changes to the code have to happen. It's marginally faster than 
calling all the setters. Developers would have access to a 
timezone-aware cosmo.datetime.Date that has a compatible API with the 
native JS Date.

Disadvantages
Tests would have to be updated to reflect the actual behavior of the 
code. Developers would have to be aware that cosmo.datetime.Date has a 
compatible API with the native JS Date.

3. Change the service code to use params with the constructor for Cosmo 
dates. It would look something like this:

if (object.javaClass.indexOf('CosmoDate') > -1) {
     var o = object;
     var newObject = new constructor(o.year, o.month, o.date,
         o.hours, o.minutes, o.seconds, o.tzId, o.utc);
}

This doesn't seem to buy us much over number 2 above, but it's another 
way to skin the cat.

Advantages
Pretty much the same as number 2 above.

Disadvantages
Pretty much the same as number 2 above.

Since nothing appears to be actually amiss in the cosmo.datetime.Date 
code, I'd probably lean toward number 2, but I would also like to get 
feedback from other people.

Thanks.


Matthew


More information about the cosmo-dev mailing list