我有一个joda-time Interval,可以延续多天。计算它跨过午夜的次数的最佳方法是什么?
Interval可能会也可能不会在其开始日期的午夜开始,并且可能不到一天。
答案 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();
}
基本上,我将间隔的开始时间调整为白天开始时(通常是午夜),然后计算调整后的间隔中包含的完整天数。
在某些测试中,不确定这是否比其他答案更好或更差,所以如果有人发表评论,我会留在这里。