I am comparing the start Date of a treatement to its End to check if it lasts more than 6 months. If the period doesn't include the month of February all is good but if I compare the 1st of January to the 30th of June, it throws my Exception. To compare both periods I add 6 months to the start Date and compare the result to the end Date like so:
Date start = new Date(2017,1,1);
Date end = new Date(2017,6,30);
Calendar startOfTreatment = new Calendar.getInstance();
startOfTreatment.setTime(start);
Calendar endOfTreatment = new Calendar.getInstance();
endOfTreatment.setTime(end);
startOfTreatment.add(Calendar.MONTH, 6);
if (startOfTreatment.compareTo(endOfTreatment) > 0) {
throw new InfinishedTreatmentException(startOfTreatment,endOfTreatment);
}
How can I fix this?
The Date
constructors (like the one you're using: new Date(2017,1,1)
) are not only deprecated (so you should avoid them) but also misleading, because years are indexed at 1900 (so 2017 becomes 3917) and months are zero-indexed (the values are in the range zero (January) to 11 (December)). So this doesn't behave as you think:
Date start = new Date(2017, 1, 1); // February 1st 3917
Date end = new Date(2017, 6, 30); // July 30th 3917
When you add 6 months to start
, it becomes August 1st, which is after end
.
To create January 1st and June 30th you must use month - 1
and to have the year 2017 you must use 117 (2017 - 1900):
Date start = new Date(117, 0, 1); // January 1st 2017
Date end = new Date(117, 5, 30); // June 30th 2017
Even though, start
plus 6 months will be July 1st, which still is after end
(so your code will throw the exception).
The old classes (Date
, Calendar
and SimpleDateFormat
) have lots of problems and design issues, and they're being replaced by the new APIs.
In Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes.
This new API has lots of new date and time types to deal with different situations. As we're dealing only with dates (day/month/year), we can use a org.threeten.bp.LocalDate
:
LocalDate start = LocalDate.of(2017, 1, 1); // January 1st 2017
LocalDate end = LocalDate.of(2017, 6, 30); // June 30th 2017
// 6 months after start
LocalDate sixMonthsLater = start.plusMonths(6);
if (sixMonthsLater.isAfter(end)) {
// throw exception
}