последний день месяца расчет


149

У меня возникают проблемы с вычислением того, когда в следующий последний день месяца будет отправлено уведомление, которое планируется отправить.

Вот мой код:

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

Я считаю, что эта строка вызывает проблемы:

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

Как я могу использовать Календарь, чтобы правильно установить последний день следующего месяца для уведомления?


1
Установите первый день следующего месяца, а затем выполните откат на один день.
Bill

SSCCE будет легче ответить на этот вопрос. Какую проблему вы на самом деле видите?
DNA

Ответы:


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

Это возвращает фактический максимум за текущий месяц. Например, сейчас февраль високосного года, поэтому он возвращает 29 как int.


спасибо, мне нужно получить максимум на следующий месяц, но он еще должен работать, что это может быть и первый день месяца, так как эта часть работает сейчас. еще раз спасибо за ваше время и усилия
OakvilleWork

4
Получить ActualMaximumна каждое свидание - не проблема . Просто перед звонком сверните экземпляр календаря на нужную дату getActualMaximum. Первое свидание может быть полученоgetActualMinimum()
AlexR

хорошо, большое спасибо, Алекс, так что, если я хочу откатить экземпляр до месяца вперед и узнать getActualMaximum за этот месяц, как бы я это сделал? ура
OakvilleWork

это будет Алекс? nextNotifTime.roll (Calendar.MONTH, истина); nextNotifTime.getActualMaximum (Calendar.DAY_OF_MONTH);
OakvilleWork

Также я установил готовое время после даты этого: nextNotification.setReadyDateTime(nextNotifTime.getTime()); поэтому я не должен делать это вместо: nextNotifTime.roll(Calendar.MONTH, true); nextNotifTime.getActualMaximum(Calendar.DAY_OF_MONTH); nextNotifTime.setTime(Calendar.DAY_OF_MONTH); ?
OakvilleWork

63

java.time.temporal.TemporalAdjusters.lastDayOfMonth ()

Используя java.timeвстроенную в Java 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

Если вам нужно добавить информацию о времени, вы можете использовать любую доступную LocalDateдля LocalDateTimeпреобразования, например

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

Хороший ответ. Но эта последняя часть слабая и предполагает использование LocalDateTime. В этом классе отсутствует понятие часового пояса или смещения от UTC. Таким образом, он не может определить, когда на самом деле начинается конкретный день в конкретном месте. Этот класс работает только для обычных 24-часовых дней, а не для реальных дней. Для настоящих дней, указать часовой пояс: ZonedDateTime zdt = now.atStartOfDay( ZoneId.of( "Asia/Tokyo" ) ) ;. Некоторые дни в некоторых местах могут начинаться в другое время, например, 01:00, из-за аномалий, таких как переход на летнее время (DST).
Basil

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 остается неизменным.


18

Следующие действия всегда будут давать правильные результаты:

    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, по умолчанию будет использоваться текущий.
ppearcy

7

java.timeЛучшее решение - использовать последнюю версию библиотеки:

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

В качестве альтернативы вы можете:

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


3

Посмотрите на getActualMaximum(int field)метод объекта Calendar.

Если вы установите объект 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
Эти ужасные классы были вытеснены много лет назад современными классами java.time с принятием JSR 310. Предлагать эти устаревшие классы в 2019 году - плохой совет.
Basil

Это неплохой совет. Современный java.time доступен для Android только для API 26+. Мы по-прежнему зависим от java.util. * При поддержке (не очень) старых устройств.
Рафаэль Шагас,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.