476 votes

Calcul de la différence entre deux instances de date Java

J'utilise la méthode Java java.util.Date en Scala et que vous souhaitez comparer une classe Date et l'heure actuelle. Je sais que je peux calculer le delta en utilisant getTime() :

(new java.util.Date()).getTime() - oldDate.getTime()

Cependant, cela me laisse juste avec un long représentant les millisecondes. Existe-t-il un moyen plus simple et plus agréable d'obtenir un delta de temps ?

12 votes

Pourquoi pas d'amour pour Joda Time ? C'est à peu près la meilleure option si vous voulez traiter des dates en Java.

9 votes

Veuillez consulter mon élégante solution à 2 lignes, sans utiliser Joda et en donnant le résultat dans n'importe quel TimeUnit à l'adresse suivante stackoverflow.com/a/10650881/82609

0 votes

596voto

Sebastien Lorber Points 9682

Différence simple (sans lib)

/**
 * Get a diff between two dates
 * @param date1 the oldest date
 * @param date2 the newest date
 * @param timeUnit the unit in which you want the diff
 * @return the diff value, in the provided unit
 */
public static long getDateDiff(Date date1, Date date2, TimeUnit timeUnit) {
    long diffInMillies = date2.getTime() - date1.getTime();
    return timeUnit.convert(diffInMillies,TimeUnit.MILLISECONDS);
}

Et ensuite vous pouvez appeler :

getDateDiff(date1,date2,TimeUnit.MINUTES);

pour obtenir la différence entre les deux dates en unités de minutes.

TimeUnit es java.util.concurrent.TimeUnit un enum standard Java allant des nanos aux jours.


Différentiel lisible par l'homme (sans lib)

public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) {

    long diffInMillies = date2.getTime() - date1.getTime();

    //create the list
    List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class));
    Collections.reverse(units);

    //create the result map of TimeUnit and difference
    Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>();
    long milliesRest = diffInMillies;

    for ( TimeUnit unit : units ) {

        //calculate difference in millisecond 
        long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS);
        long diffInMilliesForUnit = unit.toMillis(diff);
        milliesRest = milliesRest - diffInMilliesForUnit;

        //put the result in the map
        result.put(unit,diff);
    }

    return result;
}

http://ideone.com/5dXeu6

Le résultat est quelque chose comme Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0} avec les unités commandées.

Il vous suffit de convertir cette carte en une chaîne de caractères conviviale.


Avertissement

Les extraits de code ci-dessus calculent une simple différence entre 2 instants. Cela peut poser des problèmes lors d'un changement d'heure d'été, comme expliqué dans ce poste . Cela signifie que si vous calculez la différence entre des dates sans heure, il se peut qu'il manque un jour/une heure.

À mon avis, la différence de date est un peu subjective, surtout pour les jours. Vous pouvez :

  • compter le nombre de 24h écoulées : jour+1 - jour = 1 jour = 24h

  • compter le nombre de temps écoulé, en tenant compte de l'heure d'été : jour+1 - jour = 1 = 24h (mais en utilisant l'heure de minuit et l'heure d'été, cela pourrait être 0 jour et 23h)

  • compter le nombre de day switches ce qui signifie que jour+1 13h - jour 11h = 1 jour, même si le temps écoulé n'est que de 2h (ou 1h en cas d'heure d'été :p).

Ma réponse est valable si votre définition de la différence de date sur les jours correspond au 1er cas.

Avec JodaTime

Si vous utilisez JodaTime, vous pouvez obtenir la différence pour 2 dates instantanées (millièmes soutenus ReadableInstant) avec :

Interval interval = new Interval(oldInstant, new Instant());

Mais vous pouvez également obtenir la différence pour les dates/heures locales :

// returns 4 because of the leap year of 366 days
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5), PeriodType.years()).getYears() 

// this time it returns 5
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5+1), PeriodType.years()).getYears() 

// And you can also use these static methods
Years.yearsBetween(LocalDate.now(), LocalDate.now().plusDays(365*5)).getYears()

0 votes

