Numero di giorni tra due date in Joda-Time

Come faccio a trovare la differenza in Giorni tra due istanze DateTime Joda-Time ? Con “differenza di giorni” intendo se l’inizio è lunedì e la fine è martedì, mi aspetto un valore di ritorno pari a 1 indipendentemente dalle ore / minuti / secondi delle date di inizio e fine.

Days.daysBetween(start, end).getDays() mi dà 0 se start è di sera e termina al mattino.

Ho anche lo stesso problema con gli altri campi data, quindi speravo che ci sarebbe stato un modo generico per “ignorare” i campi di minore importanza.

In altre parole, i mesi tra febbraio e il 4 marzo sarebbero anche 1, così come lo sarebbero le ore tra le 14:45 e le 15:12. Tuttavia la differenza di ora tra le 14:01 e le 14:55 sarebbe 0.

Fastidiosamente, la risposta withTimeAtStartOfDay è sbagliata, ma solo occasionalmente. Tu vuoi:

 Days.daysBetween(start.toLocalDate(), end.toLocalDate()).getDays() 

Si scopre che “mezzanotte / inizio giornata” significa talvolta 1am (l’ora legale si verifica in questo modo in alcuni punti), che Days.daysBetween non gestisce correttamente.

 // 5am on the 20th to 1pm on the 21st, October 2013, Brazil DateTimeZone BRAZIL = DateTimeZone.forID("America/Sao_Paulo"); DateTime start = new DateTime(2013, 10, 20, 5, 0, 0, BRAZIL); DateTime end = new DateTime(2013, 10, 21, 13, 0, 0, BRAZIL); System.out.println(daysBetween(start.withTimeAtStartOfDay(), end.withTimeAtStartOfDay()).getDays()); // prints 0 System.out.println(daysBetween(start.toLocalDate(), end.toLocalDate()).getDays()); // prints 1 

Passare tramite un LocalDate l’intero problema.

Days lezione

L’utilizzo della class Days con il metodo withTimeAtStartOfDay dovrebbe funzionare:

 Days.daysBetween(start.withTimeAtStartOfDay() , end.withTimeAtStartOfDay() ).getDays() 

puoi utilizzare LocalDate :

 Days.daysBetween(new LocalDate(start), new LocalDate(end)).getDays() 

tl; dr

 java.time.temporal.ChronoUnit.DAYS.between( earlier.truncatedTo( ChronoUnit.DAYS ) , later.truncatedTo( ChronoUnit.DAYS ) ) 

…o…

 java.time.temporal.ChronoUnit.HOURS.between( earlier.truncatedTo( ChronoUnit.HOURS ) , later.truncatedTo( ChronoUnit.HOURS ) ) 

java.time

Cordiali saluti, il progetto Joda-Time è ora in modalità di manutenzione , con il team che consiglia la migrazione alle classi java.time .

L’equivalente di Joda-Time DateTime è ZonedDateTime .

 ZoneId z = ZoneId.of( "Pacific/Auckland" ) ; ZonedDateTime now = ZonedDateTime.now( z ) ; 

A quanto pare, vuoi contare i giorni per data, nel senso che vuoi ignorare l’ora del giorno. Ad esempio, l’avvio di un minuto prima di mezzanotte e la conclusione di un minuto dopo la mezzanotte dovrebbe comportare un singolo giorno. Per questo comportamento, estrai un LocalDate dal tuo ZonedDateTime . La class LocalDate rappresenta un valore di sola data senza ora del giorno e senza fuso orario.

 LocalDate localDateStart = zdtStart.toLocalDate() ; LocalDate localDateStop = zdtStop.toLocalDate() ; 

Usa l’ ChronoUnit per calcolare i giorni trascorsi o altre unità.

 long days = ChronoUnit.DAYS.between( localDateStart , localDateStop ) ; 

Troncare

Per quanto riguarda la possibilità di fare un conteggio più generale in cui si è interessati al delta di ore come ore del giorno anziché a ore complete come span-of-time di sessanta minuti, utilizzare il metodo truncatedTo .

Ecco il tuo esempio di 14:45 alle 15:12 dello stesso giorno.

 ZoneId z = ZoneId.of( "America/Montreal" ); ZonedDateTime start = ZonedDateTime.of( 2017 , 1 , 17 , 14 , 45 , 0 , 0 , z ); ZonedDateTime stop = ZonedDateTime.of( 2017 , 1 , 17 , 15 , 12 , 0 , 0 , z ); long hours = ChronoUnit.HOURS.between( start.truncatedTo( ChronoUnit.HOURS ) , stop.truncatedTo( ChronoUnit.HOURS ) ); 

1

Per un conteggio di giorni per data, troncare su ChronoUnit.DAYS . Ecco un esempio che va oltre la mezzanotte da cinque minuti prima a cinque minuti dopo, per i giorni trascorsi di 1 .

 ZoneId z = ZoneId.of( "America/Montreal" ); ZonedDateTime start = ZonedDateTime.of( 2017 , 1 , 17 , 23 , 55 , 0 , 0 , z ); ZonedDateTime stop = ZonedDateTime.of( 2017 , 1 , 18 , 00 , 05 , 0 , 0 , z ); long days = ChronoUnit.DAYS.between( start.truncatedTo( ChronoUnit.DAYS ) , stop.truncatedTo( ChronoUnit.DAYS ) ); 

1


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 .

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 .

La risposta accettata crea due oggetti LocalDate , che sono piuttosto costosi se si stanno leggendo molti dati. Io uso questo:

  public static int getDaysBetween(DateTime earlier, DateTime later) { return (int) TimeUnit.MILLISECONDS.toDays(later.getMillis()- earlier.getMillis()); } 

Chiamando getMillis() si utilizzano variabili già esistenti.
MILLISECONDS.toDays() quindi, utilizza un semplice calcolo aritmetico, non crea alcun object.

 public static int getDifferenceIndays(long timestamp1, long timestamp2) { final int SECONDS = 60; final int MINUTES = 60; final int HOURS = 24; final int MILLIES = 1000; long temp; if (timestamp1 < timestamp2) { temp = timestamp1; timestamp1 = timestamp2; timestamp2 = temp; } Calendar startDate = Calendar.getInstance(TimeZone.getDefault()); Calendar endDate = Calendar.getInstance(TimeZone.getDefault()); endDate.setTimeInMillis(timestamp1); startDate.setTimeInMillis(timestamp2); if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) { int day1 = endDate.get(Calendar.DAY_OF_MONTH); int day2 = startDate.get(Calendar.DAY_OF_MONTH); if (day1 == day2) { return 0; } else { return 1; } } int diffDays = 0; startDate.add(Calendar.DAY_OF_MONTH, diffDays); while (startDate.before(endDate)) { startDate.add(Calendar.DAY_OF_MONTH, 1); diffDays++; } return diffDays; }