我正在阅读鲍勃叔叔的“工匠”系列,并且已经获得了#29(PDF)。在其中,测试代码中有这个片段,因为断言日期足够接近:
private boolean DatesAreVeryClose(Date date1, Date date2) {
GregorianCalendar c1 = new GregorianCalendar();
GregorianCalendar c2 = new GregorianCalendar();
c1.setGregorianChange(date1);
c2.setGregorianChange(date2);
long differenceInMS = c1.getTimeInMillis() - c2.getTimeInMillis();
return Math.abs(differenceInMS) <= 1;
}
我阅读了文档,但却无法理解为什么简单地使用Date.getTime()
不够好而不是引入日历等。我错过了一些角落案例吗?
答案 0 :(得分:1)
宇宙飞船的时间与我们世界的时间不同。此外,宇宙飞船上的Java API与我们世界中的API略有不同。方法setGrogorianChange与宇宙飞船世界中的朱利安日期无关。相反,它是一种设置GregorianCalendar实例的时间的方法。在宇宙飞船世界中,Date.getTime()不返回毫秒。它返回一个散列值,以某种方式表示时间,但不能减去或添加。
那么。
答案 1 :(得分:1)
我要咬人:那段代码完全是垃圾。如果使用setGregorianChange()
有任何目的(我怀疑),那就是那种在真实世界代码附近没有任何业务的聪明黑客。但是我强烈怀疑那个写得那个可爱的故事的人并不是很了解日期/日历API,而且真正打算使用Calendar.setTime()。
直接比较Date
中assertEquals()
个实例的情况似乎是实例的内部时间戳可能相差几毫秒,即使是在另一个之后创建 - 因此引入了“模糊比较“以Math.abs(differenceInMS) <= 1
的形式。但这也不需要通过GregorianCalendar
来绕行,也不是足够的模糊 - 完整的GC甚至只是时钟粒度很容易导致两个日期在另一个之后相隔10毫秒或更长时间。
真正的问题是Java中缺少“日历日期”数据类型 - 与日期粒度进行比较相当冗长(您必须使用Calendar
将所有时间字段设置为0)。 Joda Time的DateMidnight课程就是这里真正需要的课程。
答案 2 :(得分:0)
没有充分理由不使用Date.getTime()
。最有可能的是,作者对他熟悉的GregorianCalendar
对象的使用进行了日期/时间操作。
另一方面,使用setGregorianChange
来获取此信息似乎......滥用了API。该方法用于设置“从Julian日期切换到格里高利日期时的点。默认值是1582年10月15日(格里高利)。”(javadoc)它可以用于进行给定的计算,但它使得从代码维护的角度来看,很难理解的事情。