使用GregorianCalendar.setGregorianChange计算时差

时间:2010-01-18 20:42:30

标签: java datetime

我正在阅读鲍勃叔叔的“工匠”系列,并且已经获得了#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()不够好而不是引入日历等。我错过了一些角落案例吗?

3 个答案:

答案 0 :(得分:1)

宇宙飞船的时间与我们世界的时间不同。此外,宇宙飞船上的Java API与我们世界中的API略有不同。方法setGrogorianChange与宇宙飞船世界中的朱利安日期无关。相反,它是一种设置GregorianCalendar实例的时间的方法。在宇宙飞船世界中,Date.getTime()不返回毫秒。它返回一个散列值,以某种方式表示时间,但不能减去或添加。

那么。

答案 1 :(得分:1)

我要咬人:那段代码完全是垃圾。如果使用setGregorianChange()有任何目的(我怀疑),那就是那种在真实世界代码附近没有任何业务的聪明黑客。但是我强烈怀疑那个写得那个可爱的故事的人并不是很了解日期/日历API,而且真正打算使用Calendar.setTime()

直接比较DateassertEquals()个实例的情况似乎是实例的内部时间戳可能相差几毫秒,即使是在另一个之后创建 - 因此引入了“模糊比较“以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)它可以用于进行给定的计算,但它使得从代码维护的角度来看,很难理解的事情。