Possible bug in Calendar

H

Harold Yarmouth

Calendar calendar = Calendar.getInstance();
calendar.set(2003,9,10,13,8,42);
Date date = calendar.getTime();



When the above code is run twice with some time passing in between, the
resulting Date objects compare unequal!


The getTime methods returned the following values from two runs of the
above code:

1065805722140
1065805722828

As you can see, the last three digits appear to vary randomly.


Clearly, this should not be the case. Calling calendar.set with the
maximal precision (six values) should completely determine the resulting
Date object. It looks like it uses the last three digits of the current
millisecond value of the system clock to "fill in the blanks" when it
really ought to use zeros.
 
M

Mark Thornton

Harold said:
Calendar calendar = Calendar.getInstance();
calendar.set(2003,9,10,13,8,42);
Date date = calendar.getTime();



When the above code is run twice with some time passing in between, the
resulting Date objects compare unequal!


The getTime methods returned the following values from two runs of the
above code:

1065805722140
1065805722828

As you can see, the last three digits appear to vary randomly.


Clearly, this should not be the case. Calling calendar.set with the
maximal precision (six values) should completely determine the resulting
Date object. It looks like it uses the last three digits of the current
millisecond value of the system clock to "fill in the blanks" when it
really ought to use zeros.

The JDK documentation says this:

"Sets the values for the fields YEAR, MONTH, DAY_OF_MONTH, HOUR, MINUTE,
and SECOND. Previous values of other fields are retained. If this is not
desired, call clear() first."

So the behaviour you have noted is by design.

Mark Thornton
 
S

Stanimir Stamenkov

Mon, 27 Oct 2008 16:42:21 -0400, /Harold Yarmouth/:
Calendar calendar = Calendar.getInstance();
calendar.set(2003,9,10,13,8,42);
Date date = calendar.getTime();

When the above code is run twice with some time passing in between, the
resulting Date objects compare unequal!

I think it is o.k. as you're not setting the field for the
milliseconds which is left at what it got set during the time of the
calendar construction. The documentation for the Calendar.set(int,
int, int, int, int, int) method
Sets the values for the fields YEAR, MONTH, DAY_OF_MONTH, HOUR,
MINUTE, and SECOND. Previous values of other fields are retained.
If this is not desired, call clear() first.

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

Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(2003,9,10,13,8,42);
Date date = calendar.getTime();
System.out.println(date.getTime());

calendar = Calendar.getInstance();
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(2003,9,10,13,8,42);
Date date2 = calendar.getTime();
System.out.println(date2.getTime());

System.out.println(date.equals(date2));
 
H

Harold Yarmouth

Mark said:
The JDK documentation says this:

"Sets the values for the fields YEAR, MONTH, DAY_OF_MONTH, HOUR, MINUTE,
and SECOND. Previous values of other fields are retained. If this is not
desired, call clear() first."

So the behaviour you have noted is by design.

Nope.

If Calendar lacks a hidden, seventh milliseconds field, the six-argument
set method sets all of the fields and retains no old values, contrary to
what's observed.

If, on the other hand, Calendar has a hidden, seventh milliseconds
field, since this value is not being set by the second call to set, it
should retain the previous value, i.e. the value it had when the first
Date object was constructed. The second Date value should therefore have
the same milliseconds last-three-digits as the first Date value, again
contrary to what's observed.

So, this still looks like a bug to me.
 
H

Harold Yarmouth

Stanimir said:
Mon, 27 Oct 2008 16:42:21 -0400, /Harold Yarmouth/:


I think it is o.k. as you're not setting the field for the milliseconds

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?)
 
S

Stanimir Stamenkov

Mon, 27 Oct 2008 17:26:40 -0400, /Harold Yarmouth/:
If there is such a field, it should either be zero or the
previously-used value, not something random.

Nope, it is not random. Calendar.getInstance()
... The Calendar returned is based on the current time...

So you're ending up with a calendar with milliseconds set based on
the current time.

Mon, 27 Oct 2008 17:26:40 -0400, /Harold Yarmouth/:
I have the feeling that Calendar.getInstance() is not returning a
singleton, and that it is also not zeroing out newly-created instances.

It is not returning a singleton for sure, why should it? There's no
mention for a singleton in the documentation nor it sounds logical
to be the case as you're probably realizing next.
 
M

Mike Schilling

Harold said:
Yep.


If, on the other hand, Calendar has a hidden, seventh milliseconds
field, since this value is not being set by the second call to set, it
should retain the previous value, i.e. the value it had when the first
Date object was constructed.

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

Mark Thornton

Stanimir said:
It is not returning a singleton for sure, why should it? There's no
mention for a singleton in the documentation nor it sounds logical to be
the case as you're probably realizing next.