Wow, on peut vraiment apprendre à un vieux chien de nouveaux tours ! Je n'en avais jamais entendu parler auparavant, c'est très utile pour traduire les différences de dates en chaînes de caractères significatives.

0 votes

@SebastienLorber Y a-t-il un moyen dans TimeUnit de calculer la différence ainsi ? "L'alarme est réglée pour 3 jours, 4 heures et 12 minutes à partir de maintenant".

0 votes

Des trucs brillants qui m'ont vraiment fait gagner beaucoup de temps. J'apprécie votre aide.

215voto

notnoop Points 30218

Le JDK Date L'API est horriblement cassée malheureusement. Je recommande d'utiliser Bibliothèque horaire de Joda .

Joda Time a un concept de temps Intervalle :

Interval interval = new Interval(oldTime, new Instant());

EDIT : Au fait, Joda a deux concepts : Interval pour représenter un intervalle de temps entre deux instants de temps (représenter le temps entre 8h et 10h), et une Duration qui représente une durée sans les limites de temps réelles (par exemple, représente deux heures !)

Si vous ne vous intéressez qu'aux comparaisons de temps, la plupart des Date (y compris celle du JDK) implémente Comparable qui vous permet d'utiliser l'interface Comparable.compareTo()

0 votes

Btw - vous voulez dire Comparable.compareTo() pas Comparable.compare() .

0 votes

Joda-Time dispose de trois classes permettant de représenter un laps de temps de différentes manières : Intervalle, Durée, et Période. Cette réponse correcte traite des deux premières. Voir ma réponse pour des informations sur la période.

0 votes

Java 8 a une nouvelle api pour la date et l'heure comme joda.

162voto

Michael Borgwardt Points 181658
int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime()) 
                 / (1000 * 60 * 60 * 24) )

Notez que cela fonctionne avec des dates UTC, la différence peut donc être d'un jour si vous regardez les dates locales. Et pour que cela fonctionne correctement avec les dates locales, il faut adopter une approche complètement différente en raison de l'heure d'été.

6 votes

En fait, cela ne fonctionne pas correctement sous Android. Des erreurs d'arrondi existent. L'exemple du 19 au 21 mai indique 1 jour parce que 1.99 est converti en 1. Utilisez l'arrondi avant de convertir en int.

4 votes

C'est la meilleure et la plus simple des réponses. Lors du calcul de la différence entre deux dates, les fuseaux horaires locaux se soustraient les uns aux autres ... de sorte que la réponse correcte (sous forme de double) est donnée simplement par ((double) (newer.getTime() - older.getTime()) / (86400.0 * 1000.0) ; ... en tant que double, vous avez également la fraction de jour qui peut facilement être convertie en HH:MM:ss.

8 votes

@scottb : le problème avec les dates locales est que vous pouvez avoir l'heure d'été, ce qui signifie que certains jours ont 23 ou 25 heures, ce qui peut fausser le résultat.

54voto

Jon Skeet Points 692016

Vous devez définir votre problème plus clairement. Vous podría il suffit de prendre le nombre de millisecondes entre les deux Date et diviser par le nombre de millisecondes en 24 heures, par exemple ... mais :

  • Cela ne prend pas en compte les fuseaux horaires. Date est toujours en UTC
  • Cela ne tient pas compte de l'heure d'été (où il peut y avoir des jours qui ne durent que 23 heures, par exemple).
  • Même en respectant l'UTC, combien de jours y a-t-il entre le 16 août à 23h et le 18 août à 2h ? Il n'y a que 27 heures, ce qui veut dire un jour ? Ou est-ce que cela devrait être trois jours parce que cela couvre trois dates ?

1 votes

Je pensais que java.util. Date n'était qu'un minuscule emballage autour d'une représentation en millisecondes, interprétée dans le fuseau horaire local (par défaut). L'impression d'une date me donne une représentation du fuseau horaire local. Suis-je confus ?

39voto

Adriano Bacha Points 485
Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();

https://www.joda.org/joda-time/faq.html#datediff

2 votes

Pour info, le Joda-Time Le projet est maintenant en mode de maintenance L'équipe conseille la migration vers le java.time classes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X