Comment obtenir l'heure de début et l'heure de fin d'une journée?
un 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.
Réponses:
tl; dr
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.
Voir les mêmes moments en UTC.
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
.Ces
OffsetDateTime
objets seront déjà en UTC, mais vous pouvez appelertoInstant
si vous avez besoin de tels objets qui sont toujours en UTC par définition.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 queabuts
,overlaps
,contains
et plus encore.À 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 .
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 .Appliquer un fuseau horaire pour obtenir l' heure de l'horloge murale pour une localité.
Pour obtenir le premier moment de la journée, parcourez la
LocalDate
classe et sonatStartOfDay
méthode.En utilisant l'approche semi-ouverte, obtenez le premier moment du jour suivant.
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 estInterval
. Construisez unInterval
en passant une paire d'Instant
objets. Nous pouvons extraire unInstant
de nosZonedDateTime
objets.À 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
, etSimpleDateFormat
.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
etDuration
. AnInterval
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.
Si vous le devez, vous pouvez le convertir en java.util.Date.
la source
LocalDateTime
Java 8
Mise à jour : j'ai ajouté ces 2 méthodes à mes classes d'utilitaires Java ici
Il se trouve dans le référentiel central de Maven à:
Java 7 et versions antérieures
Avec Apache Commons
Sans Apache Commons
la source
getStartOfDay
devrait être:LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
Ie LocalTime, pas LocalDateTime.getEndOfDay(Date date)
.getStartOfDay(Date date)
les méthodes de la section Java 8 sont correctes, à savoir LocalDateTime.MAX et .MIN vous placent aux dates les plus précoces possible dans le passé et dans le futur, pas au début et à la fin d'une journée. Au lieu de cela, je suggérerais .atStartOfDay () pour le début et .plusDays (1) .atStartOfDay (). MinusNanos (1) pour la fin.localDateTimeToDate(LocalDateTime startOfDay)
lève une exception - java.lang.IllegalArgumentException: java.lang.ArithmeticException: long overflowdans getEndOfDay, vous pouvez ajouter:
Bien que mathématiquement parlant, vous ne pouvez pas spécifier la fin d'une journée autrement qu'en disant que c'est "avant le début du jour suivant".
Ainsi , 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 à la milliseconde).la source
java.time
Utilisation du
java.time
framework intégré à Java 8.la source
Local…
classes n'ont aucun concept de fuseaux horaires et d'ajustement pour les anomalies. Par exemple, certains fuseaux horaires ont un changement d'heure d'été à minuit, de sorte que le premier moment de la journée est à l'heure01:00:00.0
(1 AM) plutôt qu'à la00:00:00.0
valeur produite par ce code. UtilisezZonedDateTime
plutôt.Un autre moyen de trouver le début de la journée avec java8 java.time.ZonedDateTime au lieu de le parcourir
LocalDateTime
est simplement de tronquer l'entrée ZonedDateTime en DAYS:la source
Pour java 8, les instructions sur une seule ligne suivantes fonctionnent. Dans cet exemple, j'utilise le fuseau horaire UTC. Veuillez envisager de modifier la zone horaire que vous utilisez actuellement.
Si aucun décalage horaire avec la sortie. Essayer:
ZoneOffset.ofHours(0)
la source
toInstant
est une syntaxe illégale et redondante sur le plan conceptuel.Java 8 ou ThreeTenABP
ZonéDateHeure
LocalDateTime
J'espère que cela aide quelqu'un.
la source
J'ai essayé ce code et ça marche bien!
la source
ZonedDateTime
etInstant
à votre disposition, il n'est jamais nécessaire de l'utiliserjava.sql.Timestamp
. Cette classe est l'une des terribles anciennes classes héritées désormais supplantées par les classes java.time . Depuis JDBC 4.2, nous pouvons directement échanger des objets java.time avec la base de données. Votre mélange de l'héritage et des cours modernes n'a aucun sens pour moi.Une autre solution qui ne dépend d'aucun framework est:
Notez qu'il renvoie l'heure UTC
la source
calendar.setTimeInMillis (0); vous donne une précision allant jusqu'à millisecondes
la source
Je sais que c'est un peu tard, mais dans le cas de Java 8, si vous utilisez OffsetDateTime (qui offre de nombreux avantages, tels que TimeZone, Nanosecondes, etc.), vous pouvez utiliser le code suivant:
la source
J'ai eu plusieurs inconvénients avec toutes les solutions car j'avais besoin du type de variable instantanée et le fuseau horaire interférait toujours en changeant tout, puis en combinant les solutions, j'ai vu que c'était une bonne option.
et nous avons en conséquence
J'espère que ça t'aide
la source
Instant
objets. Astuce: vous pourriez être intéressé par l'ajout de la bibliothèque ThreeTen-Extra à votre projet pour utiliser saInterval
classe.Je pense que le plus simple serait quelque chose comme:
Ces millis peuvent ensuite être convertis en Calendar, Instant ou LocalDate selon vos besoins avec Joda Time.
la source
la source