在两个日期之间取几个月忽略日期

时间:2016-09-04 02:07:13

标签: date jodatime

我想计算两个日期之间的月份,并且只在忽略日期的情况下与月份进行比较,因此2012-01-312012-02-01之间应该有1个月差异。

我用joda-time执行此操作:

import org.joda.time.*;
PeriodType yearMonth = PeriodType.yearMonthDay().withDaysRemoved();
LocalDate dt1 = new LocalDate(2012, 1, 31);
LocalDate dt2 = new LocalDate(2012, 2, 1);
int months = new Period(dt1, dt2, yearMonth).getMonths();
System.out.println(months);

但我得到了打印输出:

0

虽然我使用了.withDaysRemoved(),但它不起作用。我滥用了吗?

2 个答案:

答案 0 :(得分:0)

java.time

Joda-Time项目现在处于维护模式。该团队建议迁移到java.time类。

LocalDate

与Joda-Time一样,LocalDate表示没有时间且没有时区的仅限日期的值。

LocalDate start = LocalDate.of ( 2012 , Month.JANUARY , 31 );
LocalDate stop = LocalDate.of ( 2012 , Month.MARCH , 1 );

建立保留结果的地方。

long countMonths = 0;

YearMonth

YearMonth课程代表一年零一个月。这是根据需要考虑整月的渠道,而不是天数。

YearMonth ymStart = YearMonth.from ( start );
YearMonth ymStop = YearMonth.from ( stop );

YearMonth课程有比较方法,例如isAfterisBeforeequals

ChronoUnit类可以计算一对Temporal个对象之间经过的月份。幸运的是,YearMonth类实现了Temporal并与ChronoUnit一起使用。

if ( ymStart.isAfter ( ymStop ) ) {
    // Handle error condition. Unexpected input values.
} else if ( ymStart.equals ( ymStop ) ) {
    countMonths = 0;
} else { // Else different months.
    countMonths = ChronoUnit.MONTHS.between ( ymStart , ymStop );
}

转储到控制台。

System.out.println ( "start: " + start + " | stop: " + stop + " | countMonths: " + countMonths );
  

开始:2012-01-31 |停止:2012-03-01 | countMonths:2

半开

上述结果基于半开放方法来定义开头包含的时间跨度,而结尾是独占。这种方法通常用于日期时间工作,包括整个java.time类。

因此,例如,午餐时间从中午时间的第一时刻开始,一直到下午1点的第一时刻,但不包括在内。

另一个例子:一周将在星期一开始,并在下一个星期一运行,但不包括在内。或者在这种情况下,从1月开始的一对年月,直到但不包括,March;它们产生了2个月的时间。

我相信在整个代码中使用半开放式方法可以提高清晰度并减少错误。但是,如果您或您的用户另有要求,请在上面的结果中添加一个。

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧日期时间类,例如java.util.Date.Calendar和& java.text.SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。

大部分java.time功能都被反向移植到Java 6& ThreeTen-Backport中的7,并进一步适应Android中的ThreeTenABP(见How to use…)。

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuarter等。

答案 1 :(得分:0)

LocalDate的月份算术将并且必须始终使用月计算进行计算。您指定了期间类型以便不仅仅使用日期这一事实意味着:最终结果不会显示任何日期(但LocalDate的日期成分在内部仍然使用)。

但是,如果您使用其他类型,即YearMonth,则此类型定义不同的月份算术:

LocalDate dt1 = new LocalDate(2012, 1, 31);
LocalDate dt2 = new LocalDate(2012, 2, 1);

YearMonth ym1 = new YearMonth(dt1.getYear(), dt1.getMonthOfYear());
YearMonth ym2 = new YearMonth(dt2.getYear(), dt2.getMonthOfYear());

PeriodType yearMonth = PeriodType.yearMonthDay();
System.out.println(new Period(ym1, ym2, yearMonth).getMonths()); // 1
System.out.println(new Period(ym1, ym2, yearMonth.withDaysRemoved()).getMonths()); // 1

在此您还可以看到 - 在YearMonth的上下文中 - 抑制PeriodType中的日期无关紧要。