web-dev-qa-db-fra.com

Quelle est la différence entre Instant et LocalDateTime?

Je le sais:

  • Instant est plutôt une représentation "technique" d'horodatage (nanosecondes) pour l'informatique.
  • LocalDateTime est plutôt une représentation date/horloge incluant les fuseaux horaires pour les humains.

Finalement, à la fois, IMO peut être pris comme type pour la plupart des cas d'utilisation d'applications. Par exemple, je suis actuellement en train d'exécuter un travail par lots pour lequel je dois calculer un prochain cycle en fonction de dates et je me bats pour trouver un pour/un contre entre ces deux types (hormis l'avantage de la précision à la nanoseconde d'Instant et du fuseau horaire de LocalDateTime).

Pouvez-vous nommer des exemples d’application, dans lesquels seuls Instant ou LocalDateTime devraient être utilisés?

Edit: Faites attention à la mauvaise interprétation de la documentation pour LocalDateTime concernant la précision et le fuseau horaire

186
manuel aldana

Table of types of date-time class in modern Java.time versus legacy.

tl; dr

Instant et LocalDateTime sont deux animaux totalement différents: l'un représente un moment, l'autre pas.

  • Instant représente un moment, un point spécifique de la chronologie.
  • LocalDateTime représente une date et une heure du jour. Mais en l'absence d'un fuseau horaire ou d'un décalage par rapport à UTC, cette classe ne peut pas représente un moment . Il représente les moments potentiels sur une plage d'environ 26 à 27 heures, soit la plage de tous les fuseaux horaires dans le monde.

Présomption incorrecte

LocalDateTime est plutôt une représentation date/horloge incluant les fuseaux horaires pour les humains.

Votre déclaration est incorrecte: Un LocalDateTime a no fuseau horaire . N'avoir aucun fuseau horaire est le point entier de cette classe.

Pour citer le document de cette classe:

Cette classe ne stocke ni ne représente un fuseau horaire. Au lieu de cela, il s'agit d'une description de la date, telle qu'utilisée pour les anniversaires, combinée à l'heure locale telle qu'elle apparaît sur une horloge murale. Il ne peut pas représenter un instant sur la ligne de temps sans informations supplémentaires telles qu'un décalage ou un fuseau horaire.

Donc, _Local…_ signifie "pas de zonage, pas de décalage".

Instant

enter image description here

Un Instant est un moment sur la ligne de temps de UTC , un compte de nanosecondes depuis l'époque du premier moment de 1970 UTC (voir la classe de doc pour petits détails). Étant donné que la plupart de votre logique métier, de votre stockage de données et de votre échange de données doivent être au format UTC, il s'agit d'une classe pratique à utiliser fréquemment.

_Instant instant = Instant.now() ;  // Capture the current moment in UTC.
_

OffsetDateTime

La classe OffsetDateTime représente un moment en tant que date et heure avec un contexte de quelques heures-minutes-secondes avant ou après UTC. Ce nombre est représenté par la classe ZoneOffset.

Si le nombre d'heures-minutes-secondes est zéro, un OffsetDateTime représente un moment en UTC identique à un Instant.

ZoneOffset

La classe ZoneOffset représente un décalage par rapport à UTC , un nombre d'heures-minutes-secondes d'avance sur UTC ou derrière UTC.

Un ZoneOffset est simplement un nombre, sans le nom et l'historique des modifications trouvées dans un fuseau horaire (ZoneId). Il est donc toujours préférable d’utiliser une zone plutôt qu’un simple décalage.

ZoneId

enter image description here

Un ZoneId est un fuseau horaire .

Un fuseau horaire est un décalage de tant d'heures et de minutes de l'heure UTC, plus d'informations supplémentaires. Un nouveau jour se lève plus tôt dans Paris que dans Montréal , par exemple. Nous devons donc déplacer les aiguilles de l’horloge pour mieux refléter midi (lorsque le soleil est directement au-dessus de la tête) pour une région donnée. Plus le décalage est important vers l'est/l'ouest de la ligne UTC en Europe occidentale/Afrique, plus le décalage est important.

De plus, un fuseau horaire est un ensemble de règles permettant de gérer les ajustements et les anomalies appliqués par une communauté ou une région locale. L'anomalie la plus courante est la folie trop populaire connue sous le nom de Daylight Saving Time (DST) .

Un fuseau horaire contient l'historique des règles passées, des règles actuelles et des règles confirmées dans un proche avenir.

