tl;dr
Just use LocalDate
and forget all about Calendar
(troublesome legacy class).
LocalDate.parse( "2000-01-31" ).plusMonths( 1 ).toString()
2000-02-29
Method 1
Method 1: using LocalDate plusMonths():
The LocalDate
class documentation explains that it first adds the month-number, and leaves the day-of-month alone. If that day-of-month is not valid in that month (29, 30, or 31), then it adjusts backwards to the last valid day-of-month.
This method adds the specified amount to the months field in three steps:
- Add the input months to the month-of-year field
- Check if the resulting date would be invalid
- Adjust the day-of-month to the last valid day if necessary
For example, 2007-03-31 plus one month would result in the invalid date 2007-04-31. Instead of returning an invalid result, the last valid day of the month, 2007-04-30, is selected instead.
Seems like a smart approach to me.
In your example, LocalDate
first changed 2000-01-31
to 2000-02-31
. There is no 31st in February, so it walked back to 30. But no Feb 30th either. So it walked further back to 29. Bingo! In that year in that month, there is indeed a 29th day because the year 2000 is a Leap Year. So the answer is 2000-02-29
.
LocalDate.parse( "2000-01-31" )
.plusMonths( 1 )
.toString()
2000-02-29
Method 2
Method 2: using Calendar:
Don’t bother.
This terribly troublesome old Calendar
class is now legacy, supplanted entirely by the java.time classes as defined in JSR 310. Specifically, replaced by ZonedDateTime
.
Never touch Calendar
class again. Save yourself some pain and headache, and pretend this class never existed.
Furthermore, Calendar
was a date-with-time value. Not appropriate for a date-only value like yours in the Question.
Convert legacy <–> modern
If you must inter-operate with code not yet updated to java.time, convert between the legacy classes and java.time by calling new conversion methods added to the old classes. For more info, see the Question, Convert java.util.Date to what “java.time” type?
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.