java - Joda时间和Java8时差

标签 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.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-292017-02-28 很明显,每月的第二天 (28) 小于第一天 (29),因此一个月还没有结束。

Joda-Time 声明一个月已经过去,因为将 1 个月添加到 2017-01-29 将产生 2017-02-28

两者都是合理的算法,但我相信 java.time.* 算法更符合人们的期望(这就是为什么我在编写 java.时间。*)。

关于java - Joda时间和Java8时差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46232482/

相关文章:

java - 有没有更好的方法将包含 UTF-8 字节码的 String 转换为 UTF-8 字符串?

java - 如何在java中对包含两个以上异构对象的List进行排序?

Java 8 可选流 get() - 在方法内部还是外部?

java - 通过函数/供应商访问 lambda 参数

java - Joda-Time——从另一个句点中删除一个句点

java - 解析 Joda 时间部分

java - 通过 USB 连接三星 e250 和计算机

java - Gson - 无法从静态上下文引用非静态变量

java - 为什么@Repeatable注解不能继承接口(interface)

java - 如果电话时区已更改,则 SimpleDateFormat setTimeZone 不起作用