Come sottrarre X giorni da una data usando il calendario Java?

Qualcuno sa un modo semplice utilizzando il calendario Java per sottrarre X giorni da una data?

Non sono stato in grado di trovare alcuna funzione che mi permetta di sottrarre direttamente X giorni da una data in Java. Qualcuno può indicarmi la giusta direzione?

Tratto dai documenti qui :

Aggiunge o sottrae la quantità di tempo specificata al campo calendario specificato, in base alle regole del calendario. Ad esempio, per sottrarre 5 giorni dall’ora corrente del calendario, puoi ottenerlo chiamando:

 Calendar calendar = Calendar.getInstance(); // this would default to now calendar.add(Calendar.DAY_OF_MONTH, -5). 

Potresti usare il metodo add e passargli un numero negativo. Tuttavia, potresti anche scrivere un metodo più semplice che non usa la class Calendar come la seguente

 public static void addDays(Date d, int days) { d.setTime( d.getTime() + (long)days*1000*60*60*24 ); } 

Ciò ottiene il valore di timestamp della data (millisecondi dall’epoca) e aggiunge il numero corretto di millisecondi. È ansible passare un numero intero negativo per il parametro days per eseguire la sottrazione. Questo sarebbe più semplice della soluzione di calendario “corretta”:

 public static void addDays(Date d, int days) { Calendar c = Calendar.getInstance(); c.setTime(d); c.add(Calendar.DATE, days); d.setTime( c.getTime().getTime() ); } 

Si noti che entrambe queste soluzioni modificano l’object Date passato come parametro anziché restituire una Date completamente nuova. Entrambe le funzioni potrebbero essere facilmente modificate per farlo nell’altro modo, se lo si desidera.

La risposta di Anson funzionerà bene per il caso semplice, ma se hai intenzione di fare calcoli di date più complessi ti consiglio di controllare Joda Time . Renderà la tua vita molto più facile.

FYI in Joda Time che potresti fare

 DateTime dt = new DateTime(); DateTime fiveDaysEarlier = dt.minusDays(5); 

tl; dr

 LocalDate.now().minusDays( 10 ) 

Meglio specificare il fuso orario.

 LocalDate.now( ZoneId.of( "America/Montreal" ) ).minusDays( 10 ) 

Dettagli

Le vecchie classi data-ora in bundle con le prime versioni di Java, come java.util.Date / .Calendar , si sono dimostrate problematiche, confuse e imperfette. Evitalo.

java.time

Java 8 e versioni successive sostituiscono quelle vecchie classi con il nuovo framework java.time. Vedi Tutorial . Definito da JSR 310 , ispirato a Joda-Time e ampliato dal progetto ThreeTen-Extra . Il progetto ThreeTen-Backport esegue il back-ports delle classi su Java 6 e 7; il progetto ThreeTenABP ad Android.

La domanda è vaga, non chiara se richiede una data o una data.

LocalDate

Per una data solo, senza orario, utilizzare la class LocalDate . Si noti che un fuso orario è cruciale nel determinare una data come “oggi”.

 LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) ); LocalDate tenDaysAgo = today.minusDays( 10 ); 

ZonedDateTime

Se intendevi una data, quindi utilizza la class Instant per ottenere un momento sulla timeline in UTC . Da lì, regola il fuso orario per ottenere un object ZonedDateTime .

 Instant now = Instant.now(); // UTC. ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId ); ZonedDateTime tenDaysAgo = zdt.minusDays( 10 ); 

A proposito di java.time

Il framework java.time è integrato in Java 8 e versioni successive. Queste classi soppiantano le fastidiose vecchie lezioni di data e ora come java.util.Date , Calendar e SimpleDateFormat .

Il progetto Joda-Time , ora in modalità di manutenzione , consiglia la migrazione alle classi java.time .

Per saperne di più, consultare l’ esercitazione Oracle . E cerca Stack Overflow per molti esempi e spiegazioni. La specifica è JSR 310 .

