计算当月的最后一天


144

我在计算本月下一个最后一天何时发送预定的通知时遇到问题。

这是我的代码:

RecurrenceFrequency recurrenceFrequency = notification.getRecurrenceFrequency();
Calendar nextNotifTime = Calendar.getInstance();

这是导致问题的线,我相信:

nextNotifTime.add(recurrenceFrequency.getRecurrencePeriod(), 
                  recurrenceFrequency.getRecurrenceOffset());

如何使用日历正确设置下个月的通知的最后一天?


1
将其设置为下个月的第一天,然后回滚一天。
2012年

一个SSCCE会更容易回答这个问题。您实际遇到什么问题?
DNA

Answers:


347
Calendar.getInstance().getActualMaximum(Calendar.DAY_OF_MONTH);

这将返回当前月份的实际最大值。例如,现在是leap年的2月,因此它返回29作为int


谢谢,我需要获得下个月的最大值,但是它仍然必须工作,因为它也可以是该月的第一天,因为该部分现在可以工作了。再次感谢您的时间和精力
OakvilleWork

4
ActualMaximum每次约会都没有问题。只需在调用之前将日历实例滚动到所需日期即可getActualMaximum。可以通过getActualMinimum()
AlexR

好的,非常感谢Alex,因此,如果我希望将实例推迟到一个月并找出该月的getActualMaximum,我将如何做?欢呼声
OakvilleWork

这是亚历克斯吗?nextNotifTime.roll(Calendar.MONTH,true); nextNotifTime.getActualMaximum(Calendar.DAY_OF_MONTH);
OakvilleWork '02

我也设置在此之后,准备时间日期:nextNotification.setReadyDateTime(nextNotifTime.getTime()); 所以我不应该这样做,而不是:nextNotifTime.roll(Calendar.MONTH, true); nextNotifTime.getActualMaximum(Calendar.DAY_OF_MONTH); nextNotifTime.setTime(Calendar.DAY_OF_MONTH);
OakvilleWork '02

61

java.time.temporal.TemporalAdjusters.lastDayOfMonth()

使用java.timeJava 8中内置的库,您可以使用该TemporalAdjuster接口。我们发现可以在TemporalAdjusters实用程序类中使用的实现lastDayOfMonth

import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;

LocalDate now = LocalDate.now(); //2015-11-23
LocalDate lastDay = now.with(TemporalAdjusters.lastDayOfMonth()); //2015-11-30

如果您需要添加时间信息,则可以使用任何可用LocalDateLocalDateTime转化方式,例如

lastDay.atStartOfDay(); //2015-11-30T00:00

好答案。但是最后一部分很弱,建议使用LocalDateTime。该类没有任何时区或从UTC偏移的概念。因此,它无法确定特定位置的特定日期实际何时开始。该类仅适用于普通的24小时工作日,不适用于实际工作日。对于真实日期,请指定时区:ZonedDateTime zdt = now.atStartOfDay( ZoneId.of( "Asia/Tokyo" ) ) ;。由于诸如夏令时(DST)之类的异常,某些地方的某些日子可能会在其他时间开始,例如01:00。
罗勒·布尔克

35

并将最后一天作为Date对象:

Calendar cal = Calendar.getInstance();
cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));

Date lastDayOfMonth = cal.getTime();

22

您可以将日历设置为下个月的第一天,然后减去一天。

Calendar nextNotifTime = Calendar.getInstance();
nextNotifTime.add(Calendar.MONTH, 1);
nextNotifTime.set(Calendar.DATE, 1);
nextNotifTime.add(Calendar.DATE, -1);

运行此代码后,nextNotifTime将设置为当前月份的最后一天。请记住,如果今天是该月的最后一天,则此代码的最终效果是Calendar对象保持不变。


17

以下内容将始终给出正确的结果:

    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.MONTH, ANY_MONTH);
    cal.set(Calendar.YEAR, ANY_YEAR);
    cal.set(Calendar.DAY_OF_MONTH, 1);// This is necessary to get proper results
    cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
    cal.getTime();

为什么有必要?你能告诉我:)
弗兰克·芳

1
是的,正是由于上述确切原因,测试才失败。问题在于,除非设置了DAY_OF_MONTH,否则它将默认为current。
ppearcy

7

java.time这里使用最新的库是最好的解决方案:

LocalDate date = LocalDate.now();
LocalDate endOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());

或者,您可以执行以下操作:

LocalDate endOfMonth = date.withDayOfMonth(date.lengthOfMonth());


2

查看getActualMaximum(int field)Calendar对象的方法。

如果将“日历”对象设置为要查找最后日期的月份,getActualMaximum(Calendar.DAY_OF_MONTH)则将为您提供最后一天。


2
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        Date date = sdf.parse("11/02/2016");

        Calendar calendar = Calendar.getInstance();  
        calendar.setTime(date);  

        System.out.println("First Day Of Month : " + calendar.getActualMinimum(Calendar.DAY_OF_MONTH));  
        System.out.println("Last Day of Month  : " + calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); 

1

Kotlin日期扩展实现使用 java.util.Calendar

fun Date.toEndOfMonth(): Date {
    return Calendar.getInstance().apply {
        time = this@toEndOfMonth
    }.toEndOfMonth().time
}

fun Calendar.toEndOfMonth(): Calendar {
    set(Calendar.DAY_OF_MONTH, getActualMaximum(Calendar.DAY_OF_MONTH))
    return this
}

您可以toEndOfMonth在每个Date对象上调用函数,例如Date().toEndOfMonth()


4
这些可怕的类在几年前被JSR 310所采用的现代java.time类所取代。建议在2019年使用这些遗留类是不明智的建议。
罗勒·布尔克

这不是一个坏建议。现代的java.time仅可用于API 26+的Android。当支持(不是那样)旧设备时,我们仍然依赖java.util。*
拉斐尔·查加斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.