使用日历获取 XY 月的最后一天 Java

Getting last Day of Month XY with Calendar Java

我需要获取给定月份的最后一个日期,在我的例子中,我需要获取 6 月的最后一个日期。我的代码如下:

cal.set(Calendar.DAY_OF_MONTH,
            Calendar.getInstance().getActualMinimum(Calendar.DAY_OF_MONTH));
    int month = cal.get(Calendar.MONTH) + 1;

    if (month <= 6) {
        cal.set(Calendar.DAY_OF_YEAR, Calendar.getInstance()
                .getActualMaximum(Calendar.JUNE));
        return (Calendar) cal;
    } else {
        cal.set(Calendar.DAY_OF_YEAR, Calendar.getInstance()
                .getActualMaximum(Calendar.DAY_OF_YEAR));
        return (Calendar) cal;
    }

起初我得到实际的月份,无论是上半年还是下半年都需要另一个日期,总是那半年的最后一个日期。使用上面的代码 return 是

2015-01-31

而不是我认为的 2015-06-31。我怎么可能解决这个问题?

你的代码目前到处都是,不幸的是 - 你无缘无故地多次创建新日历,并且你正在调用 Calendar.getActualMaximum 传递错误类型的常量(a值而不是字段)。

你想要这样的东西:

int month = cal.get(Calendar.MONTH) <= Calendar.JUNE
    ? Calendar.JUNE : Calendar.DECEMBER;
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calenday.DAY_OF_MONTH));
return cal;

但是,如果您使用的是 Java 8,我强烈建议您使用 java.time,如果您不是,我强烈建议您使用 Joda Time - 两者都是比 [=13= 好得多的 API ].

java.time

现在使用现代 java.time classes 更容易了。具体来说,YearMonthMonthLocalDate classes.

LocalDate

LocalDate class 表示没有时间和时区的仅日期值。

时区对于确定日期至关重要。对于任何给定时刻,日期在全球范围内因地区而异。例如,Paris France is a new day while still “yesterday” in Montréal Québec.

午夜后几分钟

如果未指定时区,JVM 将隐式应用其当前默认时区。该默认设置可能随时更改,因此您的结果可能会有所不同。最好明确指定您的 desired/expected 时区作为参数。

指定 proper time zone name in the format of continent/region, such as America/Montreal, Africa/CasablancaPacific/Auckland。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们 不是 真正的时区,没有标准化,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

如果你想使用 JVM 当前的默认时区,请求它并作为参数传递。如果省略,则隐式应用 JVM 的当前默认值。最好是明确的,因为默认值可能会在任何时候 在运行时 中被 JVM 中任何应用程序的任何线程中的任何代码更改。

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

或指定日期。您可以通过数字设置月份,1 月至 12 月的编号为 1-12。

LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.

或者,更好的是,使用 Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety

LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;

YearMonth

手头有 LocalDate,获取该日期的年月。

YearMonth ym = YearMonth.from( ld ) ;

看看是哪半年

Set < Month > firstHalfOfYear = EnumSet.range( Month.JANUARY , Month.JUNE ); // Populate the set with first six months of the year.
boolean isFirstHalf = firstHalfOfYear.contains( ym.getMonth() );

知道是哪半年,就得到当年的6月末或12月末

LocalDate result = null;
if ( isFirstHalf ) {
    result = ym.withMonth( Month.JUNE.getValue() ).atEndOfMonth();
} else {  // Else in last half of year.
    result = ym.withMonth( Month.DECEMBER.getValue() ).atEndOfMonth();
}

关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

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

您可以直接与您的数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes.

从哪里获得java.time classes?

  • Java SE 8, Java SE 9, Java SE 10,及以后
    • 内置。
    • 标准 Java API 的一部分,带有捆绑实施。
    • Java 9 添加了一些小功能和修复。
  • Java SE 6 and Java SE 7
  • Android
    • Android java.time classes.
    • 捆绑实施的更高版本
    • 对于较早的 Android (<26),ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See .

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.