Comment obtenir l’heure de début et l’heure de fin d’une journée?

Comment obtenir l’heure de début et l’heure de fin d’une journée?

code comme celui-ci n’est pas précis:

private Date getStartOfDay(Date date) { Calendar calendar = Calendar.getInstance(); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH); int day = calendar.get(Calendar.DATE); calendar.set(year, month, day, 0, 0, 0); return calendar.getTime(); } private Date getEndOfDay(Date date) { Calendar calendar = Calendar.getInstance(); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH); int day = calendar.get(Calendar.DATE); calendar.set(year, month, day, 23, 59, 59); return calendar.getTime(); } 

Ce n’est pas précis à la milliseconde.

À moitié ouvert

La réponse de mprivat est correcte. Son propos est de ne pas essayer d’obtenir la fin d’une journée, mais plutôt de comparer “avant le début de la journée”. Son idée est connue sous le nom d’approche «semi-ouverte» où une période de temps a un début inclusif alors que la fin est exclusive .

  • Les frameworks date-heure actuels sont Java (java.util.Date/Calendar et Joda-Time ), tous deux utilisent des millisecondes de l’ époque . Mais dans Java 8, les nouvelles classes JSR 310 java.time. * Utilisent une résolution en nanosecondes. Tout code que vous écrivez en forçant le nombre de millisecondes du dernier moment du jour serait incorrect si vous passiez aux nouvelles classes.
  • La comparaison des données provenant d’autres sources devient défectueuse si elles utilisent d’autres résolutions. Par exemple, les bibliothèques Unix utilisent généralement des secondes entières, et des bases de données telles que Postgres résolvent la date et l’heure en microsecondes.
  • Certains changements de l’heure d’été surviennent à minuit, ce qui pourrait compliquer davantage les choses.

entrer la description de l'image ici

Joda-Time 2.3 propose à cet effet une méthode, pour obtenir le premier moment de la journée: withTimeAtStartOfDay() . De même dans java.time, LocalDate::atStartOfDay .

Recherchez StackOverflow pour “joda half-open” pour voir plus de discussions et d’exemples.

Voir cet article, Les intervalles de temps et les autres plages doivent être à moitié ouverts , par Bill Schneider.

Éviter les anciennes classes date-heure

Les classes java.util.Date et .Calendar sont notoirement problématiques. Évite-les.

Utilisez soit Joda-Time, soit de préférence java.time . Le framework java.time est le successeur officiel de la très populaire bibliothèque Joda-Time.

java.time

Le framework java.time est intégré à Java 8 et versions ultérieures. Back-porté sur Java 6 & 7 dans le projet ThreeTen-Backport , encore adapté à Android dans le projet ThreeTenABP .

Un Instant est un moment de la chronologie en UTC avec une résolution de nanosecondes .

 Instant instant = Instant.now(); 

Appliquez un fuseau horaire pour obtenir l’ heure de l’horloge murale pour une localité.

 ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId ); 

Pour obtenir le premier moment de la journée, passez par la classe LocalDate et sa méthode atStartOfDay .

 ZonedDateTime zdtStart = zdt.toLocalDate().atStartOfDay( zoneId ); 

En utilisant l’approche demi-ouverte, obtenez le premier moment du jour suivant.

 ZonedDateTime zdtTomorrowStart = zdtStart.plusDays( 1 ); 

Actuellement, l’infrastructure java.time ne possède pas de classe d’ Interval , comme décrit ci-dessous pour Joda-Time. Cependant, le projet ThreeTen-Extra étend java.time avec des classes supplémentaires. Ce projet est le terrain d’essai pour d’éventuels ajouts futurs à java.time. Parmi ses classes est Interval . Construisez un Interval en passant une paire d’objects Instant . Nous pouvons extraire un Instant de nos objects ZonedDateTime .

 Interval today = Interval.of( zdtStart.toInstant() , zdtTomorrowStart.toInstant() ); 

Joda-Time

