如何规范ZonedDateTime以便.equals()工作? [英] How to normalise ZonedDateTime so that .equals() works?
问题描述
我有类似的代码:
import java.time._
object app {
def main (args :Array[String]) = {
println("app started")
// create two ZonedDateTime objects for 1st Jan 2018, 10am UTC
// using separate methods
val zdt1 = ZonedDateTime.of(2018, 1, 1, 10, 0, 0, 0, ZoneId.of("UTC"))
val zdt2 = ZonedDateTime.parse("2018-01-01T10:00:00Z")
println(s"COMPARING: $zdt1 and $zdt2")
println("== check: " + (zdt1 == zdt2))
println(".equals check: " + (zdt1.equals(zdt2)))
println(".isEqual check " + (zdt1.isEqual(zdt2)))
println("app finished")
}
}
可在此处找到代码: https://ideone.com/43zf8B
问题:
- 这些都是类型的ZonedDateTime对象
- 根据.isEqual()方法,它们是等效的.
- 根据.equals()方法,它们不等效
但是我的测试套件使用beEquals进行深度匹配 对这些datetime实例进行的类的操作 因此,我需要一种将它们标准化的方法,以便 .equals()返回true.
请问如何将它们标准化?
如果用ZonedDateTime.of(2018, 1, 1, 10, 0, 0, 0, ZoneOffset.UTC)
创建zdt1
,则两个对象在equals()
下是相等的(在Java中仍然不在==
下).>
显然,当区域名称不同时,使区域相等是不够的.通过使用ZoneOffset.UTC
构造第一个ZonedDateTime
,两者将具有相同的时区,因此将相等.进行更改后,至少在Mac上,zdt1.getZone() == zdt2.getZone()
现在评估为true
.
作为对问题的更直接答案,您可以按以下方式规范化ZonedDateTime
对象(带有分号的Java语法,请自行翻译):
zdt1 = zdt1.withZoneSameInstant(zdt1.getZone().normalized());
当然,与zdt2
类似. ZoneId.normalized()
承诺在可能的情况下返回ZoneOffset
,这取决于您的情况.因此,在您的情况下,它确实使两个对象在equals()
下相等.在所有其他情况下,我都不确定.
一种比较安全的方法是让比较显式地处理不同但相等的时区:
zdt1.toInstant().equals(zdt2.toInstant())
&& zdt1.getZone().getRules().equals(zdt2.getZone().getRules())
这将使用您问题中的两个日期时间计算为true
.
BTW Code available here: https://ideone.com/43zf8B The issue: However my test suite uses deep matching using beEquals
operations against the classes these datetime instances are
in, therefore I need a way to normalise them so that
.equals() returns true. how can I normalise them please? If I create Apparently it’s not enough for the zones to be equivalent when their names are different. By using As a more direct answer to your question, you may normalize your Similarly for A safer way would be to have the comparison explicitly take care of different but equal time zones: This evaluates to BTW 这篇关于如何规范ZonedDateTime以便.equals()工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
zdt1
with ZonedDateTime.of(2018, 1, 1, 10, 0, 0, 0, ZoneOffset.UTC)
, the two objects are equal under equals()
(still not under ==
in Java).ZoneOffset.UTC
for constructing the first ZonedDateTime
, both will have the same time zone and will thus be equal. With my change, at least on my Mac, zdt1.getZone() == zdt2.getZone()
now evaluates to true
.ZonedDateTime
objects this way (Java syntax with semicolon, please translate yourself): zdt1 = zdt1.withZoneSameInstant(zdt1.getZone().normalized());
zdt2
, of course. ZoneId.normalized()
promises to return a ZoneOffset
where possible, which it is in your case. So in your case it does make two objects that are equal under equals()
. I’m not sure it will in all other cases.zdt1.toInstant().equals(zdt2.toInstant())
&& zdt1.getZone().getRules().equals(zdt2.getZone().getRules())
true
with your two date-times from the question.isEqual()
compares the instants in time only, not the zones at all, which is why it didn’t care.