Ces règles changent plus souvent que prévu. Assurez-vous de conserver les règles de votre bibliothèque de date-heure, généralement une copie de la base de données 'tz' , à jour. Rester à jour est plus facile que jamais à l’heure actuelle avec Java 8, Oracle ayant publié un outil de mise à jour Timezone Updater .

Spécifiez un nom de fuseau horaire approprié au format _Continent/Region_, tel que _America/Montreal_, _Africa/Casablanca_ ou _Pacific/Auckland_. N'utilisez jamais les abréviations de 2 à 4 lettres telles que EST ou IST, car elles sont not / vrais fuseaux horaires, non normalisés et même uniques (!).

Fuseau horaire = décalage + règles de réglage

_ZoneId z = ZoneId.of( “Africa/Tunis” ) ; 
_

ZonedDateTime

enter image description here

Pensez ZonedDateTime sur le plan conceptuel en tant que Instant avec un ZoneId assigné.

ZonedDateTime = (Instant + ZoneId)

Pour capturer le moment actuel tel qu'il apparaît dans l'horloge murale utilisée par les habitants d'une région donnée (un fuseau horaire):

_ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Pass a `ZoneId` object such as `ZoneId.of( "Europe/Paris" )`. 
_

La quasi-totalité de votre backend, de votre base de données, de votre logique métier, de votre persistance des données et de votre échange de données devrait être en UTC. Mais pour la présentation aux utilisateurs, vous devez vous adapter à un fuseau horaire attendu par l'utilisateur. C'est le but de la classe ZonedDateTime et des classes formatter utilisées pour générer des représentations sous forme de chaînes de ces valeurs date-heure.

_ZonedDateTime zdt = instant.atZone( z ) ;
String output = zdt.toString() ;                 // Standard ISO 8601 format.
_

Vous pouvez générer du texte au format localisé à l’aide de DateTimeFormatter .

_DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ; 
String outputFormatted = zdt.format( f ) ;
_

mardi 30 avril 2019 à 23 h 22 min 55 s heure de l’Inde

LocalDate, LocalTime, LocalDateTime

Diagram showing only a calendar for a <code>LocalDate</code>.

Diagram showing only a clock for a <code>LocalTime</code>.

Diagram showing a calendar plus clock for a <code>LocalDateTime</code>.

Les classes d'heure de date "locales", LocalDateTime , LocalDate , LocalTime , sont d'un autre type de bestiole. Ils ne sont liés à aucune localité ni à aucun fuseau horaire. Ils ne sont pas liés à la chronologie. Ils n'ont aucune signification réelle jusqu'à ce que vous les appliquiez à une localité pour trouver un point sur la timeline.

Par exemple, "Noël commence à minuit le 25 décembre 2015" est un LocalDateTime. Les coups de minuit se produisent à différents moments à Paris et à Montréal, et à nouveau à Seattle et à Auckland .

_LocalDate ld = LocalDate.of( 2018 , Month.DECEMBER , 25 ) ;
LocalTime lt = LocalTime.MIN ;   // 00:00:00
LocalTime ldt = LocalDateTime.of( ld , lt ) ;  // Xmas morning anywhere. 
_

Un autre exemple, "Acme Company a pour politique de déjeuner à partir de 12h30 PM dans chacune de ses usines dans le monde" est un LocalTime. Pour avoir un sens réel, vous devez l’appliquer à la chronologie pour indiquer le moment de 12h30 à l’usine Stuttgart ou 12h30 à l’usine Rabat ou 12h30 à la Sydney usine.

Le mot "Local" dans ces noms de classe peut être contre-intuitif pour les non-initiés. Le mot signifie any localité, ou every localité, mais not une localité particulière.

Ainsi, pour les applications professionnelles, les types "Local" ne sont pas souvent utilisés car ils représentent simplement l'idée générale d'une date ou d'une heure possible et non d'un moment spécifique sur la timeline. Les applications professionnelles ont tendance à se soucier du moment exact où une facture est arrivée, un produit expédié pour le transport, un employé a été embauché ou le taxi a quitté le garage. Les développeurs d’applications commerciales utilisent donc presque exclusivement Instant et ZonedDateTime.

Rendez-vous de réservation

D'autre part, vous devez utiliser les types _Local…_ pour réserver des événements futurs (ex: rendez-vous chez le dentiste) assez loin dans le futur, où vous risquez que les politiciens redéfinissent le fuseau horaire avec peu d'avertissement, comme ils le font si souvent.

Pour les rendez-vous, stockez un LocalDateTime avec un ZoneId. Plus tard, lors de la génération d'un programme, déterminez un moment à la volée en appelant LocalDateTime::atZone( ZoneId ) pour générer un objet ZonedDateTime.

