如何确定间隔期间午夜交叉的次数

时间:2014-06-13 22:30:52

标签: jodatime

我有一个joda-time Interval,可以延续多天。计算它跨过午夜的次数的最佳方法是什么?

Interval可能会也可能不会在其开始日期的午夜开始,并且可能不到一天。

2 个答案:

答案 0 :(得分:2)

这里我假设一个半开的区间,包括开始但不包括结束。首先,我使用类型LocalDate来排除日期差异的时间效应。

public int getCountOfMidnights(Interval interval) {
  LocalDate start = interval.getStart().toLocalDate();
  LocalDate end = interval.getEnd().toLocalDate();
  int countOfMidnights = Days.daysBetween(start, end).getDays();

  if (interval.getStart().toLocalTime().equals(LocalTime.MIDNIGHT)) {
    countOfMidnights++;
  }

  return countOfMidnights;
}

由于OP自己的回答而更新:

我已经测试了他的代码,特别是时区" America / Sao_Paulo"它在2013-10-20午夜时分引入了夏季,而不是跳到T01:00。

使用@GabrielBauman解决方案的输出结果:

    DateTimeZone tz = DateTimeZone.forID("America/Sao_Paulo");
    DateTime start = new DateTime(2013, 10, 20, 5, 0, tz);
    DateTime end = new DateTime(2013, 10, 21, 0, 0, tz);
    Interval interval = new Interval(start.withTimeAtStartOfDay(), end);
    System.out.println(getCountOfMidnights(interval)); // 0!!!

使用我的解决方案,正确的结果是1.如果间隔时间从午夜开始,还有另一个问题是不考虑条件(OP必须考虑是否也要计算这个。在我看来,是的,请参阅我的评论也在下面)。

结论:在计算中午时,我们基本上只有一个仅限日期的方案。

因此,最好避免在内部包含时区的时态类型(如果可能)(如Joda - DateTime或JDK-GregorianCalendar或新JSR-310中的ZonedDateTime)因为这里是时间算术不太清楚(对于墙壁时间比较也是明智的)。这就是我使用像LocalDate这样的本地类型的主要原因。这也是我在自己的库中放弃这种混合类型的几个原因之一(另一个原因是例如数据库中直接存储的缺失选项)。这些具有日期,时间和时区的通用类型远没有大多数用户认为的那么有用。在大多数情况下,使用本地类型并使用全局类型主要用于时区感知转换目的更好。

答案 1 :(得分:0)

我想出了以下内容:

public int getCountOfMidnights(Interval i) {
    return Days.daysIn(i.withStart(i.getStart().withTimeAtStartOfDay())).getDays();
}

基本上,我将间隔的开始时间调整为白天开始时(通常是午夜),然后计算调整后的间隔中包含的完整天数。

在某些测试中,不确定这是否比其他答案更好或更差,所以如果有人发表评论,我会留在这里。