Calendar.add (DAY_OF_YEAR, 1) - roll not working properly

L

Lars Uffmann

Simple code snippet:
===================
Calendar date = Calendar.getInstance();
date.set(Calendar.YEAR, 2007);
date.set(Calendar.MONTH, 4);
date.set(Calendar.DAY_OF_MONTH, 30);
date.add(Calendar.DAY_OF_YEAR, 1);
===================

After this manipulation, the date reads out as 2007-04-31 - reading it
with date.get(Calendar.YEAR), date.get(Calendar.MONTH) and
date.get(Calendar.DAY_OF_MONTH).

Same behaviour when calling add with field Calendar.DAY_OF_MONTH.

This is with Compiler compliance 1.5 and 1.6 in Sun Java.

Is anyone able to tell me how I can tell this Calendar class to do
proper date calculation? I don't want to do everything by hand,
accounting for leap years - I just want to add a certain amount of days
to a date and get the date of the result...

Thanks for any hints!

Lars
 
L

Lars Uffmann

Lars said:
Simple code snippet:
===================
Calendar date = Calendar.getInstance();
date.set(Calendar.YEAR, 2007);
date.set(Calendar.MONTH, 4);
date.set(Calendar.DAY_OF_MONTH, 30);
date.add(Calendar.DAY_OF_YEAR, 1);
===================

After this manipulation, the date reads out as 2007-04-31 - reading it
with date.get(Calendar.YEAR), date.get(Calendar.MONTH) and
date.get(Calendar.DAY_OF_MONTH).

Same behaviour when calling add with field Calendar.DAY_OF_MONTH.

Found the solution here:
http://groups.google.com/group/comp.lang.java.help/msg/e23b845398c50ffe?hl=en

Jon said:
> "month - the value used to set the MONTH time field. Month value is 0-
> based. e.g., 0 for January."

Effin inconsequent programming. Someone needs a smack there. Such
inconsistencies need to be outlined with a big fat CAUTION in the
documentation.

/out

Lars
 
L

Lew

According to Lars Uffmann:
I vote for the one who didn't read the API docs first.

Thomas said:
The need-for-smack originates quite far in the past.

And comes right back down on the OP for not doing in the first place as Arne
suggested: use the declared constant.

He ran right into the scenario that has every programming book and various IDE
options working so hard to keep programmers from using magic numbers.
 
M

markspace

Lew said:
He ran right into the scenario that has every programming book and
various IDE options working so hard to keep programmers from using magic
numbers.


To be fair to the OP, I like the way C++ solved this better. Days and
years are integral, but month is a class type. Bjarne Stroustrup
specifically mentioned confusion over starting months with 0 or 1 when
he discussed the design of that API.

I'm somewhat distressed that the newest Java date API, to be added in
Java 7, still does not use this idea.
 
L

Lars Uffmann

Arne said:
But but but.

You should use:

date.set(Calendar.MONTH, Calendar.APRIL);

Good point. I will from now on :) I had been wondrin what those enum
values were good for *g*

Kind Regards,

Lars
 
L

Lars Uffmann

Thomas said:
I think it was designed that way so that Calendar would use the same
numerical values than equivalent C programs -- the 'struct tm' type
includes the month as 0 for January and so on. The need-for-smack
originates quite far in the past.

Erm. Another good point. And it's not even been *that* long since I last
used struct tm. Shame on me *g*
 
L

Lars Uffmann

Lew said:
I vote for the one who didn't read the API docs first.

I say any programming language where you need to read the complete
documentation to do something right isn't suited for practical purposes ;)
I like to read up on the documentation of the function I'm using, and in
this case, I think the inconsistency should be marked better, for I
missed the mention of month index starting with 0. My eyes have been
getting worse over the years, but they ain't that bad ;) It just doesn't
stick out.
And comes right back down on the OP for not doing in the first place as
Arne suggested: use the declared constant.
I did my first Java project in 10 years last night and tonight - I
wanted to contribute a class to someone elses project. So I wanted
(pretty!) results fast, I didn't wanna learn all java classes in and
out. That's why I didn't understand the usage of the constants until
Arne mentioned em. And I am sure you would agree that the documentation
should *recommend* using the declared constants here.

The documentation in my Eclipse (I am assuming this is Sun
documentation) on the field MONTH reads:
==========
MONTH

public static final int MONTH

Field number for get and set indicating the month. This is a
calendar-specific value. The first month of the year in the Gregorian
and Julian calendars is JANUARY which is 0; the last depends on the
number of months in a year.

See Also:
JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER,
OCTOBER, ...
==========

How was I to know when briefly glancing at this, that just because
JANUARY is written in capitals, it is a declared constant?

Not saying that I am not to blame for this, I would have preferred to
use constants, I always do where it's possible. However:
He ran right into the scenario that has every programming book and
various IDE options working so hard to keep programmers from using magic
numbers.

I don't read programming books anymore unless I want to learn about the
basics of some programming concept (My first Basic programs, then Turbo
Pascal, then Ansi C, then Delphi, SQL, and lately threading concepts and
network programming). If I start on a new language, I get a hello world
program going from some getting started guide, and from there on I do
what I came to do, by using online references ;) It might not float
everyone's boat, but it definitely works out for me so far.

Anyways, you like the others also have a point.

Best Regards,

Lars
 
L

Lars Uffmann

markspace said:
years are integral, but month is a class type. Bjarne Stroustrup
specifically mentioned confusion over starting months with 0 or 1 when
he discussed the design of that API.

And actually I don't think I would call 1-12 "magic numbers" in the
context of months - They are at least quite established numbers...

But of course, whatever does the job and looks halfway pretty will do...
 