_ZonedDateTime zdt = ldt.atZone( z ) ;  // Given a date, a time-of-day, and a time zone, determine a moment, a point on the timeline.
_

Si nécessaire, vous pouvez vous adapter à UTC. Extrayez un Instant du ZonedDateTime.

_Instant instant = zdt.toInstant() ;  // Adjust from some zone to UTC. Same moment, same point on the timeline, different wall-clock time.
_

Tous les types date-heure

Par souci d'exhaustivité, voici un tableau de tous les types date-heure possibles, modernes et hérités en Java, ainsi que ceux définis par le standard SQL. Cela pourrait aider à placer les classes Instant & LocalDateTime dans un contexte plus large.

Table of all date-time types in Java (both modern & legacy) as well as SQL standard.

Notez les choix étranges faits par l'équipe Java lors de la conception de JDBC 4.2. Ils ont choisi de prendre en charge tous les Java.time times… à l'exception des deux classes les plus utilisées: Instant & ZonedDateTime.

Mais ne vous inquiétez pas. Nous pouvons facilement convertir en arrière.

Conversion Instant.

_// Storing
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;

// Retrieving
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;
_

Conversion ZonedDateTime.

_// Storing
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ;

// Retrieving
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZone( z ) ; 
_

À propos de Java.time

Le cadre Java.time est intégré à partir de Java 8. Ces classes supplantent les anciennes classes gênantes legacy telles que Java.util.Date , Calendar , & SimpleDateFormat .

Le projet Joda-Time , désormais en mode maintenance , conseille la migration vers les classes Java.time .

Pour en savoir plus, consultez le Oracle Tutorial . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 31 .

Vous pouvez échanger des objets Java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou une version ultérieure. Pas besoin de chaînes, pas besoin de _Java.sql.*_ classes.

Où obtenir les classes Java.time?

Le projet ThreeTen-Extra étend Java.time avec des classes supplémentaires. Ce projet est un terrain d’essai pour d’éventuels ajouts à Java.time. Vous pouvez trouver ici quelques classes utiles telles que Interval , YearWeek , YearQuarter et more .

552
Basil Bourque

Une différence principale est la Local partie de LocalDateTime. Si vous habitez en Allemagne et créez une instance LocalDateTime et que quelqu'un d'autre habite aux États-Unis et en crée une autre au même moment (à condition que les horloges soient correctement définies), la valeur de ces objets sera en réalité différente. Ceci ne s'applique pas à Instant, qui est calculée indépendamment du fuseau horaire.

LocalDateTime stocke la date et l'heure sans fuseau horaire, mais sa valeur initiale dépend du fuseau horaire. Instant n'est pas.

De plus, LocalDateTime fournit des méthodes de manipulation des composants de date tels que les jours, les heures et les mois. Un Instant ne le fait pas.

en dehors de l'avantage de précision en nanosecondes d'Instant et de la partie fuseau horaire de LocalDateTime

Les deux classes ont la même précision. LocalDateTime ne stocke pas le fuseau horaire. Lisez attentivement les javadocs, car vous risquez de vous tromper avec ces hypothèses invalides: Instant et LocalDateTime .

20
Dariusz

Vous vous trompez à propos de LocalDateTime : il ne stocke aucune information de fuseau horaire et sa précision est de la nanoseconde. Citant le Javadoc (mon emphase):

Date-heure sans fuseau horaire dans le système de calendrier ISO-8601 , telle que 2007-12-03T10: 15: 30.

LocalDateTime est un objet date-heure immuable qui représente une date-heure, souvent visualisée sous la forme année-mois-jour-heure-minute-seconde. Vous pouvez également accéder à d'autres champs de date et d'heure, tels que le jour de l'année, le jour de la semaine et la semaine de l'année. Le temps est représenté à la nanoseconde près . Par exemple, la valeur "le 2 octobre 2007 à 13 h 45 min 30 s, 12 h 30 min, peut être stockée dans une heure locale".

La différence entre les deux est que Instant représente un décalage par rapport à l'époque (01-01-1970) et, en tant que tel, représente un instant particulier sur la ligne de temps. Deux objets Instant créés au même moment dans deux endroits différents de la Terre auront exactement la même valeur.

11
Tunaki

Instant correspond au temps sur le méridien d'origine (Greenwich).

Considérant que LocalDateTime par rapport aux paramètres de fuseau horaire du système d’exploitation, et

ne peut pas représenter un instant sans informations supplémentaires telles qu'un décalage ou un fuseau horaire.

1
user2418306