7

我有这个代码:

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?

4

2 回答 2

21

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

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

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

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

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

当且仅当具有与类的每个and相同的布尔值时,类的自然排序C被称为与 equals 一致e1.compareTo(e2) == 0e1.equals(e2)e1e2C

(引自Comparable接口文档

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

  1. 使用isBefore,isAfterisEqual:

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

    输出:

false
false
true
  1. 使用Yoav Gur 的答案:明确比较瞬间。
于 2018-04-06T07:04:47.093 回答
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())); 
于 2018-04-06T06:03:09.963 回答