Java-比较两个ZonedDateTime时的结果不符合预期

Hai*_*ang 3 java zoneddatetime

我有这个代码:

ZonedDateTime t1 = ZonedDateTime.parse("2018-04-06T10:01:00.000+03:00");
ZonedDateTime t2 = ZonedDateTime.parse("2018-04-06T10:01:00.000-03:00");
System.out.println(t1.compareTo(t2));
Run Code Online (Sandbox Code Playgroud)

结果是-1。我想它将把t1和t2都转换为相同的时区,然后进行比较。例如,在第一种情况下,它将(可能)进行比较

t1 = 2018-04-06T07:01:00.000+00:00 to t2 = 2018-04-06T13:01:00.000+00:00
Run Code Online (Sandbox Code Playgroud)

如我所料,此案例返回1

ZonedDateTime t1 = ZonedDateTime.parse("2018-04-06T17:01:00.000+03:00");
ZonedDateTime t2 = ZonedDateTime.parse("2018-04-06T10:01:00.000-03:00");
System.out.println(t1.compareTo(t2));
Run Code Online (Sandbox Code Playgroud)

但是这个(*)不返回0,而是返回1:

ZonedDateTime t1 = ZonedDateTime.parse("2018-04-06T16:01:00.000+03:00");
ZonedDateTime t2 = ZonedDateTime.parse("2018-04-06T10:01:00.000-03:00");
System.out.println(t1.compareTo(t2));
Run Code Online (Sandbox Code Playgroud)

我什至尝试truncatedTo(ChronoUnit.MINUTES)在解析字符串后使用以忽略秒部分,但没有任何变化。

最有趣的是,如果我将t1 / t2减少/增加一秒,结果将为-1

例如:

ZonedDateTime t1 = ZonedDateTime.parse("2018-04-06T16:01:00.000+03:00");
ZonedDateTime t2 = ZonedDateTime.parse("2018-04-06T10:01:01.000-03:00");
System.out.println(t1.compareTo(t2));
Run Code Online (Sandbox Code Playgroud)

在我的用例中,所有用户输入时间将以上述格式保存在许多ZoneOffset中,并且我有一些查询需要将其与服务器时间进行比较(忽略时间的秒数)。在上述情况(*)下,如何使t1等于t2?

Ole*_*.V. 11

比较首先基于即时,然后基于本地日期时间,然后基于区域ID,再基于时间顺序。定义为“等于” Comparable

compareTo在超类中实现,超ChronoZonedDateTime类是我们通常不关心的类,但是我们需要在其中查找一些方法的文档。所以上面的报价来自那里。

因此,在两个ZonedDateTime对象都表示同一时刻的情况下,t1本地时间为16:01,大于本地时间t210:01。因此1是正确的预期结果。另一方面,如果时刻相隔仅一秒(或仅1纳秒),则优先,而本地时间不进行比较。

我相信这可以解释您观察到的行为。

该引号还暗示了为什么必须这样做:假设比较ZonedDateTime具有相同即时但时区不同的两个对象返回0。这样,比较将不再等于equals。这被认为是一个非常不错的属性(尽管不是必需的)。

一类的自然顺序C被说成是与equals一致当且仅当e1.compareTo(e2) == 0具有相同的布尔值的e1.equals(e2)每一个e1e2阶级的C

(引自Comparable接口文档

因此,如果您只想比较瞬间,则有两种选择,具体取决于您希望哪种类型的结果:

  1. 使用isBeforeisAfterisEqual

    ZonedDateTime t1 = ZonedDateTime.parse("2018-04-06T16:01:00.000+03:00");
    ZonedDateTime t2 = ZonedDateTime.parse("2018-04-06T10:01:00.000-03:00");
    System.out.println(t1.isBefore(t2));
    System.out.println(t1.isAfter(t2));
    System.out.println(t1.isEqual(t2));
    
    Run Code Online (Sandbox Code Playgroud)

    输出:

false
false
true
Run Code Online (Sandbox Code Playgroud)
  1. 使用Yoav Gur的答案:明确比较瞬间。


Yoa*_*Gur 5

使用toInstant(),然后比较结果,如下所示:

    ZonedDateTime t1 = ZonedDateTime.parse("2018-04-06T16:01:00.000+03:00");
    ZonedDateTime t2 = ZonedDateTime.parse("2018-04-06T10:01:00.000-03:00");
    System.out.println(t1.toInstant().compareTo(t2.toInstant())); 
Run Code Online (Sandbox Code Playgroud)