Joda时间和Java8时间差
我正在寻找一个解决方案来计算两个日期之间的月份。我认为joda或java8 time可以做到这一点。但当我比较它们时,我发现了一些非常奇怪的东西Joda时间和Java8时间差,java,java-8,jodatime,date-difference,jsr310,Java,Java 8,Jodatime,Date Difference,Jsr310,我正在寻找一个解决方案来计算两个日期之间的月份。我认为joda或java8 time可以做到这一点。但当我比较它们时,我发现了一些非常奇怪的东西 import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.ut
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);
}
}
结果如下:
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
我对测试用例2感到非常困惑,哪一个是合理的
对不起,这是我的第一个问题。已完成的代码附加。Joda Time和Java 8
Java.Time.
有不同的算法来确定两个时间之间的月数
java.time.*
只声明一个月的某一天(或下一个月)过了一个月。从2017-01-29
到2017-02-28
很明显,月份的第二天(28)比第一天(29)短,因此一个月尚未完成
Joda Time声明一个月已经过去,因为向2017-01-29
添加一个月将产生2017-02-28
两者都是合理的算法,但我相信
java.time.*
算法更符合人们的期望(这就是为什么我在编写java.time.*
时选择了不同的算法)。Joda在我看来是错的。它的文档显示了整月数,但您的测试与此不一致。@JoeC:我怀疑它取的是最大的数,例如fromDate.plusMonths(x)您使用的是java.sql.Date
还是java.util.Date
?请记录这一事实,并说明如何生成作为参数对传递的Date
对象。并显示如何生成输出字符串。您的输出与java.sql.Date
或java.util.Date
上的toString
方法的输出不匹配。为我们提供一个新的解决方案。所示代码不完整,因此我们无法复制您的scenario.Hm。没有明确提到该方法如何处理可变长度的单位(如天
、月
或年
或几乎所有这些单位)。我的实现最终调用的是(非基于时间的单位)反过来调用的单位。然而,如果end.time.isBefore(time)
,它可能会将结束日期缩短一天-也许在您的测试中就是这样(尽管从您的输出来看它与此不同)?让我不安的是,这是Java8时间中的决定。因此,每次我们有一个2月28日,从1月29日到3月1日只有一个月的时间——对我来说似乎是错误的,特别是因为在2月28日将一个月添加到1月29日的结果。我该如何处理这件事,这样我就可以告诉自己“让它去吧”?