web-dev-qa-db-fra.com

Nombre de jours entre deux dates dans Joda-Time

Comment trouver la différence en jours entre deux Joda-TimeDateTime instances? 1 indépendamment des heures/minutes/secondes des dates de début et de fin.

Days.daysBetween(start, end).getDays() me donne 0 si le début est dans la soirée et se termine le matin.

J'ai également le même problème avec d'autres champs de date, alors j'espérais qu'il y aurait un moyen générique pour «ignorer» les champs de moindre importance. 

En d'autres termes, les mois compris entre février et le 4 mars seraient également 1, de même que les heures comprises entre 14h45 et 15h12. Cependant, la différence d'heure entre 14h01 et 14h55 serait de 0.

303
pvgoddijn

De manière gênante, la réponse withTimeAtStartOfDay est fausse, mais seulement occasionnellement. Tu veux:

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

Il s’avère que "minuit/début de la journée" signifie parfois 1h (l’heure avancée se passe de cette façon à certains endroits), ce que Days.daysBetween ne gère pas correctement.

// 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

Passer par une LocalDate évite toute la question.

358
Alice Purcell

Days Classe

L'utilisation de Days class avec la méthode withTimeAtStartOfDay devrait fonctionner:

Days.daysBetween(start.withTimeAtStartOfDay() , end.withTimeAtStartOfDay() ).getDays() 
183
Michael Borgwardt

vous pouvez utiliser LocalDate :

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

tl; dr

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

…ou…

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

Java.time

Pour votre information, le projet Joda-Time est maintenant en mode maintenance , avec l'équipe conseillant la migration vers les classes Java.time

L'équivalent de Joda-Time DateTime est ZonedDateTime.

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

Apparemment, vous voulez compter les jours par dates, ce qui signifie que vous voulez ignorer l'heure. Par exemple, commencer une minute avant minuit et se terminer une minute après minuit devrait donner lieu à un seul jour. Pour ce comportement, extrayez une LocalDate de votre ZonedDateTime. La classe LocalDate représente une valeur de date uniquement sans heure et sans fuseau horaire.

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

Utilisez l'énumération ChronoUnit pour calculer le nombre de jours écoulés ou d'autres unités.

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

Tronquer

Pour ce qui est de demander une façon plus générale de procéder en comptant, là où vous êtes intéressé, le delta d’heures comme heure de l’heure plutôt que des heures complètes comme une durée de soixante minutes, utilisez la méthode truncatedTo.

Voici votre exemple de 14h45 à 15h12 le même jour.

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

Pour un nombre de jours par dates, tronquez à ChronoUnit.DAYS. Voici un exemple sur minuit allant de cinq minutes avant à cinq minutes après, pendant les jours écoulés de 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


À propos de Java.time

Le cadre Java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciennes classes gênantes héritées _ date-heure telles que Java.util.Date , Calendar _, & SimpleDateFormat .

Le projet Joda-Time , désormais en mode { mode maintenance }, conseille la migration vers les classes Java.time .

Pour en savoir plus, consultez le Oracle Tutorial . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .

Vous pouvez échanger des objets Java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou une version ultérieure. Pas besoin de chaînes, pas besoin de Java.sql.* classes.

Où obtenir les classes Java.time? 

  • Java SE 8 , Java SE 9 , Java SE 10 et versions ultérieures
    • Intégré. 
    • Une partie de l'API Java standard avec une implémentation fournie.
    • Java 9 ajoute quelques fonctionnalités et corrections mineures.
  • Java SE 6 et Java SE 7
    • Une grande partie de la fonctionnalité Java.time est rétroportée vers Java 6 et 7 dans ThreeTen-Backport .
  • Android
    • Les versions ultérieures d'Android regroupent des implémentations des classes Java.time.
    • Pour les anciens Android (<26), le projet ThreeTenABP s’adapte ThreeTen-Backport (mentionné ci-dessus). Voir Comment utiliser ThreeTenABP… .

Le projet ThreeTen-Extra étend Java.time avec des classes supplémentaires. Ce projet est un terrain d'essai pour d'éventuels ajouts à Java.time. Vous pouvez y trouver des classes utiles telles que Interval _, YearWeek , YearQuarter _ et plus _.

Le projet ThreeTen-Extra étend Java.time avec des classes supplémentaires. Ce projet est un terrain d'essai pour d'éventuels ajouts à Java.time. Vous pouvez y trouver des classes utiles telles que Interval _, YearWeek , YearQuarter _ et plus _.

6
Basil Bourque

La réponse acceptée génère deux objets LocalDate, qui sont assez coûteux si vous lisez beaucoup de données . J'utilise ceci:

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

En appelant getMillis(), vous utilisez des variables déjà existantes.
MILLISECONDS.toDays() utilise alors un simple calcul arithmétique, ne crée aucun objet.

2
JBoy

Java.time.Period

Utilisez le Java.time.Period class pour compter les jours .

Puisque Java 8, calculer la différence est plus intuitif en utilisant LocalDate, LocalDateTime pour représenter les deux dates. 

    LocalDate now = LocalDate.now();
    LocalDate inputDate = LocalDate.of(2018, 11, 28);

    Period period = Period.between( inputDate, now);
    int diff = period.getDays();
    System.out.println("diff = " + diff);
1
Azi
DateTime  dt  = new DateTime(laterDate);        

DateTime newDate = dt.minus( new  DateTime ( previousDate ).getMillis());

System.out.println("No of days : " + newDate.getDayOfYear() - 1 );    
0
Arnab Bhui