tl; dr
LocalDate // Represents an entire day, without time-of-day and without time zone.
.now( // Capture the current date.
ZoneId.of( "Asia/Tokyo" ) // Returns a `ZoneId` object.
) // Returns a `LocalDate` object.
.atStartOfDay( // Determines the first moment of the day as seen on that date in that time zone. Not all days start at 00:00!
ZoneId.of( "Asia/Tokyo" )
) // Returns a `ZonedDateTime` object.
Début de la journée
Obtenez la longueur totale de la journée d'aujourd'hui dans un fuseau horaire.
En utilisant l'approche semi-ouverte, où le début est inclusif tandis que la fin est exclusive . Cette approche résout la faille dans votre code qui ne tient pas compte de la toute dernière seconde de la journée.
ZoneId zoneId = ZoneId.of( "Africa/Tunis" ) ;
LocalDate today = LocalDate.now( zoneId ) ;
ZonedDateTime zdtStart = today.atStartOfDay( zoneId ) ;
ZonedDateTime zdtStop = today.plusDays( 1 ).atStartOfDay( zoneId ) ;
zdtStart.toString () = 2020-01-30T00: 00 + 01: 00 [Afrique / Tunis]
zdtStop.toString () = 2020-01-31T00: 00 + 01: 00 [Afrique / Tunis]
Voir les mêmes moments en UTC.
Instant start = zdtStart.toInstant() ;
Instant stop = zdtStop.toInstant() ;
start.toString () = 2020-01-29T23: 00: 00Z
stop.toString () = 2020-01-30T23: 00: 00Z
Si vous voulez que la journée entière d'une date soit vue en UTC plutôt que dans un fuseau horaire, utilisez OffsetDateTime
.
LocalDate today = LocalDate.now( ZoneOffset.UTC ) ;
OffsetDateTime odtStart = today.atTime( OffsetTime.MIN ) ;
OffsetDateTime odtStop = today.plusDays( 1 ).atTime( OffsetTime.MIN ) ;
odtStart.toString () = 2020-01-30T00: 00 + 18: 00
odtStop.toString () = 2020-01-31T00: 00 + 18: 00
Ces OffsetDateTime
objets seront déjà en UTC, mais vous pouvez appeler toInstant
si vous avez besoin de tels objets qui sont toujours en UTC par définition.
Instant start = odtStart.toInstant() ;
Instant stop = odtStop.toInstant() ;
start.toString () = 2020-01-29T06: 00: 00Z
stop.toString () = 2020-01-30T06: 00: 00Z
Astuce: Vous pouvez être intéressé par l'ajout de la bibliothèque ThreeTen-Extra à votre projet pour utiliser sa Interval
classe pour représenter cette paire d' Instant
objets. Cette catégorie offre des méthodes utiles aux fins de comparaison tels que abuts
, overlaps
, contains
et plus encore.
Interval interval = Interval.of( start , stop ) ;
interval.toString () = 2020-01-29T06: 00: 00Z / 2020-01-30T06: 00: 00Z
À moitié ouvert
La réponse de mprivat est correcte. Son point est de ne pas essayer d'obtenir la fin d'une journée, mais plutôt de comparer à "avant le début du lendemain". Son idée est connue sous le nom d'approche «semi-ouverte» où une période de temps a un début inclusif tandis que la fin est exclusive .
- Les frameworks date-heure actuels de Java (java.util.Date/Calendar et Joda-Time ) utilisent tous les deux 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 avez écrit en forçant le décompte des millisecondes du dernier moment de la journée serait incorrect s'il passait aux nouvelles classes.
- La comparaison des données d'autres sources devient erronée si elles utilisent d'autres résolutions. Par exemple, les bibliothèques Unix utilisent généralement des secondes entières et les bases de données telles que Postgres résolvent la date-heure en microsecondes.
- Certains changements d'heure d'été se produisent pendant minuit, ce qui peut encore compliquer les choses.
Joda-Time 2.3 offre une méthode à cet effet, pour obtenir très premier moment de la journée: withTimeAtStartOfDay()
. De même dans java.time, LocalDate::atStartOfDay
.
Recherchez dans StackOverflow "joda semi-ouvert" pour voir plus de discussions et d'exemples.
Voir cet article, les intervalles de temps et autres plages devraient être à moitié ouverts , par Bill Schneider.
Évitez les anciennes classes date-heure
Les classes java.util.Date et .Calendar sont notoirement gênantes. Évite-les.
Utilisez les classes java.time . Le framework java.time est le successeur officiel du très réussi Joda-Time bibliothèque .
java.time
Le framework java.time est intégré à Java 8 et versions ultérieures. Rétroporté vers Java 6 et 7 dans le projet ThreeTen-Backport , ensuite adapté à Android dans le ThreeTenABP projet .
An Instant
est un moment sur la chronologie en UTC avec une résolution de nanosecondes .
Instant instant = Instant.now();
Appliquer 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, parcourez la LocalDate
classe et sonatStartOfDay
méthode.
ZonedDateTime zdtStart = zdt.toLocalDate().atStartOfDay( zoneId );
En utilisant l'approche semi-ouverte, obtenez le premier moment du jour suivant.
ZonedDateTime zdtTomorrowStart = zdtStart.plusDays( 1 );
Actuellement, le framework java.time n'a pas de Interval
classe 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 futurs ajouts à java.time. Parmi ses classes est Interval
. Construisez un Interval
en passant une paire d' Instant
objets. Nous pouvons extraire un Instant
de nos ZonedDateTime
objets.
Interval today = Interval.of( zdtStart.toInstant() , zdtTomorrowStart.toInstant() );
À propos de java.time
Le framework java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciens gênants hérités des classes date-heure tels que java.util.Date
, Calendar
, et SimpleDateFormat
.
Pour en savoir plus, consultez le didacticiel Oracle . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .
Le projet Joda-Time , désormais en mode maintenance , conseille la migration vers les classes java.time .
Vous pouvez échanger des objets java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou version ultérieure. Pas besoin de chaînes, pas besoin de java.sql.*
classes. Prise en charge d'Hibernate 5 et JPA 2.2 java.time .
Où obtenir les classes java.time?
Joda-Time
MISE À JOUR: 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 un laps de temps de diverses manières: Interval
, Period
et Duration
. An 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 withTimeAtStartOfDay
plutôt que de définir l'heure de la journée sur des zéros. En raison de l'heure d'été et d'autres anomalies, le premier moment de la journée peut ne pas être00: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 le devez, vous pouvez le convertir en java.util.Date.
java.util.Date date = todayStart.toDate();