I should like to contribute the modern answer.
ZonedDateTime endOfFebruary2010 = LocalDate.of(2010, Month.MARCH, 1)
.atStartOfDay(ZoneId.systemDefault())
.minusNanos(1);
System.out.println(endOfFebruary2010);
Running in my time zone this prints:
2010-02-28T23:59:59.999999999+01:00[Europe/Copenhagen]
The printout is the same no matter the time of year and month you run it. The dependency on time zone may be unfortunate, but can be mended by specifying which time zone you want, for example ZoneId.of("Asia/Oral")
. I am using and recommending java.time
, the modern Java date and time API.
If you indispensably need an old-fashioned java.util.Date
object (and only in this case), convert:
Date oldFashionedDate = Date.from(endOfFebruary2010.toInstant());
System.out.println(oldFashionedDate);
Sun Feb 28 23:59:59 CET 2010
If you only needed a count of days in some month (this was asked in a duplicate question):
YearMonth ym = YearMonth.of(2011, Month.FEBRUARY);
int numDays = ym.lengthOfMonth();
System.out.println(numDays);
28
As I understand, your real question was:
…I was wondering is this really was the wanted behaviour. Any thoughts
?
I strongly believe that it is wanted behaviour that the no-arg GregorianCalendar
constructor returns the current day and the current time of day. And that Calender.set()
only sets the fields that you explicitly set and tries to keep other fields unchanged. And that February 31, 2010 overflows into March without any sign of error because there were only 28 days in the month. The combination of these design decisions leads me to the inevitable conclusion: the behaviour you observed is by design.
If you think this is a poor design, we are many that agree with you. This was also why the replacement for Calendar
and GregorianCalendar
came out with java.time
four years ago now. You will never need to use Calendar
again.
Reservation: Our tool is still dependent on Java 1.7
java.time
works nicely on Java 7. It just requires at least Java 6.
- In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
- In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
- On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from
org.threeten.bp
with subpackages.
Links
java.util.Calendar
is many things, but not a normal API. See the first comment here for how JodaTime does it: blog.smart-java.nl/blog/index.php/2010/01/20/… – Nipping