Comparer deux java.util.Dates pour voir s’ils sont dans la même journée

Je dois comparer deux Date (par exemple, date1 et date2 ) et obtenir un boolean sameDay qui est vrai pour le partage des deux Date le même jour, et false si ce n’est pas le cas.

Comment puis-je faire ceci? Il semble y avoir un tourbillon de confusion ici … et je voudrais éviter autant que possible d’imposer d’autres dépendances au-delà du JDK.

pour clarifier: si date1 et date2 partagent la même année, le même mois et le même jour, le même sameDay est vrai, sinon il est faux. Je me rends compte que cela nécessite la connaissance d’un fuseau horaire … ce serait bien de passer dans un fuseau horaire, mais je peux vivre avec GMT ou l’heure locale tant que je connais le comportement.

encore une fois, pour clarifier:

 date1 = 2008 Jun 03 12:56:03 date2 = 2008 Jun 03 12:59:44 => sameDate = true date1 = 2009 Jun 03 12:56:03 date2 = 2008 Jun 03 12:59:44 => sameDate = false date1 = 2008 Aug 03 12:00:00 date2 = 2008 Jun 03 12:00:00 => sameDate = false 

 Calendar cal1 = Calendar.getInstance(); Calendar cal2 = Calendar.getInstance(); cal1.setTime(date1); cal2.setTime(date2); boolean sameDay = cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR); 

Notez que “même jour” n’est pas un concept aussi simple que cela puisse paraître lorsque différents fuseaux horaires peuvent être impliqués. Le code ci-dessus pour les deux dates calcule le jour par rapport au fuseau horaire utilisé par l’ordinateur sur lequel il s’exécute. Si ce n’est pas ce dont vous avez besoin, vous devez transmettre le ou les fuseaux horaires pertinents aux appels Calendar.getInstance() , après avoir décidé ce que vous entendez exactement par “le même jour”.

Et oui, LocalDate Joda Time rendrait le tout beaucoup plus propre et plus facile (bien que les mêmes difficultés concernant les fuseaux horaires soient présentes).

Que diriez-vous:

 SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd"); return fmt.format(date1).equals(fmt.format(date2)); 

Vous pouvez également définir le fuseau horaire sur SimpleDateFormat, si nécessaire.

J’utilise le package “apache commons lang” pour ce faire (à savoir org.apache.commons.lang.time.DateUtils)

 boolean samedate = DateUtils.isSameDay(date1, date2); //Takes either Calendar or Date objects 

