[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