Given that Calendar is not thread safe and that users might wish to use
Calendar objects concurrently in different threads it would be broken if
it were a singleton.

Mark Thornton
 
A

Arne Vajhøj

Harold said:
Nope.

If Calendar lacks a hidden, seventh milliseconds field, the six-argument
set method sets all of the fields and retains no old values, contrary to
what's observed.

If, on the other hand, Calendar has a hidden, seventh milliseconds
field, since this value is not being set by the second call to set, it
should retain the previous value, i.e. the value it had when the first
Date object was constructed. The second Date value should therefore have
the same milliseconds last-three-digits as the first Date value, again
contrary to what's observed.

Why should a second object inherit a value from the first object ??

Arne
 
W

Wojtek

Harold Yarmouth wrote :
Calendar calendar = Calendar.getInstance();
calendar.set(2003,9,10,13,8,42);
Date date = calendar.getTime();



When the above code is run twice with some time passing in between, the
resulting Date objects compare unequal!


The getTime methods returned the following values from two runs of the above
code:

1065805722140
1065805722828

As you can see, the last three digits appear to vary randomly.


Clearly, this should not be the case. Calling calendar.set with the maximal
precision (six values) should completely determine the resulting Date object.
It looks like it uses the last three digits of the current millisecond value
of the system clock to "fill in the blanks" when it really ought to use
zeros.

calendar.getTime() always returns the current time regardless of the
value wihin the Calendar object.

Yes, this is a pain.
 
A

Arne Vajhøj

Harold said:
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.

Have you read the documentation ?

http://java.sun.com/javase/6/docs/api/java/util/Calendar.html

public static Calendar getInstance()

Gets a calendar using the default time zone and locale. The
Calendar returned is based on the current time in the default time zone
with the default locale.

The keywords are "current time".

And even though a singleton implies a getInstance method, then a
getInstance method does not imply a singleton.

Arne
 
A

Arne Vajhøj

Wojtek said:
calendar.getTime() always returns the current time regardless of the
value wihin the Calendar object.

It does not. It returns value within the Calendar object.

Arne
 
W

Wojtek

Arne Vajhøj wrote :
It does not. It returns value within the Calendar object.

Arne

Sigh.

My opinion was based on a series of test I did when I was using an
earlier Java version. I could never get the Calendar object to return
the date within it. It always seemed to return the current time rather
than the set time.

And now a quick test shows it returns the Calendar time.

I remember this specifically as I was getting quite frustrated with it.
 
M

Mike Schilling

Wojtek said:
Arne Vajhøj wrote :

Sigh.

My opinion was based on a series of test I did when I was using an
earlier Java version. I could never get the Calendar object to
return
the date within it. It always seemed to return the current time
rather
than the set time.

And now a quick test shows it returns the Calendar time.

I remember this specifically as I was getting quite frustrated with
it.

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

Harold Yarmouth

Mike said:

Nope. Or, at least, not what was implied elsewhere.
Calendar.getInstance() returns a Calendar representing "now", so each time
it's called you will see a different milliseconds value.

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

It leads one to expect that any milliseconds value wouldn't be changing.
 
H

Harold Yarmouth

Arne said:
Why should a second object inherit a value from the first object ??

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

Harold Yarmouth

Stanimir said:
So you're ending up with a calendar with milliseconds set based on the
current time.

Why is the "most specific" set method missing a field for this? And
surely it should set that field to zero, since there's no reason to set
everything else but have those last three digits vary randomly.

It is not returning a singleton for sure, why should it?

It shouldn't, but having no public constructor and having instead a
no-arguments "getInstance" method suggests it, or a similar thing such
as fetching a per-thread instance.
 
H

Harold Yarmouth

Arne said:
Have you read the documentation ?

Have you forgotten yet again to check your confrontational attitude at
the door?
And even though a singleton implies a getInstance method, then a
getInstance method does not imply a singleton.

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.

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

Stanimir Stamenkov

Tue, 28 Oct 2008 02:42:21 -0400, /Harold Yarmouth/:
Why is the "most specific" set method missing a field for this? And
surely it should set that field to zero, since there's no reason to set
everything else but have those last three digits vary randomly.

Whether the "most specific" method should automatically set the
milliseconds to 0 is subjective. Probably many would come up with
cases they would not want that method doing so. At least the
present behavior is ever since the Calendar has been introduced
(Java 1.1), thus changing it would break existing applications. You
can only hope an even more specific method will be introduced in
future Java versions, but I don't think it worths it.
It shouldn't, but having no public constructor and having instead a
no-arguments "getInstance" method suggests it, or a similar thing such
as fetching a per-thread instance.

You've already been given the most exact answer by Mark Space: "It's
just a plain old factory method."
 

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,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top