Possible bug in Calendar

H

Harold Yarmouth

Jean-Baptiste Nizet said:
I have the feeling that Calendar.getInstance() is not returning a
singleton, and that it is also not zeroing out newly-created instances.

Of course it's not returning a singleton, since the javadoc of the
getInstance method explicitely says that "The Calendar returned is
based on the current time [...]".

That's ambiguous. Could have meant the current time from the viewpoint
of the guy writing the documentation, so, the time the documentation got
written.

Yes, that would be perverse.

And yes, I've seen worse.
The calendar object reuses the milliseconds as they were at the time
of the creation, i.e. of your getInstance call. But since you're
calling getInstance twice, you have two different instances of
Calendar, each with different milliseconds.

And therein derives the problematic behavior: using Calendar in the
"natural way" as a date builder results in dates that have an
essentially-random component.
 
H

Harold Yarmouth

Lew said:
Of course it's not returning a singleton, since the javadoc of the
getInstance method explicitely says that "The Calendar returned is
based on the current time [...]".

Which could, perversely, be referring to the time the documentation was
being written. Stranger things have happened.
Of course Calendar doesn't zero out newly-created instances, since it's
defined to assign the current time to newly-created instances.

Which is silly, or at least including the milliseconds is silly.

Consider: the main and most "natural" use of Calendar is in

Calendar c = Calendar.getInstance();
c.set(y, mm, d, h, m, s);
Date d = c.getTime();

and this results in a Date with an effectively random set of
milliseconds instead of in a Date wholly determined by y, mm, d, h, m,
and s.

This is, at best, counterintuitive, if not downright broken.

Furthermore, since the current time can be gotten with new Date(), so
you don't need Calendar.getInstance().getTime() to do this, there's
really no reason for Calendar.getInstance() not to zero out *at least*
the milliseconds if not the whole darn thing.
 
H

Harold Yarmouth

Mark said:

Yes, unless there's an obvious reason for a polymorphic implementation,
such as the method's return value has dynamically variable qualitative
behavior (not just dynamically variable in a parametrizable way).
 
H

Harold Yarmouth

Arne said:

Yes, unless there's a clear need for a polymorphic value to be returned,
which would be the case if the value's behavior may vary qualitatively
(so, not just in a parametrizable way).
That is something you have misunderstood.

That is a gratuitous insult. Please stop posting namecalling and other
personal attacks to this newsgroup and limit your remarks to those about
Java, not those about other people here. Thank you.
I just grepped the Java API docs. There are nine no-arg getInstance
methods. Of those zero are singletons.

In the core API, perhaps. If you use lots of libraries and other
third-party code, you'll find rather a different statistical pattern in
that vastly larger code-base.
 
H

Harold Yarmouth

Mike said:
Calendar cal = Calendar.getInstance();
cal.setTime(.....)
Calendar cal2 = Calendar.getInstance();
cal2.setTime(....) // D'oh!

Except that by far the primary usage pattern is

getInstance()
set(...)
Date d1 = getTime();
getInstance()
set(...)
Date d2 = getTime();
etc.

Builder objects that get overwritten with each use aren't considered a
problem, because you usually extract an instance of the immutable output
object type with each use.

I'm thinking that perhaps part of the design problem with Calendar (and
the behavior of clear() mentioned elsewhere seems equally, if not more
problematic) is that it has fuzzily-defined/multiple responsibilities,
perhaps being used as a Date builder and as a mutable Date itself, and
even perhaps for other purposes. Multiple classes with separate,
narrower responsibilities might have been a better design choice.
 
H

Harold Yarmouth

Arne said:
That may be the case in the unknown YarmouthLib, but it is most
certainly not the case in the Java library.

It is the case in a large number of Java libraries, if not in Sun's own
core classes.
 
H

Harold Yarmouth

Roedy said:
This is not a bug because the behaviour is documented and consistent
with the documentation.

Technically, perhaps. I'd say it's a bug, but the bug is at a higher
abstraction level than "the code doesn't perform to spec in case XYZ".
Instead, the design itself is flawed, i.e. has a bug.

Unfortunately, design issues are subject to more subjectivity than are
code-behavior-vs.-spec issues, which tend to be pretty cut-and-dried.

This could be argued over endlessly, but a statement from elsewhere in
this thread seems apropos:

Joshua said:
FWIW, many people would consider the Calendar API to be a shining example of poor design.

My guess is the class was given overloaded responsibilities and ended up
compromising its performance of all of them as a result. In this case,
perhaps its ability to do a good job in its "DateBuilder" role was
compromised by making it conform to some other role.
I usually call these "gotchas", but I think this sort of thing
deserves another name, something closer to "design flaw".

Indeed. See above.
 
J

Joshua Cranmer

Harold said:
A constructor would have worked as well and potentially caused less
confusion.

Okay, should I be constructing a GregorianCalendar, BuddhistCalendar,
JulianCalendar, what? Constructors aren't polymorphic, Calendars are.

Please note that the semantics are defined in the documentation.

Let me repeat: they're DOCUMENTED. This isn't something that's buried in
paragraph 9 of the 30th page, it's mentioned in paragraph 3 of the class
documentation at about the position my eyes naturally gravitate towards.

Also, this is not a notation unique to the Calendar class; a subset of
classes in Java also use similar semantics for getInstance.

I haven't checked the tutorials, but it's probably discussed there as well.
 
L

Lew