A

Arne Vajhøj

Lars said:
Good point. I will from now on :) I had been wondrin what those enum
values were good for *g*

Too bad that enum's were not in the language when Calendar
was created, because then the use of real enums could have
been enforced.

But we can't change the past.

Arne
 
A

Arne Vajhøj

markspace said:
To be fair to the OP, I like the way C++ solved this better. Days and
years are integral, but month is a class type. Bjarne Stroustrup
specifically mentioned confusion over starting months with 0 or 1 when
he discussed the design of that API.

Does standard C++ have a month class?

Arne
 
A

Arne Vajhøj

Lars said:
I say any programming language where you need to read the complete
documentation to do something right isn't suited for practical purposes ;)

Everybody should but very few including me actually does.

But when one have a problem, then it is time to read the fine print.
I like to read up on the documentation of the function I'm using, and in
this case, I think the inconsistency should be marked better, for I
missed the mention of month index starting with 0. My eyes have been
getting worse over the years, but they ain't that bad ;) It just doesn't
stick out.

MONTH

public static final int MONTH

Field number for get and set indicating the month. This is a
calendar-specific value. The first month of the year in the Gregorian
and Julian calendars is JANUARY which is 0; the last depends on the
number of months in a year.

I did my first Java project in 10 years last night and tonight - I
wanted to contribute a class to someone elses project. So I wanted
(pretty!) results fast, I didn't wanna learn all java classes in and
out. That's why I didn't understand the usage of the constants until
Arne mentioned em. And I am sure you would agree that the documentation
should *recommend* using the declared constants here.

The example in the top of the class documentation do use the
constants.

But Calendar is a bit tricky in general. It is one of those
classes where it pay off to read the docs in its entirety.
The documentation in my Eclipse (I am assuming this is Sun
documentation) on the field MONTH reads:
==========
MONTH

public static final int MONTH

Field number for get and set indicating the month. This is a
calendar-specific value. The first month of the year in the Gregorian
and Julian calendars is JANUARY which is 0; the last depends on the
number of months in a year.

See Also:
JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER,
OCTOBER, ...
==========

How was I to know when briefly glancing at this, that just because
JANUARY is written in capitals, it is a declared constant?

You could have noticed that Eclipse for Calendar. suggested
the month names.

But you are not the first to be confused over some of the more
tricky points in the Calendar class.

You had a problem, you asked a question, you got an answer
and you became a wiser person. Happy ending. End of story.

Arne
 
L

Lew

For starters, it's been the Java coding convention for over a decade that
variables spelled in all caps represent constants.
But you are not the first to be confused over some of the more
tricky points in the Calendar class.

You had a problem, you asked a question, you got an answer
and you became a wiser person. Happy ending. End of story.

If you think starting a month with 0 is tricky, check out what
Calendar#clear(int) actually does, versus what most people would expect it to do.
 
L

Lew

Lars said:
That is where I looked (among others). If you don't know 100% what
you're searching for - and I didn't - then you will not find the
solution there - like I didn't.

I suggest reading the Javadocs for what is in there, not for what you expect
to be in there.

Others have learned of Calendar.MONTH and its zero-based nature, and of other
java.util.Calendar quirks, that way.
 
A

Arved Sandstrom

Lew said:
I suggest reading the Javadocs for what is in there, not for what you
expect to be in there.

Others have learned of Calendar.MONTH and its zero-based nature, and of
other java.util.Calendar quirks, that way.
What they could have done for 1.5, and certainly no later than 1.6, is
deprecate every Calendar setter method that uses ints, and introduce
parallel versions that use real enums. That way new code could use
something that isn't a bandaid, and people unfamiliar with the API would
have a stronger indication (at least in an IDE) of preferred methods.

But I figure mundane maintenance-type coding improvements like this take
second stage to gee-whiz APIs and trying to decide whether to include
closures.

AHS
 
A

Arne Vajhøj

Arved said:
What they could have done for 1.5, and certainly no later than 1.6, is
deprecate every Calendar setter method that uses ints, and introduce
parallel versions that use real enums. That way new code could use
something that isn't a bandaid, and people unfamiliar with the API would
have a stronger indication (at least in an IDE) of preferred methods.

Actually a good idea.

And it is not as if there is not already deprecated stuff in
the date time stuff.

Arne
 
E

Eric Sosman

Arne said:
Too bad that enum's were not in the language when Calendar
was created, because then the use of real enums could have
been enforced.

The API would have been rather different. Instead of
set(int,int) there would have been setMonth(Calendar.Month),
setDayOfYear(Calendar.DayOfYear), and so on. Or perhaps
there would have been one comprehensive enum with members
for everything, so you could do set(Calendar.APRIL) or
set(Calendar.DayOfYear42), and the set() method would figure
out from the enum value which field was being altered.

Not sure what the roll() methods might have looked like.
But we can't change the past.

Nor should we moan about it *too* loudly. However bad
it may seem, it might have been worse ...

Still, it must be said that Calendar.JANUARY == 0 is
just plain stupid. (Math.atan2() is also stupid, although
perhaps just a trifle less so.)
 
M

markspace

Arne said:
Does standard C++ have a month class?

Hmm, I may be mistaken. Stroustrup talks about a Date class in The C++
Programming Language, but it isn't the standard one. He defines a Month
class type like this:

class Date {
public:
enum Month { jan=1, feb, mar, apr, may, jun, jul, aug, sep,
oct, nov, dec };

...
}

So it's not really had to do.

In Java it would have been easy to make a marker interface:

interface Month {}

if nothing else. Although I think extending Iterable would also be useful.
 

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,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top