Différence de jours entre deux dates en Java?

j'ai besoin de trouver la nombre de jours entre deux dates : l'un est à partir d'un rapport et un est la date actuelle. Mon extrait de:

  int age=calculateDifference(agingDate, today);

ici calculateDifference est une méthode privée, agingDate et today sont des objets Date , juste pour votre clarification. J'ai suivi deux articles d'un forum Java, Thread 1 / Thread 2 .

Il fonctionne très bien dans un programme autonome bien que lorsque je l'inclus dans ma logique de lire à partir du rapport, je reçois une différence inhabituelle dans les valeurs.

pourquoi cela se produit - il et comment puis-je le réparer?

EDIT:

je reçois un plus grand nombre de jours par rapport à la quantité réelle de jours.

public static int calculateDifference(Date a, Date b)
{
    int tempDifference = 0;
    int difference = 0;
    Calendar earlier = Calendar.getInstance();
    Calendar later = Calendar.getInstance();

    if (a.compareTo(b) < 0)
    {
        earlier.setTime(a);
        later.setTime(b);
    }
    else
    {
        earlier.setTime(b);
        later.setTime(a);
    }

    while (earlier.get(Calendar.YEAR) != later.get(Calendar.YEAR))
    {
        tempDifference = 365 * (later.get(Calendar.YEAR) - earlier.get(Calendar.YEAR));
        difference += tempDifference;

        earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    if (earlier.get(Calendar.DAY_OF_YEAR) != later.get(Calendar.DAY_OF_YEAR))
    {
        tempDifference = later.get(Calendar.DAY_OF_YEAR) - earlier.get(Calendar.DAY_OF_YEAR);
        difference += tempDifference;

        earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    return difference;
}

Note:

malheureusement, aucune des réponses m'a aidé à résoudre le problème. J'ai accompli ce problème avec l'aide de Joda-time bibliothèque.

79
demandé sur Community 2010-07-21 17:53:59

20 réponses

je vous suggérerais d'utiliser l'excellente bibliothèque Joda Time à la place du java défectueux.util.Date et amis. Vous pouvez simplement écrire

import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.Days;

Date past = new Date(110, 5, 20); // June 20th, 2010
Date today = new Date(110, 6, 24); // July 24th 
int days = Days.daysBetween(new DateTime(past), new DateTime(today)).getDays(); // => 34
147
répondu Adam Schmideg 2014-08-20 10:48:07

il est peut-être trop tard pour me joindre au jeu, mais qu'est-ce qui se passe? :)

pensez-vous qu'il s'agit d'un problème de threading? Comment utilisez-vous la sortie de cette méthode, par exemple? Ou

Peut-on changer votre code pour faire quelque chose d'aussi simple que:

Calendar calendar1 = Calendar.getInstance();
    Calendar calendar2 = Calendar.getInstance();
    calendar1.set(<your earlier date>);
    calendar2.set(<your current date>);
    long milliseconds1 = calendar1.getTimeInMillis();
    long milliseconds2 = calendar2.getTimeInMillis();
    long diff = milliseconds2 - milliseconds1;
    long diffSeconds = diff / 1000;
    long diffMinutes = diff / (60 * 1000);
    long diffHours = diff / (60 * 60 * 1000);
    long diffDays = diff / (24 * 60 * 60 * 1000);
    System.out.println("\nThe Date Different Example");
    System.out.println("Time in milliseconds: " + diff
 + " milliseconds.");
    System.out.println("Time in seconds: " + diffSeconds
 + " seconds.");
    System.out.println("Time in minutes: " + diffMinutes 
+ " minutes.");
    System.out.println("Time in hours: " + diffHours 
+ " hours.");
    System.out.println("Time in days: " + diffDays 
+ " days.");
  }
48
répondu Suji 2010-07-29 16:47:26

la différence / (24 * etc) ne prend pas en compte le fuseau horaire, donc si votre fuseau horaire par défaut contient un DST, il peut annuler le calcul.

Ce lien a une jolie petite mise en œuvre.

Voici la source du lien ci-dessus au cas où le lien descend:

/** Using Calendar - THE CORRECT WAY**/  
public static long daysBetween(Calendar startDate, Calendar endDate) {  
  //assert: startDate must be before endDate  
  Calendar date = (Calendar) startDate.clone();  
  long daysBetween = 0;  
  while (date.before(endDate)) {  
    date.add(Calendar.DAY_OF_MONTH, 1);  
    daysBetween++;  
  }  
  return daysBetween;  
}  

et

/** Using Calendar - THE CORRECT (& Faster) WAY**/  
public static long daysBetween(final Calendar startDate, final Calendar endDate)
{
  //assert: startDate must be before endDate  
  int MILLIS_IN_DAY = 1000 * 60 * 60 * 24;  
  long endInstant = endDate.getTimeInMillis();  
  int presumedDays = 
    (int) ((endInstant - startDate.getTimeInMillis()) / MILLIS_IN_DAY);  
  Calendar cursor = (Calendar) startDate.clone();  
  cursor.add(Calendar.DAY_OF_YEAR, presumedDays);  
  long instant = cursor.getTimeInMillis();  
  if (instant == endInstant)  
    return presumedDays;

  final int step = instant < endInstant ? 1 : -1;  
  do {  
    cursor.add(Calendar.DAY_OF_MONTH, step);  
    presumedDays += step;  
  } while (cursor.getTimeInMillis() != endInstant);  
  return presumedDays;  
}
23
répondu Mad_troll 2013-04-23 18:55:44

de java.temps

en Java 8 et plus tard, utilisez le java.cadre de temps ( Tutoriel ).

Duration

la classe Duration représente un intervalle de temps en nombre de secondes plus une fraction de seconde. Il peut compter les jours, les heures, les minutes et les secondes.

ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10);
Duration duration = Duration.between(oldDate, now);
System.out.println(duration.toDays());