Vous pouvez éviter les dépendances externes et les performances liées à l’utilisation de Calendrier en calculant le nombre de jours juliens pour chacune des dates, puis en les comparant:

 public static boolean isSameDay(Date date1, Date date2) { // Ssortingp out the time part of each date. long julianDayNumber1 = date1.getTime() / MILLIS_PER_DAY; long julianDayNumber2 = date2.getTime() / MILLIS_PER_DAY; // If they now are equal then it is the same day. return julianDayNumber1 == julianDayNumber2; } 

Joda-Time

En ce qui concerne l’ajout d’une dépendance, j’ai bien peur que java.util.Date & .Calendar soit vraiment si mauvais que la première chose à faire pour tout nouveau projet est d’append la bibliothèque Joda-Time. Dans Java 8, vous pouvez utiliser le nouveau package java.time, inspiré par Joda-Time.

Le kernel de Joda-Time est la classe DateTime . Contrairement à java.util.Date, il comprend son fuseau horaire ( DateTimeZone ). Lors de la conversion depuis juDate, assignez une zone.

 DateTimeZone zone = DateTimeZone.forID( "America/Montreal" ); DateTime dateTimeQuébec = new DateTime( date , zone ); 

LocalDate

Une façon de vérifier si deux dates sont disponibles à la même date consiste à convertir en objects LocalDate .

Cette conversion dépend du fuseau horaire atsortingbué. Pour comparer des objects LocalDate , ils doivent avoir été convertis avec la même zone.

Voici une petite méthode utilitaire.

 static public Boolean sameDate ( DateTime dt1 , DateTime dt2 ) { LocalDate ld1 = new LocalDate( dt1 ); // LocalDate determination depends on the time zone. // So be sure the date-time values are adjusted to the same time zone. LocalDate ld2 = new LocalDate( dt2.withZone( dt1.getZone() ) ); Boolean match = ld1.equals( ld2 ); return match; } 

Mieux serait un autre argument, en spécifiant le fuseau horaire plutôt que de supposer que le premier fuseau horaire de l’object DateTime devrait être utilisé.

 static public Boolean sameDate ( DateTimeZone zone , DateTime dt1 , DateTime dt2 ) { LocalDate ld1 = new LocalDate( dt1.withZone( zone ) ); // LocalDate determination depends on the time zone. // So be sure the date-time values are adjusted to the same time zone. LocalDate ld2 = new LocalDate( dt2.withZone( zone ) ); return ld1.equals( ld2 ); } 

Représentation de chaîne

Une autre approche consiste à créer une représentation sous forme de chaîne de la partie date de chaque date-heure, puis à comparer les chaînes.

Encore une fois, le fuseau horaire atsortingbué est crucial.

 DateTimeFormatter formatter = ISODateTimeFormat.date(); // Static method. Ssortingng s1 = formatter.print( dateTime1 ); Ssortingng s2 = formatter.print( dateTime2.withZone( dt1.getZone() ) ); Boolean match = s1.equals( s2 ); return match; 

Span of Time

La solution généralisée consiste à définir une période de temps, puis à demander si la plage contient votre cible. Cet exemple de code est dans Joda-Time 2.4. Notez que les classes liées à “minuit” sont obsolètes. Utilisez plutôt la méthode withTimeAtStartOfDay . Joda-Time propose trois classes pour représenter une période de temps de différentes manières: Intervalle, Période et Durée.

En utilisant l’approche “Half-Open” où le début de la plage est inclusif et la fin de la période exclusive.

Le fuseau horaire de la cible peut être différent du fuseau horaire de l’intervalle.

 DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" ); DateTime target = new DateTime( 2012, 3, 4, 5, 6, 7, timeZone ); DateTime start = DateTime.now( timeZone ).withTimeAtStartOfDay(); DateTime stop = start.plusDays( 1 ).withTimeAtStartOfDay(); Interval interval = new Interval( start, stop ); boolean containsTarget = interval.contains( target ); 

java.time

Java 8 et les versions ultérieures sont livrées avec le framework java.time . Inspiré par Joda-Time, défini par JSR 310, et étendu par le projet ThreeTen-Extra. Voir le tutoriel .

Les fabricants de Joda-Time nous ont tous demandé de passer à java.time dès que possible. En attendant, Joda-Time continue comme un projet activement maintenu. Mais attendez-vous à ce que les travaux futurs se produisent uniquement dans java.time et ThreeTen-Extra plutôt que dans Joda-Time.

Pour résumer java.time en quelques mots… Un Instant est un moment de la chronologie en UTC. Appliquez un fuseau horaire ( ZoneId ) pour obtenir un object ZonedDateTime . Pour sortir de la chronologie, pour avoir la vague idée indéfinie d’une date-heure, utilisez les classes “locales”: LocalDateTime , LocalDate , LocalTime .

La logique décrite dans la section Joda-Time de cette réponse s’applique à java.time.

L’ancienne classe java.util.Date a une nouvelle méthode toInstant pour la conversion en java.time.

 Instant instant = yourJavaUtilDate.toInstant(); // Convert into java.time type. 

La détermination d’une date nécessite un fuseau horaire.

 ZoneId zoneId = ZoneId.of( "America/Montreal" ); 

Nous appliquons cet object de fuseau horaire à l’ Instant pour obtenir un ZonedDateTime . De là, nous extrayons une valeur de date uniquement (un LocalDate ) car notre objective est de comparer les dates (pas les heures, les minutes, etc.).

 ZonedDateTime zdt1 = ZonedDateTime.ofInstant( instant , zoneId ); LocalDate localDate1 = LocalDate.from( zdt1 ); 

Faites la même chose avec le deuxième object java.util.Date nous avons besoin pour la comparaison. Je vais juste utiliser le moment présent à la place.

 ZonedDateTime zdt2 = ZonedDateTime.now( zoneId ); LocalDate localDate2 = LocalDate.from( zdt2 ); 

Utilisez la méthode spéciale isEqual pour tester la même valeur de date.

 Boolean sameDate = localDate1.isEqual( localDate2 ); 

Convertissez les dates en Java 8 java.time.LocalDate comme vu ici .

 LocalDate localDate1 = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); LocalDate localDate2 = date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); // compare dates assertTrue("Not on the same day", localDate1.equals(localDate2)); 
 private boolean isSameDay(Date date1, Date date2) { Calendar calendar1 = Calendar.getInstance(); calendar1.setTime(date1); Calendar calendar2 = Calendar.getInstance(); calendar2.setTime(date2); boolean sameYear = calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR); boolean sameMonth = calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH); boolean sameDay = calendar1.get(Calendar.DAY_OF_MONTH) == calendar2.get(Calendar.DAY_OF_MONTH); return (sameDay && sameMonth && sameYear); } 

Java 8

Si vous utilisez Java 8 dans votre projet et comparez java.sql.Timestamp , vous pouvez utiliser la classe LocalDate :

 sameDate = date1.toLocalDateTime().toLocalDate().equals(date2.toLocalDateTime().toLocalDate()); 

Si vous utilisez java.util.Date , consultez la réponse d’Istvan qui est moins ambiguë.

POUR LES UTILISATEURS ANDROID:

Vous pouvez utiliser DateUtils.isToday(dateMilliseconds) pour vérifier si la date donnée est le jour actuel ou non.

Référence API: https://developer.android.com/reference/android/text/format/DateUtils.html#isToday(long)

en plus de la solution Binil Thomas

 public static boolean isOnSameDay(Timestamp... dates) { SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd"); Ssortingng date1 = fmt.format(dates[0]); for (Timestamp date : dates) { if (!fmt.format(date).equals(date1)) { return false; } } return true; } 

usage

  isOnSameDay(date1,date2,date3 ...); //or isOnSameDay(mydates); 
 public static boolean validSearchRange(Ssortingng start, Ssortingng end){ SimpleDateFormat dateFormat = new SimpleDateFormat(clientDateFormat); try { Date start_date = dateFormat.parse(start); Date end_date = dateFormat.parse(end); return !start_date.after(end_date); } catch (ParseException e) { e.printStackTrace(); } return false; } 

vous pouvez appliquer la même logique que la solution SimpleDateFormat sans utiliser SimpleDateFormat

 date1.getFullYear()*10000 + date1.getMonth()*100 + date1.getDate() == date2.getFullYear()*10000 + date2.getMonth()*100 + date2.getDate()