I'm looking for a solution to calculate the months between two date. I think joda or java8 time can do it. But when I compare them I found something really weird.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import org.joda.time.Months;
public class DateMain {
public static void main(String[] args) throws ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date d1 = simpleDateFormat.parse("2017-01-28 00:00:00.000");
Date d2 = simpleDateFormat.parse("2017-02-28 00:00:00.000");
System.out.println("Test Cast 1");
System.out.println("joda time api result: " + monthsBetweenJoda(d1, d2) + " month");
System.out.println("java8 time api result: " + monthsBetweenJava8(d1, d2) + " month");
Date dd1 = simpleDateFormat.parse("2017-01-29 00:00:00.000");
Date dd2 = simpleDateFormat.parse("2017-02-28 00:00:00.000");
System.out.println("Test Cast 2");
System.out.println("joda time api result: " + monthsBetweenJoda(dd1, dd2) + " month");
System.out.println("java8 time api result: " + monthsBetweenJava8(dd1, dd2) + " month");
}
public static int monthsBetweenJoda(Date fromDate, Date toDate) {
if (fromDate == null || toDate == null) {
throw new IllegalArgumentException();
}
org.joda.time.LocalDateTime fromLocalDateTime = org.joda.time.LocalDateTime
.fromDateFields(fromDate);
org.joda.time.LocalDateTime toLocalDateTime = org.joda.time.LocalDateTime
.fromDateFields(toDate);
Months months = Months.monthsBetween(fromLocalDateTime, toLocalDateTime);
return months.getMonths();
}
public static long monthsBetweenJava8(Date fromDate, Date toDate) {
if (fromDate == null || toDate == null) {
throw new IllegalArgumentException();
}
LocalDateTime ldt1 = fromDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime ldt2 = toDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
return ChronoUnit.MONTHS.between(ldt1, ldt2);
}
}
the output is below:
Test Cast 1
joda time api result: 1 month
java8 time api result: 1 month
Test Cast 2
joda time api result: 1 month
java8 time api result: 0 month
I feel very confused with the test case 2, and which one is reasonable?
Sorry, it's my first question here. Completed code attached.
fromDate.plusMonths(x) <= toDate
, which is reasonable when adding 1 month to January 29th still gives February 28th. Basically calendar arithmetic is weird. – Liquorjava.sql.Date
orjava.util.Date
? Please document this fact, and show how you generate yourDate
objects being passed as the pair of arguments. And show how your generated your output strings. Your output does not match that of thetoString
method on eitherjava.sql.Date
orjava.util.Date
. Provide us with a MCVE. Your code as shown is not complete, so we cannot replicate your scenario. – SiliciumLocalDate.of(2017, 1, 29).plusMonths(1L)
results injava.time.LocalDate = 2017-02-28
but getting the month interval between them results in 0. Could be a bug – CorruptionDAYS
,MONTHS
orYEARS
or almost all of them actually). – Chironend.time.isBefore(time)
- maybe this is the case in your test (although it doesn't look like it from your output)? – Chiron