UPDATE: le projet Joda-Time est maintenant en mode maintenance et conseille la migration vers les classes java.time . Je laisse cette section intacte pour l’histoire.

Joda-Time a trois classes pour représenter une période de temps de différentes manières: Interval , Period et Duration . Un Interval a un début et une fin spécifiques sur la chronologie de l’univers. Cela correspond à notre besoin de représenter “un jour”.

Nous appelons la méthode avec withTimeAtStartOfDay plutôt que de définir l’heure du jour à zéro. En raison de l’heure d’été et d’autres anomalies, le premier moment de la journée peut ne pas être 00:00:00 .

Exemple de code utilisant Joda-Time 2.3.

 DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" ); DateTime now = DateTime.now( timeZone ); DateTime todayStart = now.withTimeAtStartOfDay(); DateTime tomorrowStart = now.plusDays( 1 ).withTimeAtStartOfDay(); Interval today = new Interval( todayStart, tomorrowStart ); 

Si vous devez, vous pouvez convertir en java.util.Date.

 java.util.Date date = todayStart.toDate(); 

Java 8


 public static Date atStartOfDay(Date date) { LocalDateTime localDateTime = dateToLocalDateTime(date); LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN); return localDateTimeToDate(startOfDay); } public static Date atEndOfDay(Date date) { LocalDateTime localDateTime = dateToLocalDateTime(date); LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX); return localDateTimeToDate(endOfDay); } private static LocalDateTime dateToLocalDateTime(Date date) { return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); } private static Date localDateTimeToDate(LocalDateTime localDateTime) { return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); } 

Mise à jour : j’ai ajouté ces 2 méthodes à mes classes d’utilitaires Java ici

  • DateUtils.atStartOfDay
  • DateUtils.atEndOfDay

Il se trouve dans le référentiel central de Maven à:

  com.github.rkumsher utils 1.3  

Java 7 et versions antérieures


Avec Apache Commons

 public static Date atEndOfDay(Date date) { return DateUtils.addMilliseconds(DateUtils.ceiling(date, Calendar.DATE), -1); } public static Date atStartOfDay(Date date) { return DateUtils.truncate(date, Calendar.DATE); } 

Sans Apache Commons

 public Date atEndOfDay(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, 23); calendar.set(Calendar.MINUTE, 59); calendar.set(Calendar.SECOND, 59); calendar.set(Calendar.MILLISECOND, 999); return calendar.getTime(); } public Date atStartOfDay(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); return calendar.getTime(); } 

dans getEndOfDay, vous pouvez append:

 calendar.set(Calendar.MILLISECOND, 999); 

Bien que mathématiquement parlant, vous ne pouvez pas spécifier la fin d’une journée en disant que c’est «avant le début du jour suivant».

Donc, au lieu de dire if(date >= getStartOfDay(today) && date <= getEndOfDay(today)) , vous devriez dire: if(date >= getStartOfDay(today) && date < getStartOfDay(tomorrow)) . C'est une définition beaucoup plus solide (et vous n'avez pas à vous soucier de la précision en milliseconde).

java.time

Utiliser le framework java.time intégré à Java 8.

 import java.time.LocalTime; import java.time.LocalDateTime; LocalDateTime now = LocalDateTime.now(); // 2015-11-19T19:42:19.224 // start of a day now.with(LocalTime.MIN); // 2015-11-19T00:00 now.with(LocalTime.MIDNIGHT); // 2015-11-19T00:00 // end of a day now.with(LocalTime.MAX); // 2015-11-19T23:59:59.999999999 

Pour Java 8, les instructions à une seule ligne suivantes fonctionnent. Dans cet exemple, j’utilise le fuseau horaire UTC. Veuillez envisager de modifier TimeZone que vous utilisez actuellement.

 System.out.println(new Date()); final LocalDateTime endOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MAX); final Date endOfDayAsDate = Date.from(endOfDay.toInstant(ZoneOffset.UTC)); System.out.println(endOfDayAsDate); final LocalDateTime startOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MIN); final Date startOfDayAsDate = Date.from(startOfDay.toInstant(ZoneOffset.UTC)); System.out.println(startOfDayAsDate); 

