calcolo dell'ultimo giorno del mese


144

Sto riscontrando problemi con il calcolo di quando il prossimo ultimo giorno del mese è per una notifica che è prevista l'invio.

Ecco il mio codice:

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

Questa è la linea che causa problemi che credo:

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

Come posso utilizzare il Calendario per impostare correttamente l'ultimo giorno del mese successivo per la notifica?


1
Impostalo sul primo giorno del mese successivo e poi torna indietro di un giorno.
Bill

Un SSCCE renderebbe più semplice rispondere a questa domanda. Che problema stai effettivamente vedendo?
DNA,

Risposte:


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

Questo restituisce il massimo effettivo per il mese corrente. Ad esempio, è febbraio dell'anno bisestile, quindi restituisce 29 come int.


grazie, devo ottenere il massimo per il prossimo mese, tuttavia deve anche funzionare perché possa essere anche il primo giorno del mese, poiché quella parte funziona ora. grazie ancora per il tuo tempo e impegno
OakvilleWork,

4
Non è un problema ottenere ActualMaximumper ogni data. Basta scorrere l'istanza del calendario alla data richiesta prima di chiamare getActualMaximum. La prima data può essere ottenuta dagetActualMinimum()
AlexR

ok grazie mille Alex, quindi se volessi portare l'istanza a un mese in anticipo e scoprire getActualMaximum per quel mese come lo farei ?? salute
OakvilleWork,

sarebbe questo Alex? nextNotifTime.roll (Calendar.MONTH, true); nextNotifTime.getActualMaximum (Calendar.DAY_OF_MONTH);
OakvilleWork,

inoltre ho impostato la data pronta dopo questo: nextNotification.setReadyDateTime(nextNotifTime.getTime()); quindi non dovrei farlo invece nextNotifTime.roll(Calendar.MONTH, true); nextNotifTime.getActualMaximum(Calendar.DAY_OF_MONTH); nextNotifTime.setTime(Calendar.DAY_OF_MONTH); :?
OakvilleWork,

61

java.time.temporal.TemporalAdjusters.lastDayOfMonth ()

Utilizzando la java.timelibreria integrata in Java 8, è possibile utilizzare l' TemporalAdjusterinterfaccia. Troviamo un'implementazione pronto per l'uso in TemporalAdjustersclasse di utilità: 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

Se è necessario aggiungere informazioni temporali, è possibile utilizzare qualsiasi tipo LocalDatedi LocalDateTimeconversione disponibile

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

Buona risposta. Ma quest'ultima parte è debole, suggerendo l'uso di LocalDateTime. Quella classe non ha alcun concetto di fuso orario o offset da UTC. Quindi non può determinare quando inizia un determinato giorno in un determinato luogo. Quella classe funziona solo per semplici giorni generici di 24 ore, non giorni del mondo reale. Per giorni veri, specificare un fuso orario: ZonedDateTime zdt = now.atStartOfDay( ZoneId.of( "Asia/Tokyo" ) ) ;. Alcuni giorni in alcuni luoghi potrebbero iniziare in un'ora diversa, ad esempio 01:00, a causa di anomalie come l'ora legale (DST).
Basil Bourque,

35

E per ottenere l'ultimo giorno come oggetto Date:

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

Date lastDayOfMonth = cal.getTime();

22

È possibile impostare il calendario sul primo del mese successivo e quindi sottrarre un giorno.

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

Dopo aver eseguito questo codice nextNotifTime verrà impostato sull'ultimo giorno del mese corrente. Tieni presente che se oggi è l'ultimo giorno del mese l'effetto netto di questo codice è che l'oggetto Calendar rimane invariato.


17

Di seguito fornirà sempre risultati corretti:

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

Perché è necessario Potresti dirmelo :)
Frank Fang,

1
Sì, i test hanno fallito per questo motivo esatto sopra. Il problema è che, a meno che non sia impostato DAY_OF_MONTH, l'impostazione predefinita sarà corrente.
ppearcy,

7

Utilizzando l'ultima java.timelibreria qui è la soluzione migliore:

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

In alternativa, puoi fare:

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


2

Guarda il getActualMaximum(int field)metodo dell'oggetto Calendar.

Se imposti l'oggetto Calendar in modo che sia nel mese per il quale stai cercando l'ultima data, getActualMaximum(Calendar.DAY_OF_MONTH)ti darà l'ultimo giorno.


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

Implementazione dell'estensione della data di Kotlin utilizzando 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
}

Puoi chiamare la toEndOfMonthfunzione su ogni oggetto Date comeDate().toEndOfMonth()


4
Queste classi terribili sono state soppiantate anni fa dalle moderne classi java.time con l'adozione di JSR 310. Suggerire queste classi legacy nel 2019 è un cattivo consiglio.
Basil Bourque,

Non è un cattivo consiglio. Il moderno java.time è disponibile per Android solo per API 26+. Dipendiamo ancora da java.util. * Quando supportiamo (non così) vecchi dispositivi.
Rafael Chagas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.