È ansible scambiare oggetti java.time direttamente con il proprio database. Utilizzare un driver JDBC compatibile con JDBC 4.2 o successivo. Nessuna necessità di stringhe, nessuna necessità per le classi java.sql.* .

Dove ottenere le classi java.time?

  • Java SE 8 , Java SE 9 , Java SE 10 e versioni successive
    • Built-in.
    • Parte dell’API Java standard con un’implementazione in bundle.
    • Java 9 aggiunge alcune funzionalità e correzioni minori.
  • Java SE 6 e Java SE 7
    • Gran parte della funzionalità java.time è back-porting su Java 6 e 7 in ThreeTen-Backport .
  • android
    • Versioni successive di implementazioni di bundle Android delle classi java.time.
    • Per Android precedente (<26), il progetto ThreeTenABP adatta ThreeTen-Backport (menzionato sopra). Vedi Come usare ThreeTenABP ….

Il progetto ThreeTen-Extra estende java.time con classi aggiuntive. Questo progetto è un terreno di prova per possibili aggiunte future a java.time. Puoi trovare alcune classi utili come Interval , YearWeek , YearQuarter e altro .

 int x = -1; Calendar cal = ...; cal.add(Calendar.DATE, x); 

modifica: il parser non sembra gradire il collegamento al Javadoc, quindi qui è in chiaro:

http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#add(int , int)

Invece di scrivere i miei addDays come suggerito da Eli, preferirei usare DateUtils da Apache . È utile soprattutto quando devi utilizzarlo in più punti del tuo progetto.

L’API dice:

addDays(Date date, int amount)

Aggiunge un numero di giorni a una data che restituisce un nuovo object.

Si noti che restituisce un nuovo object Date e non apporta modifiche a quello precedente.

Qualcuno ha raccomandato Joda Time così – ho usato questa class CalendarDate http://calendardate.sourceforge.net

È un progetto in qualche modo in competizione con Joda Time, ma molto più basilare a sole 2 classi. È molto utile e ha funzionato benissimo per ciò di cui avevo bisogno, dal momento che non volevo utilizzare un pacchetto più grande del mio progetto. A differenza delle controparti Java, la sua unità più piccola è il giorno quindi è davvero una data (non averla fino a millisecondi o qualcosa del genere). Una volta creata la data, tutto ciò che fai per sottrarre è qualcosa come myDay.addDays (-5) per tornare indietro di 5 giorni. Puoi usarlo per trovare il giorno della settimana e cose del genere. Un altro esempio:

 CalendarDate someDay = new CalendarDate(2011, 10, 27); CalendarDate someLaterDay = today.addDays(77); 

E:

 //print 4 previous days of the week and today String dayLabel = ""; CalendarDate today = new CalendarDate(TimeZone.getDefault()); CalendarDateFormat cdf = new CalendarDateFormat("EEE");//day of the week like "Mon" CalendarDate currDay = today.addDays(-4); while(!currDay.isAfter(today)) { dayLabel = cdf.format(currDay); if (currDay.equals(today)) dayLabel = "Today";//print "Today" instead of the weekday name System.out.println(dayLabel); currDay = currDay.addDays(1);//go to next day } 

La seconda soluzione di Eli Courtwright è sbagliata, dovrebbe essere:

 Calendar c = Calendar.getInstance(); c.setTime(date); c.add(Calendar.DATE, -days); date.setTime(c.getTime().getTime()); 

Può essere fatto facilmente dal seguente

 Calendar calendar = Calendar.getInstance(); // from current time long curTimeInMills = new Date().getTime(); long timeInMills = curTimeInMills - 5 * (24*60*60*1000); // `enter code here`subtract like 5 days calendar.setTimeInMillis(timeInMills); System.out.println(calendar.getTime()); // from specific time like (08 05 2015) calendar.set(Calendar.DAY_OF_MONTH, 8); calendar.set(Calendar.MONTH, (5-1)); calendar.set(Calendar.YEAR, 2015); timeInMills = calendar.getTimeInMillis() - 5 * (24*60*60*1000); calendar.setTimeInMillis(timeInMills); System.out.println(calendar.getTime());