Joshua said:
Okay, should I be constructing a GregorianCalendar, BuddhistCalendar,
JulianCalendar, what? Constructors aren't polymorphic, Calendars are.

Please note that the semantics are defined in the documentation.

Let me repeat: they're DOCUMENTED. This isn't something that's buried in
paragraph 9 of the 30th page, it's mentioned in paragraph 3 of the class
documentation at about the position my eyes naturally gravitate towards.

Also, this is not a notation unique to the Calendar class; a subset of
classes in Java also use similar semantics for getInstance.

I haven't checked the tutorials, but it's probably discussed there as well.

Furthermore, for anyone who has read /Effective Java/ by Joshua Bloch, or the
excerpt in
<http://www.ddj.com/java/208403883>
or otherwise studied best practices for Java programming, it is well known
that factories are often preferable to constructors, in part for the reasons
Joshua mentions.

Note from the article:
# getInstance -- Returns an instance that is described by the parameters
but cannot be said to have the same value. In the case of a singleton,
getInstance takes no parameters and returns the sole instance.

# newInstance -- Like getInstance, except that newInstance guarantees
that each instance returned is distinct from all others.

See? No guarantee or convention that 'getInstance' return a singleton. Only
one "in the case of a singleton".
 
M

Mike Schilling

Lew said:
Note from the article:

See? No guarantee or convention that 'getInstance' return a
singleton. Only one "in the case of a singleton".

But this does argue that Calendar.newInstance() would be more logical,
since all Calendars returned are unique.
 
A

Arne Vajhøj

Mike said:
But this does argue that Calendar.newInstance() would be more logical,
since all Calendars returned are unique.

Yes.

But apparently SUN does not seem to think so. There are lots of
getInstance methods that return non singleton. I counted 44 classes
in the Java API.

Arne
 
A

Arne Vajhøj

Harold said:
Jean-Baptiste Nizet said:
I have the feeling that Calendar.getInstance() is not returning a
singleton, and that it is also not zeroing out newly-created instances.

Of course it's not returning a singleton, since the javadoc of the
getInstance method explicitely says that "The Calendar returned is
based on the current time [...]".

That's ambiguous. Could have meant the current time from the viewpoint
of the guy writing the documentation, so, the time the documentation got
written.

I hereby nominate that argument for the title as the most lame
argument posted to cljp in 2008.
And therein derives the problematic behavior: using Calendar in the
"natural way" as a date builder results in dates that have an
essentially-random component.

Well - everyone else seems perfectly capable of reading the docs
and use the Calendar class.

Arne
 
A

Arne Vajhøj

Harold said:
A constructor would have worked as well and potentially caused less
confusion.

I repeat: you can not instantiate an abstract class.
When the primary use of Calendar is as a date builder,

But it is not. Its primary use are to get local specific interpretation
and modifications of date objects.
though, especially useful would be if the most-precise set method 100%
determined the result. When you want the current date, you use new
Date(). When you want a specific date, you use Calendar.getInstance(),
set(), getTime(), and then if you're setting the seconds and higher
units you probably don't want essentially-arbitrary milliseconds.

No. Everyone that read the documentation will of course set those
as well (if needed in the context).

Arne
 
A

Arne Vajhøj

Harold said:
Clearly, the answer to my last question there is "yes" ...

No I am trying to bring you from non-programmer to programmer-newbee
by telling you to read the documentation instead of posting silly
bug posts to usenet.
Then by all means, go ahead and don't spend any.

The readers would prefer that you stopped posting bogus bug reports.

Please tell me where in the Java API you see that practice ?

Or any other Java API.
And this misdesign is somehow my fault? Why not have the default
calendar class be Calendar itself, with overridden behavior as appropriate?

Because it would be very bad OO design.

You do not let Calendar be GregorianCalendar and then ask all
other Calendars to overwrite most methods.

Read up on "is a" principle.
Time zone differences are clearly of the sort of behavioral variations
that are best dealt with by parametrization. Using polymorphism instead
for this is like hitting a fly with a tactical nuclear weapon.

No. Polymorphism is the correct OO solution to this. The other approach
will result in a ton of if statements and switches in the methods.

Arne
 
A

Arne Vajhøj

Harold said:
Lew said:
Of course it's not returning a singleton, since the javadoc of the
getInstance method explicitely says that "The Calendar returned is
based on the current time [...]".

Which could, perversely, be referring to the time the documentation was
being written. Stranger things have happened.

You will not get nominated twice !
Which is silly, or at least including the milliseconds is silly.

Since it stores time in milliseconds and need to convert to and
from Date with milliseconds then avoiding using milliseconds
would be difficult and inconsistent.

Arne
 
A

Arne Vajhøj

Harold said:
Yes, unless there's an obvious reason for a polymorphic implementation,
such as the method's return value has dynamically variable qualitative
behavior (not just dynamically variable in a parametrizable way).

There are.

Arab, Chines and Japanese calendars are very different from Gregorian
and Julian calendars.

Arne
 
A

Arne Vajhøj

Harold said:
In the core API, perhaps. If you use lots of libraries and other
third-party code, you'll find rather a different statistical pattern in
that vastly larger code-base.

Please provide a reference to which.

Arne
 
A

Arne Vajhøj

Harold said:
Except that by far the primary usage pattern is

getInstance()
set(...)
Date d1 = getTime();
getInstance()
set(...)
Date d2 = getTime();
etc.

I don't think so. That i a rather rare usage of Calendar.

And note that even that usage is working fine, if the programmer
reads the docs.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top