ChronoUnit

si tout ce que vous avez besoin est le nombre de jours, vous pouvez également utiliser le ChronoUnit enum . Notez que les méthodes de calcul renvoient un long au lieu de int .

long days = ChronoUnit.DAYS.between( then, now );
15
répondu Vitalii Fedorenko 2016-06-14 15:38:38

Cela dépend de ce que vous définissez comme la différence. Pour comparer deux dates à minuit, vous pouvez le faire.

long day1 = ...; // in milliseconds.
long day2 = ...; // in milliseconds.
long days = (day2 - day1) / 86400000;
13
répondu Peter Lawrey 2010-07-29 19:10:07
import java.util.Calendar;
import java.util.Date;

public class Main {
    public static long calculateDays(String startDate, String endDate)
    {
        Date sDate = new Date(startDate);
        Date eDate = new Date(endDate);
        Calendar cal3 = Calendar.getInstance();
        cal3.setTime(sDate);
        Calendar cal4 = Calendar.getInstance();
        cal4.setTime(eDate);
        return daysBetween(cal3, cal4);
    }

    public static void main(String[] args) {
        System.out.println(calculateDays("2012/03/31", "2012/06/17"));

    }

    /** Using Calendar - THE CORRECT WAY**/
    public static long daysBetween(Calendar startDate, Calendar endDate) {
        Calendar date = (Calendar) startDate.clone();
        long daysBetween = 0;
        while (date.before(endDate)) {
            date.add(Calendar.DAY_OF_MONTH, 1);
            daysBetween++;
        }
        return daysBetween;
    }
}
13
répondu Soumyarup Dasgupta 2012-09-27 05:26:54

Solution utilisant la différence entre le temps millisecondes, avec arrondissement correct pour les dates D'heure D'été:

public static long daysDiff(Date from, Date to) {
    return daysDiff(from.getTime(), to.getTime());
}

public static long daysDiff(long from, long to) {
    return Math.round( (to - from) / 86400000D ); // 1000 * 60 * 60 * 24
}

Une remarque: bien sûr, les dates doivent être dans une certaine fuseau horaire.

le code important:

Math.round( (to - from) / 86400000D )

Si vous ne voulez pas rond, vous pouvez utiliser dates UTC,

9
répondu angelcervera 2013-03-02 09:58:07

