Possible bug in Calendar

M

Mike Schilling

Harold said:
Nope. Or, at least, not what was implied elsewhere.


Well, there's the problem, right there. Most other places, having a
no-arguments "getInstance" method instead of a constructor means
some
sort of singleton. (Although I can see why this wouldn't work for
Calendar, which is mutable; it wouldn't be thread-safe.)

Or useful even within one thread:

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

newInstance() would be a better name.
 
J

Joshua Cranmer

Harold said:
It usually implies something of the sort, if it takes no arguments and
there's no public constructor. In this case, a per-thread instance might
have made sense. With the semantics of producing a new instance every
time, there's no apparent reason not to have a public constructor.

FWIW, many people would consider the Calendar API to be a shining
example of poor design.
To be more exact, use of a factory method instead of any public
constructors usually means one of two things: the exact type is dynamic
(and why would it be in this case?) or it may return a pre-existing
instance.

.... You just answered your own question. Then you said "Why would it be
in this case?"

From the documentation:
Like other locale-sensitive classes, Calendar provides a class method,
getInstance, for getting a generally useful object of this type.
Calendar's getInstance method returns a Calendar object whose calendar
fields have been initialized with the current date and time.

Note that there are different Calendars: there's the Gregorian calendar,
Buddhist calendar, and Julian calendar in what I could find of my OpenJDK.
 
R

Roedy Green

Calendar.getInstance() returns a Calendar representing "now", so each time
it's called you will see a different milliseconds value. To get the
behavior you're looking for, you need

Calendar calendar = Calendar.getInstance();
calendar.set(2003,9,10,13,8,42);
calendar.set(Calendar.MILLISECOND, 0);

Yes, this is obnoxious.

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

I usually call these "gotchas", but I think this sort of thing
deserves another name, something closer to "design flaw".
 
L

Lew

Stanimir said:
So you may either call clear() or set(MILLISECOND, 0):

Problem with clear() is that it leaves the calendar in an inconsistent state.
It "ets the given calendar field value and the time value (millisecond
offset from the Epoch) of this Calendar undefined. This means that
isSet(field) will return false, and the date and time calculations will treat
the field as if it had never been set."

This is a surprise if you expect the method to zero the field.
 
J

Jean-Baptiste Nizet

If there is such a field, it should either be zero or the
previously-used value, not something random.

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 [...]".
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.

JB.
 
L

Lew

Jean-Baptiste Nizet 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 [...]".
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.

Of course Calendar doesn't zero out newly-created instances, since it's
defined to assign the current time to newly-created instances.
 
O

ojacobson

If there is such a field, it should either be zero or the
previously-used value, not something random.

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

(And since Calendar is really a mutable Date mainly used to get
immutable Dates, perhaps they should have called it DateBuilder?)

#11943: Ah yes, and you are the first person to have noticed this bug
since 1998. Sure.
 
W

Wojtek

Mike Schilling wrote :
A newly created Calendar contains the current time. Perhaps your test was
inadvertently creating a new Calendar object and doing the getTime() on that?

No, I wanted to use the methods in the Date object that the Calendar
object did not have. So the solution was to get a Date object then use
those methods. Seemed obvious to me, yet it did not work.

This was several years ago, so I cannot remember the details, just the
frustration. I think it had something to do with JDBC and a timestamp
column.

BTW, why does a ResultSet not return a Calendar object rather than a
thinly disguised Date object (TimeStamp)? Most of the methods in a Date
object are deprecated. I would be happy to supply a Timezone...
 
M

Mark Thornton

Harold said:
That depends on there being a second object. Ordinarily, having no
constructor but a no-arguments "getInstance" method signals a singleton,
or something with singleton-like behavior (such as one instance per
calling thread).

No it merely indicates a factory pattern. There are numerous cases where
the result is not a singleton.
 
L

Lew

Wojtek said:
No, I wanted to use the methods in the Date object that the Calendar
object did not have. So the solution was to get a Date object then use
those methods. Seemed obvious to me, yet it did not work.

Non-deprecated methods in java.util.Date and their Calendar
counterparts:
Date: Calendar:
after() after()
before() before()
clone() clone()
compareTo() compareTo()
equals() equals()
getTime() getTimeInMillis()
hashCode() hashCode()
setTime() setTimeInMillis()
toString() toString()
 
A

Arne Vajhøj

Harold said:
Nope. Or, at least, not what was implied elsewhere.


Well, there's the problem, right there. Most other places, having a
no-arguments "getInstance" method instead of a constructor means some
sort of singleton.

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

Arne
 
A

