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

时间:2018-04-06 05:55:27

标签: 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));

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

t1 = 2018-04-06T07:01:00.000+00:00 to t2 = 2018-04-06T13:01:00.000+00:00

此案例按预期返回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));

但是这一个(*)不返回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));

我甚至尝试在解析字符串之后使用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));

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

2 个答案:

答案 0 :(得分:7)

  

比较首先基于瞬间,然后是本地   日期时间,然后是区域ID,然后是年表。它是   "与Comparable定义的等号"一致。

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

因此,在两个ZonedDateTime个对象表示同一时刻的情况下,t1的本地时间是16:01,大于t2的10:01。所以1是正确的和预期的结果。另一方面,如果瞬间仅相隔一秒 - 或仅为1纳秒 - 则优先,并且不比较当地时间。

我相信这解释了你观察到的行为。

该引用进一步暗示了为什么必须如此:假设比较两个具有相同时刻但不同时区的ZonedDateTime个对象返回0.然后比较将不再与equals一致。这被认为是一个非常好的属性(虽然不是必需的)。

  

C的自然顺序被认为与一致   等于当且仅当e1.compareTo(e2) == 0具有相同的布尔值时   类e1.equals(e2)的每个e1e2的值为C

(引自Comparable interface documentation

因此,如果您只想比较时刻,有两种选择,具体取决于您对结果的偏好类型:

  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));
    

    输出:

  2. false
    false
    true
    
    1. 使用the answer by Yoav Gur:明确比较时刻。

答案 1 :(得分:2)

使用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()));