我需要获取给定月份的最后日期,就我而言,我需要获取六月的最后日期。 我的代码如下:

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;
}

起初,我得到了实际的月份,并且它是该年的上半年或第二个需要另一个日期,总是那个半年的最后一个日期。 上面的代码返回的是

2015-01-31

而不是我认为应该的2015-06-31。 我该如何解决?

您是否注意到要设置DAY_OF_YEAR而不是DAY_OF_MONTH?

将返回值更改为实际月份的最后一天,在这种情况下为2015-08-31

不幸的是,您的代码此刻无处不在-您无缘无故地多次创建新的日历,并且调用Calendar.getActualMaximum传递了错误的常量类型(值而不是字段)。

您想要类似的东西:

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,如果您使用的不是Java,我强烈建议您使用Joda Time-这两个API都比java.util.Calendar好得多。

java.time

现在,使用现代的java.time类要容易得多。具体来说,是YearMonth,Month和LocalDate类。

LocalDate

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

时区对于确定日期至关重要。在任何给定时刻,日期都会在全球范围内变化。例如,法国巴黎午夜过后几分钟是新的一天,而在魁北克蒙特利尔仍然是"昨天"。

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

以continent/region格式指定正确的时区名称,例如America/Montreal,Africa/Casablanca或Pacific/Auckland。切勿使用3-4个字母的缩写,例如EST或IST,因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

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。
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枚举对象,一年中的每个月使用一个。提示:在整个代码库中使用这些Month对象而不是仅使用整数,可以使您的代码更具自记录性,确保有效值并提供类型安全性。

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() );

知道一年中的哪半年,就可以在同一年的六月底或十二月底。

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框架内置于Java 8及更高版本中。这些类取代了麻烦的旧版旧式日期时间类,例如java.util.Date,Calendar和SimpleDateFormat。

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

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。

您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

Java SE 8,Java SE 9,Java SE 10和更高版本

内置的

标准Java API的一部分,具有捆绑的实现。

Java 9添加了一些次要功能和修复。

Java SE 6和Java SE 7

java.time的许多功能在ThreeTen-Backport中都被反向移植到Java 6和7。

安卓系统

更高版本的Android捆绑了java.time类的实现。

对于早期的Android(<26),ThreeTenABP项目改编了ThreeTen-Backport(如上所述)。请参阅如何使用ThreeTenABP…。

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval,YearWeek,YearQuarter等。