Arne Vajhøj

Harold said:
That depends on there being a second object. Ordinarily, having no
constructor but a no-arguments "getInstance" method signals a singleton,
or something with singleton-like behavior (such as one instance per
calling thread).

No. That is something you have misunderstood.

I just grepped the Java API docs. There are nine no-arg getInstance
methods. Of those zero are singletons.

Arne
 
A

Arne Vajhøj

Harold said:
Have you forgotten yet again to check your confrontational attitude at
the door?

Considering that the documentation clearly states that it returns
a Calendar instance based on time, then it seems as a very relevant
question.

I see no reason why people should spend time on your perceived
bugs, if you are not even willing to read the documentation
for the classes/methods you think contain a bug.
It usually implies something of the sort, if it takes no arguments and
there's no public constructor.

No. It never means that in the Java API. And I can not think of any
code where you could conclude that.
. With the semantics of producing a new instance every
time, there's no apparent reason not to have a public constructor.

Again: read the documentation.

Calendar is an abstract class. You can not instantiate it.
To be more exact, use of a factory method instead of any public
constructors usually means one of two things: the exact type is dynamic
(and why would it be in this case?) or it may return a pre-existing
instance.
>
> Since there's no obvious reason for polymorphism here (any
> locale/timezone stuff can be done by way of private fields and
> delegation, with generic behavior) that leaves pre-existing instances.
> Or perversity, I suppose.

Wrong.

In this case it can return different types of calendars.

Yes - different parts of the world use different calendars.

Arne
 
A

Arne Vajhøj

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

Have you read the documentation ?

Quite obviously not. Not with comprehension, anyhow.

My impression is that he is not looking for help or even
looking for information, but just braying about conclusions
already drawn and unshakeable. There's not much point in
trying to change the mind of someone who's already armored
himself against reality. "The man convinced against his will
is of the same opinion still."

Probably true.

Arne
 
A

Arne Vajhøj

Wojtek said:
BTW, why does a ResultSet not return a Calendar object rather than a
thinly disguised Date object (TimeStamp)? Most of the methods in a Date
object are deprecated. I would be happy to supply a Timezone...

In most databases time is just stored as "number of X since Y", so that
Date is a better fit than Calendar.

Arne
 
H

Harold Yarmouth

Stanimir said:
Whether the "most specific" method should automatically set the
milliseconds to 0 is subjective.

Perhaps so, but really, it *smells* when one does the
apparently-designers-intended thing to get a Date object accurate to the
second, does so again with the same values, gets Date objects that look
equal when displayed as date strings, and finds that they compare
unequal with .equals.

If this isn't quite a bug, it is a definite wart.
You've already been given the most exact answer by Mark Space

An incomplete answer is the "most exact" one? That does not bode well.
 
H

Harold Yarmouth

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

Yes; I'm one of them.
> Like other locale-sensitive classes, Calendar provides a class method,
> getInstance, for getting a generally useful object of this type.

A constructor would have worked as well and potentially caused less
confusion. When the primary use of Calendar is as a date builder,
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. Having
those plays hell with code that constructs accurate-to-the-second dates
and then compares them.
 
H

Harold Yarmouth

Arne said:
Considering that the documentation clearly states ...

Clearly, the answer to my last question there is "yes" ...
I see no reason why people should spend time on your ...

Then by all means, go ahead and don't spend any. I'd be glad to be
spared unpleasant and confrontational posts like yours seem prone to being.
the documentation for the classes/methods you think contain a bug.

If the behavior is (implicitly) documented, but undesirable, then
perhaps it's not technically a bug anymore, but it is still a flaw.
Yes.


Again: read the documentation.

Calendar is an abstract class. You can not instantiate it.

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

Does anyone ever use any other calendar objects, save by specifying a
locale/timezone?

No, not wrong.
In this case it can return different types of calendars.

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

Harold Yarmouth

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

Have you read the documentation ?

Quite obviously not.

[rest snipped]

If you have nothing Java-related to say, only personal attacks against a
fellow poster, might I suggest that instead you not say anything at all?
 
H

Harold Yarmouth

Arne said:
Eric said:
Arne said:
Harold Yarmouth wrote:
[...]
I have the feeling that Calendar.getInstance() is not returning a
singleton, and that it is also not zeroing out newly-created instances.

Have you read the documentation ?

Quite obviously not.

[rest snipped]
Probably true.

If you two have nothing Java-related to say, only personal attacks
against a fellow poster, then perhaps you should refrain from saying
anything at all?
 

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,020
Latest member
GenesisGai

Latest Threads

Top