Illustration du problème: (mon code calcule delta en semaines, mais la même question s'applique avec delta en jours)

Voici une mise en œuvre très raisonnable:

public static final long MILLIS_PER_WEEK = 7L * 24L * 60L * 60L * 1000L;

static public int getDeltaInWeeks(Date latterDate, Date earlierDate) {
    long deltaInMillis = latterDate.getTime() - earlierDate.getTime();
    int deltaInWeeks = (int)(deltaInMillis / MILLIS_PER_WEEK);
    return deltaInWeeks; 
}

mais ce test échouera:

public void testGetDeltaInWeeks() {
    delta = AggregatedData.getDeltaInWeeks(dateMar09, dateFeb23);
    assertEquals("weeks between Feb23 and Mar09", 2, delta);
}

la raison est:

Lun Mar 09 00:00:00 HAE 2009 = 1,236,571,200,000

Lun Feb 23 00:00:00 EST 2009 = 1,235,365,200,000

MillisPerWeek = 604,800,000

Thus,

(Mar09 - Feb23) / MillisPerWeek =

1,206,000,000 / 604,800,000 = 1.994...

mais quiconque regarde un calendrier serait d'accord que la réponse est 2.

4
répondu KennethB 2012-08-20 10:26:04

j'utilise cette fonction:

DATEDIFF("31/01/2016", "01/03/2016") // me return 30 days

ma fonction:

import java.util.Date;

public long DATEDIFF(String date1, String date2) {
        long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000;
        long days = 0l;
        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy"); // "dd/MM/yyyy HH:mm:ss");

        Date dateIni = null;
        Date dateFin = null;        
        try {       
            dateIni = (Date) format.parse(date1);
            dateFin = (Date) format.parse(date2);
            days = (dateFin.getTime() - dateIni.getTime())/MILLISECS_PER_DAY;                        
        } catch (Exception e) {  e.printStackTrace();  }   

        return days; 
     }
3
répondu cesin 2013-05-24 18:09:10

Regardez de la getFragmentInDays méthodes dans cet apache commons-lang classe DateUtils .

2
répondu ccpizza 2013-03-25 16:30:50

basé sur la réponse de @Mad_Troll, j'ai développé cette méthode.

j'ai couru environ 30 cas de test contre elle, est la seule méthode qui traite correctement des fragments de temps de sous-journée.

exemple: si vous passez maintenant et maintenant + 1 milliseconde qui est encore le même jour. Faire 1-1-13 23:59:59.098 à 1-1-13 23:59:59.099 retourne 0 jours, correctement; allot des autres méthodes postées ici ne fera pas cela correctement.

mérite de noter qu'il ne se soucie pas de quelle façon vous les mettez, si votre date de fin est avant votre date de début, il comptera à l'envers.

/**
 * This is not quick but if only doing a few days backwards/forwards then it is very accurate.
 *
 * @param startDate from
 * @param endDate   to
 * @return day count between the two dates, this can be negative if startDate is after endDate
 */
public static long daysBetween(@NotNull final Calendar startDate, @NotNull final Calendar endDate) {

    //Forwards or backwards?
    final boolean forward = startDate.before(endDate);
    // Which direction are we going
    final int multiplier = forward ? 1 : -1;

    // The date we are going to move.
    final Calendar date = (Calendar) startDate.clone();

    // Result
    long daysBetween = 0;

    // Start at millis (then bump up until we go back a day)
    int fieldAccuracy = 4;
    int field;
    int dayBefore, dayAfter;
    while (forward && date.before(endDate) || !forward && endDate.before(date)) {
        // We start moving slowly if no change then we decrease accuracy.
        switch (fieldAccuracy) {
            case 4:
                field = Calendar.MILLISECOND;
                break;
            case 3:
                field = Calendar.SECOND;
                break;
            case 2:
                field = Calendar.MINUTE;
                break;
            case 1:
                field = Calendar.HOUR_OF_DAY;
                break;
            default:
            case 0:
                field = Calendar.DAY_OF_MONTH;
                break;
        }
        // Get the day before we move the time, Change, then get the day after.
        dayBefore = date.get(Calendar.DAY_OF_MONTH);
        date.add(field, multiplier);
        dayAfter = date.get(Calendar.DAY_OF_MONTH);

        // This shifts lining up the dates, one field at a time.
        if (dayBefore == dayAfter && date.get(field) == endDate.get(field))
            fieldAccuracy--;
        // If day has changed after moving at any accuracy level we bump the day counter.
        if (dayBefore != dayAfter) {
            daysBetween += multiplier;
        }
    }
    return daysBetween;
}

vous pouvez supprimer les annotations @NotNull , celles-ci sont utilisées par Intellij pour faire l'analyse de code à la volée

2
répondu Chris.Jenkins 2013-10-15 11:27:42

vous dites qu'il" fonctionne bien dans un programme autonome, "mais que vous obtenez" des valeurs de différence inhabituelles "quand vous"inclure dans ma logique de lire à partir du rapport". Cela suggère que votre rapport a certaines valeurs pour lesquelles il ne fonctionne pas correctement, et votre programme autonome n'a pas ces valeurs. Au lieu d'un programme autonome, je suggère un cas d'essai. Écrivez un cas de test comme vous le feriez pour un programme autonome, subclassing de la classe TestCase de JUnit. Maintenant, vous pouvez exécuter une très spécifiques par exemple, savoir quelle valeur vous attendez (et ne pas la donner aujourd'hui pour la valeur de test, parce qu'aujourd'hui change avec le temps). Si vous mettez les valeurs que vous avez utilisées dans le programme autonome, vos tests seront probablement réussis. C'est génial - vous voulez que ces affaires continuent de fonctionner. Maintenant, ajoute une valeur de ton rapport, qui ne fonctionne pas correctement. Votre nouveau test échouera probablement. Découvrez pourquoi il échoue, réparez-le et passez au vert (tous les tests réussis). Exécuter votre rapport. Voir ce qui est encore cassé; écrire un test; le faire passer. Bientôt, vous verrez que votre rapport fonctionne.

1
répondu Carl Manaster 2010-07-21 14:03:58

cent lignes de code pour cette fonction de base???

Juste une méthode simple:

protected static int calculateDayDifference(Date dateAfter, Date dateBefore){
    return (int)(dateAfter.getTime()-dateBefore.getTime())/(1000 * 60 * 60 * 24); 
    // MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
}
1
répondu joro 2014-08-12 09:43:14
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;
}
1
répondu user1091978 2014-12-24 17:34:57

ThreeTen-Extra

la réponse de Vitalii Fedorenko est correcte, décrivant comment effectuer ce calcul d'une manière moderne avec java.classes de temps ( Duration & ChronoUnit ) intégré à Java 8 et plus tard (et rétroporté à Java 6 & 7 et à Android ).

Days

si vous utilisez un certain nombre de jours de manière routinière dans votre code, vous pouvez remplacer de simples entiers par l'utilisation d'une classe. La classe Days se trouve dans le projet ThreeTen-Extra , une extension de java.temps et terrain d'essai pour d'éventuelles futures additions à java.temps. Le Days classe fournit un moyen sûr de représenter un nombre de jours de votre demande. La classe comprend pratique constantes pour ZERO et ONE .

étant donné les anciens objets java.util.Date , convertissez-les d'abord en objets modernes java.time.Instant . Les anciennes classes date-heure ont ajouté de nouvelles méthodes pour faciliter la conversion en java.le temps, un tel java.util.Date::toInstant .

Instant start = utilDateStart.toInstant(); // Inclusive.
Instant stop = utilDateStop.toInstant();  // Exclusive.

Pass tous les deux Instant objets à la méthode d'usine pour org.threeten.extra.Days .

dans l'implémentation actuelle (2016-06) ceci est un wrapper appelant java.time.temporal.ChronoUnit.DAYS.between , lisez la classe ChronoUnit doc pour plus de détails. Pour être clair: toute la majuscule DAYS est dans l'enum ChronoUnit tandis que le premier-cap Days est une classe de ThreeTen-Extra.

Days days = Days.between( start , stop );

vous pouvez passer ces Days les objets autour de votre propre code. Vous pouvez sérialiser à une chaîne de caractères dans le format standard ISO 8601 en appelant toString . Ce format de PnD utilise un P pour marquer le début et D signifie" jours", avec un nombre de jours entre les deux. Les deux java.les classes de temps et ThreeTen-Extra utilisent ces formats standards par défaut pour générer et analyser des chaînes représentant des valeurs date-heure.

String output = days.toString();

P3D

Days days = Days.parse( "P3D" );  
1
répondu Basil Bourque 2017-05-23 12:09:17

ce code calcule les jours entre 2 chaînes de date:

    static final long MILLI_SECONDS_IN_A_DAY = 1000 * 60 * 60 * 24;
    static final String DATE_FORMAT = "dd-MM-yyyy";
    public long daysBetween(String fromDateStr, String toDateStr) throws ParseException {
    SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
    Date fromDate;
    Date toDate;
    fromDate = format.parse(fromDateStr);
    toDate = format.parse(toDateStr);
    return (toDate.getTime() - fromDate.getTime()) / MILLI_SECONDS_IN_A_DAY;
}
0
répondu Kayvan Tehrani 2014-08-16 09:45:46

si vous cherchez une solution qui retourne le nombre approprié ou les jours entre par exemple 11/30/2014 23:59 et 12/01/2014 00:01 voici la solution en utilisant Joda Time.

private int getDayDifference(long past, long current) {
    DateTime currentDate = new DateTime(current);
    DateTime pastDate = new DateTime(past);
    return currentDate.getDayOfYear() - pastDate.getDayOfYear();
} 

cette implémentation renverra 1 en jours différents. La plupart des solutions présentées ici calculent la différence en millisecondes entre deux dates. Cela signifie que 0 serait retourné parce qu'il n'y a que 2 minutes de différence entre ces deux dates.

0
répondu tomrozb 2014-12-03 16:02:06

j'ai déjà écrit à ce sujet. Il S'agit d'un report de calculant la différence entre deux instances de date Java .

public int getDiffernceInDays(long timeAfter, long timeBefore) {
    Calendar calendarAfter = Calendar.getInstance();
    calendarAfter.setTime(new Date(timeAfter));

    Calendar calendarNewAfter = Calendar.getInstance();
    calendarNewAfter.set(calendarAfter.get(Calendar.YEAR), calendarAfter.get(Calendar.MONTH), calendarAfter.get(Calendar.DAY_OF_MONTH));

    Calendar calendarBefore = Calendar.getInstance();
    calendarBefore.setTime(new Date(timeBefore));

    Calendar calendarNewBefore = Calendar.getInstance();
    calendarNewBefore.set(calendarBefore.get(Calendar.YEAR), calendarBefore.get(Calendar.MONTH), calendarBefore.get(Calendar.DAY_OF_MONTH));

    return (int) ((calendarNewAfter.getTime().getTime() - calendarNewBefore.getTime().getTime()) / (24 * 60 * 60 * 1000));
}
0
répondu M. S. 2017-05-23 12:09:17

vous devez utiliser la bibliothèque Joda Time Car Java Util Date renvoie parfois des valeurs erronées.

Joda vs Java Util Date

par exemple les jours entre hier (JJ-mm-AAAA, 12-07-2016) et le premier jour de l'année en 1957 (JJ-mm-AAAA, 01-01-1957):

public class Main {

public static void main(String[] args) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date date = null;
    try {
        date = format.parse("12-07-2016");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    //Try with Joda - prints 21742
    System.out.println("This is correct: " + getDaysBetweenDatesWithJodaFromYear1957(date));
    //Try with Java util - prints 21741
    System.out.println("This is not correct: " + getDaysBetweenDatesWithJavaUtilFromYear1957(date));    
}


private static int getDaysBetweenDatesWithJodaFromYear1957(Date date) {
    DateTime jodaDateTime = new DateTime(date);
    DateTimeFormatter formatter = DateTimeFormat.forPattern("dd-MM-yyyy");
    DateTime y1957 = formatter.parseDateTime("01-01-1957");

    return Days.daysBetween(y1957 , jodaDateTime).getDays();
}

private static long getDaysBetweenDatesWithJavaUtilFromYear1957(Date date) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date y1957 = null;
    try {
        y1957 = format.parse("01-01-1957");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return TimeUnit.DAYS.convert(date.getTime() - y1957.getTime(), TimeUnit.MILLISECONDS);
}

donc je vous conseille vraiment D'utiliser la bibliothèque Joda Time.

0
répondu Šime Tokić 2016-07-13 19:30:02

Je l'ai fait comme ça. c'est facile :)

Date d1 = jDateChooserFrom.getDate();
Date d2 = jDateChooserTo.getDate();

Calendar day1 = Calendar.getInstance();
day1.setTime(d1);

Calendar day2 = Calendar.getInstance();
day2.setTime(d2);

int from = day1.get(Calendar.DAY_OF_YEAR);
int to = day2.get(Calendar.DAY_OF_YEAR);

int difference = to-from;
-6
répondu Dayadra Lakmal 2013-10-08 03:28:18