检查 Joda-Time DateTime 对象是否不代表一年中的最后一天的更聪明的方法是什么?

What is a smarter way to check if a Joda-Time DateTime object does not represent the last day of the year?

我正在使用 Joda-Time,我想检查某个特定日期是否 而不是 一年的最后一天(换句话说,日期不应该是31/12/XXXX)。它应该适用于任何一年。

为了实现这个检查,我做了这样的事情:

DateTime dataSecondoMovimento = new DateTime(mappaQuote.get(2).getDatariferimentoprezzo());

if(!(dataSecondoMovimento.getMonthOfYear() == 12 && dataSecondoMovimento.getDayOfMonth() == 31)) {
    System.out.println("It is not the end of year !!!");
}

所以基本上我是在检查月份是否不是 12 月以及日期是否不是 31(两者都必须为真,因为它不是一年的最后一天)。我认为这应该可以正常工作。

我的问题:Joda-Time 是否提供了一种更简洁的方法来执行此操作?是否存在检查特定日期是否为一年中最后一天的方法?

另一种简单的方法是将日期添加一天,然后检查年份是否已更改:

DateTime dataSecondoMovimentoPlusOneDay = dataSecondoMovimento.plusDays(1);

boolean yearChanged = dataSecondoMovimento.getYear() != dataSecondoMovimentoPlusOneDay.getYear();

目前 Joda Time 没有直接实现 getLastDayOfYear(),我们必须使用逻辑方式来处理一年的最后一天,您尝试过一种方式,或者您可以使用如下替代方式

 public int getDayOfYear() { //This is library method
    return getChronology().dayOfYear().get(getMillis());
}

if(!getDayOfYear() <=365 ||!getDayOfYear() <=366) { //Considering leap year
System.out.println("It is not the end of year !!!");
}

恕我直言,你的方法很实用。

我唯一想到的是

dataSecondoMovimento.plusDays(1).getDayOfYear() == 1

哪个更短但几乎没有更有效

P.S.: 我发现这种方法有一个小好处——它适用于非公历的不太可能的情况,最后一个日历没有 12 个月或 31 天!

tl;博士

MonthDay.from( zdt ).equals( 
    MonthDay.of( 
        Month.DECEMBER , 
        Month.DECEMBER.maxLength() 
    )
)

java.time

Joda-Time 项目现在处于维护模式,建议迁移到 java.time classes 内置于 Java.

这些包括 MonthDay class 来表示没有年份的日期。我们知道一年的最后一天总是 12 月 31 日。我们为该值设置一个常量。为了防止愚蠢的错误,我们要求月份的长度而不是硬编码 31.

static final public MonthDay MONTHDAY_END_OF_YEAR = MonthDay.of( Month.DECEMBER , Month.DECEMBER.maxLength() );

class 相当于 java.time 中的 Joda-Time DateTimeZonedDateTime

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.now( z );

请求MonthDay

MonthDay md = MonthDay.from( zdt );

与我们的常量比较。

Boolean isLastDay = md.equals( MONTHDAY_END_OF_YEAR );

TemporalAdjuster

对了,还有个TemporalAdjuster for getting last day of the year: TemporalAdjusters.lastDayOfYear()(注意复数's')。

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtNow = ZonedDateTime.now( z );
ZonedDateTime zdtLastDayOfYear = zdtNow.with( TemporalAdjusters.lastDayOfYear() ) ;
MonthDay mdYearEnd = MonthDay.from( zdtLastDayOfYear );

转储到控制台。

System.out.println( "zdtNow: " + zdtNow );
System.out.println( "zdtLastDayOfYear: " + zdtLastDayOfYear );
System.out.println( "mdYearEnd: " + mdYearEnd );

zdtNow: 2016-11-26T15:44:06.449-05:00[America/Montreal]

zdtLastDayOfYear: 2016-12-31T15:44:06.449-05:00[America/Montreal]

mdYearEnd: --12-31

参见 live code in IdeOne.com


关于java.time

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

Joda-Time project, now in maintenance mode,建议迁移到java.time。

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

从哪里获得java.time classes?

  • Java SE 8 and SE 9 及更高版本
    • 内置。
    • 标准 Java API 的一部分,带有捆绑实施。
    • Java 9 添加了一些小功能和修复。
  • Java SE 6 and SE 7
  • Android
    • ThreeTenABP项目专门为Android改编了ThreeTen-Backport(上面提到的)。
    • 参见

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

DateTime.Property

如果您想要一些接近您用自然语言表达问题的方式的代码,您可以编写一个方法,您可以在其中访问 DateTime.Property called dayOfYear 来询问最大值,即一年中的最后一天.

private boolean isLastDayOfYear(DateTime dateTime) {
    return dateTime.dayOfYear().get() == dateTime.dayOfYear().getMaximumValue();
}

然后:

if (!isLastDayOfYear(dataSecondoMovimento)) {
    System.out.println("It is not the end of year !!!");
}