Si pas de différence de temps avec la sortie. Essayez: ZoneOffset.ofHours(0)

Un moyen supplémentaire de trouver le début de la journée avec java8 java.time.ZonedDateTime au lieu de passer par LocalDateTime est simplement de tronquer l’entrée ZonedDateTime à DAYS:

 zonedDateTimeInstance.truncatedTo( ChronoUnit.DAYS ); 

Une autre solution qui ne dépend d’aucun framework est la suivante:

 static public Date getStartOfADay(Date day) { final long oneDayInMillis = 24 * 60 * 60 * 1000; return new Date(day.getTime() / oneDayInMillis * oneDayInMillis); } static public Date getEndOfADay(Date day) { final long oneDayInMillis = 24 * 60 * 60 * 1000; return new Date((day.getTime() / oneDayInMillis + 1) * oneDayInMillis - 1); } 

Notez qu’il renvoie l’heure UTC

Java 8 ou ThreeTenABP

ZonedDateTime

 ZonedDateTime curDate = ZonedDateTime.now(); public ZonedDateTime startOfDay() { return curDate .toLocalDate() .atStartOfDay() .atZone(curDate.getZone()) .withEarlierOffsetAtOverlap(); } public ZonedDateTime endOfDay() { ZonedDateTime startOfTomorrow = curDate .toLocalDate() .plusDays(1) .atStartOfDay() .atZone(curDate.getZone()) .withEarlierOffsetAtOverlap(); return startOfTomorrow.minusSeconds(1); } // based on https://stackoverflow.com/a/29145886/1658268 

LocalDateTime

 LocalDateTime curDate = LocalDateTime.now(); public LocalDateTime startOfDay() { return curDate.atStartOfDay(); } public LocalDateTime endOfDay() { return startOfTomorrow.atTime(LocalTime.MAX); //23:59:59.999999999; } // based on https://stackoverflow.com/a/36408726/1658268 

J’espère que cela aide quelqu’un.

J’ai essayé ce code et ça marche bien!

 final ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC); final ZonedDateTime startofDay = now.toLocalDate().atStartOfDay(ZoneOffset.UTC); final ZonedDateTime endOfDay = now.toLocalDate().atTime(LocalTime.MAX).atZone(ZoneOffset.UTC); 

En complément de @BasilBourque, répondez:

Une méthode un peu lourde mais sûre pour définir un temps minimum (uniquement pour le début):

 cal.setTime(...); cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY)); cal.set(Calendar.MINUTE, cal.getMinimum(Calendar.MINUTE)); cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND)); cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND)); 

Cela garantit que les valeurs minimales sont celles du calendrier.

 public static Date beginOfDay(Date date) { Calendar cal = Calendar.getInstance(); cal.setTime(date); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return cal.getTime(); } public static Date endOfDay(Date date) { Calendar cal = Calendar.getInstance(); cal.setTime(date); cal.set(Calendar.HOUR_OF_DAY, 23); cal.set(Calendar.MINUTE, 59); cal.set(Calendar.SECOND, 59); cal.set(Calendar.MILLISECOND, 999); return cal.getTime(); } 

J’ai essayé ce code et ça marche bien! :

 Date d= new Date(); GregorianCalendar c = new GregorianCalendar(TimeZone.getTimeZone("UTC")); Ssortingng s_d=d.getYear()+"-"+(d.getMonth()+1)+"-"+d.getDay(); DateFormat dateFormat = DateFormat.getDateInstance(); try { // for the end of day : c.setTime(dateFormat.parse(s_d+" 23:59:59")); // for the start of day: //c.setTime(dateFormat .parse(s_d+" 00:00:00")); } catch (ParseException e) { e.printStackTrace(); }