我该如何在Java 8中比较两个时间段(Period)?
例如:
Period one = Period.of(10,0,0);
Period two = Period.of(8,0,0);
在这种情况下,一个比两个大。
确实,在一般情况下,由于月份的标准长度未定义,比较两个Period
对象是没有意义的。
然而,在许多情况下,您可以使用类似以下实现的实现。合同将类似于compareTo()
的合同:
public int comparePeriodsApproximately(Period p1, Period p2) {
return period2Days(p1) - period2Days(p2);
}
private int period2Days(Period p) {
if (p == null) {
return 0;
}
return (p.getYears() * 12 + p.getMonths()) * 30 + p.getDays();
}
private fun Period.toDayEstimate():Int = years * 12 + months * 30 + days
- m.reiterJB Nizet说得很对。根据Java文档中Period类的说明,有一个类与Period(Duration)类似,可以根据您的业务需求使用它,因此您不能比较Periods。
"在添加到ZonedDateTime时,持续时间和周期在处理夏令时方面有所不同。持续时间将添加精确的秒数,因此一天的持续时间始终精确为24小时。相比之下,期间将添加一个概念上的日,试图保持本地时间。"
Period period = Period.of(10, 0, 0);
Period period2 = Period.of(10, 0, 0);
// No compareTo method in period
System.out.println(period.compareTo(period2));
Duration duration = Duration.ofDays(3);
Duration duration2 = Duration.ofDays(3);
// Can compare durations as it gives you the exact time
System.out.println(duration.compareTo(duration2));
月
和一个 年
的时间段,可以按照以下方式操作:Period periodOfMonths = Period.ofMonths(16);
Period periodOfYears = Period.ofYears(1);
// Check if period of months is ghreather that the period of years
System.out.println(periodOfMonths.toTotalMonths() > periodOfYears.toTotalMonths());
public static int compareTo(final Period first, final Period second)
{
return LocalDate.MIN.plus(first).compareTo(LocalDate.MIN.plus(second));
}
LocalDate.EPOCH
。除此之外,该方法将生成结果,这些结果可能很难理解和预测,但是这些结果是可重现的。 - Ole V.V.这个应该是无懈可击的。是否有用呢?
我声称,从2097年2月1日开始向前计算,你可以得到给定年份和月份中最少的天数,因为首先要计算二月(28天),直到连续两个月都有31天(七月和八月)需要很长时间,而且要更长时间才能遇到闰年(2104年)。另外,2200年和2300年都不是闰年,如果计算到那时,也不会出现闰年。相反,当从同一日期向后计算时,你将得到最大可能的天数。你首先要计算通过31天的2个月(1月和12月)。你遇到的第一个二月是在2096年,是一个闰年,所以有29天。而2000年是一个闰年。
所以我的诀窍是从提到的日期两个时期的差异进行双向计数。如果计数一致,差异为正(或负),那么无论我们从哪一天开始计数,两个
(或一个
)总是更长的。
在某些情况下,计数可能不一致。那么我就拒绝称之为更长的时期。
Period one = Period.of(10, 0, 0);
Period two = Period.of(8, 0, 0);
if (one.normalized().equals(two.normalized())) {
System.out.println("They are the same.");
} else {
Period diff = two.minus(one);
LocalDate anchor = LocalDate.of(2097, Month.FEBRUARY, 1);
LocalDate plusDiff = anchor.plus(diff);
LocalDate minusDiff = anchor.minus(diff);
if (plusDiff.isAfter(anchor) && minusDiff.isBefore(anchor)) {
System.out.println("Two is greater (unambiguously)");
} else if (plusDiff.isBefore(anchor) && minusDiff.isAfter(anchor)) {
System.out.println("One is greater (unambiguously)");
} else {
System.out.println("Cannot decide");
}
}
在这种情况下的输出(使用问题中的句点):
一个更大(明确无误)
我在第一次比较中使用的normalized
方法将年份和月份之间进行转换,确保月份在-11到+11的区间内,并且与年份具有相同的符号(除非年份为0)。由于一年总是有12个月,因此可以明确无误地完成此操作。
您可以将其细化为报告一个期间长于或等于另一个期间。例如,如果one
是一个月,而two
是31天,则我们知道two
至少与one
一样长,尽管我们无法确定它是否也严格更长。
可以通过借鉴LocalDate
的方法,使用适当的compareTo()
方法来实现该功能。
public static int compareTo(final Period first, final Period second)
{
final LocalDate now = LocalDate.now();
return now.plus(first).compareTo(now.plus(second));
}
Period
不可比较,也不应该比较。然而,JSR-310的设计者们允许/定义了一个方法isNegative()
,并使用疯狂的定义和实现来规避“P1M-30D”的问题。非常糟糕。 - Meno Hochschild