Confusion avec l'analyse de l'heure Java UTC


Je suis confondu avec la gestion du temps en temps java. J'ai si longtemps travaillé sous l'hypothèse que si un horodatage est spécifié comme heure zouloue, java s'occuperait du décalage par rapport à l'heure locale.

Pour illustrer. Je suis actuellement en BST qui a un décalage de UTC + 1. Dans cet esprit, je m'attendrais à ce temps zoulou:

2016-09-12T13:15:17.309Z

Être

2016-09-12T14:15:17.309 

LocalDateTime après l'analyse. En effet, mon heure système par défaut est définie sur BST et l'horodatage ci-dessus (heure zouloue) spécifie qu'il s'agit d'une heure UTC.

Considérez plutôt cet exemple:

        String ts = "2016-09-12T13:15:17.309Z";
        LocalDateTime parse = LocalDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME);
        System.out.println(parse);

Ceci imprimera:

2016-09-12T13:15:17.309

Ainsi, l'horodatage, analysé en tant que LocalDateTime, n'est pas reconnu comme heure UTC et traité directement en tant que localtime. J'ai donc pensé que je devais peut-être l'analyser en tant que ZonedDateTime et le convertir en LocalDateTime spécifiquement afin d'obtenir l'heure locale correcte. Avec ce test:

        String ts = "2016-09-12T13:15:17.309Z";
        ZonedDateTime parse = ZonedDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME);
        System.out.println(parse);
        System.out.println(parse.toLocalDateTime());

J'obtiens les sorties:

2016-09-12T13:15:17.309Z
2016-09-12T13:15:17.309

Idem de sortie pour les deux dates.

La seule façon d'analyser correctement ce que j'ai pu trouver est:

    String ts = "2016-09-12T13:15:17.309Z";
    Instant instant = Instant.parse(ts); // parses UTC
    LocalDateTime ofInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    System.out.println(instant);
    System.out.println(ofInstant);

Ceci imprime:

2016-09-12T13:15:17.309Z
2016-09-12T14:15:17.309

Ce qui est correct.

Donc les questions sont:

  • java time ne devrait-il pas reconnaître un horodatage UTC et l'analyser selon la valeur par défaut du système?
  • Comment puis-je utiliser l'approche LocalDateTime#parse pour obtenir le résultat correct?
  • dois-je utiliser Instant pour tout maintenant et jetez l'analyse?

Le problème est que les modules de temps java de jersey/jackson analysent les horodatages en utilisant le format ISO et les méthodes régulières LocalDateTime#parse. Je me suis rendu compte que mon temps n'est pas éteint car ils sont traités comme LocalTime alors qu'en fait ils sont à l'heure zouloue.

Author: pandaadb, 2016-09-12

2 answers

Vous êtes un malentendu le but de LocalDateTime.

Pour citer la documentation de la classe:

Une date-heure sans fuseau horaire dans le système de calendrier ISO-8601, tel que {@code 2007-12-03T10:15:30}.

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

Donc son but explicite est juste de représenter une date et une heure sans un fuseau horaire. C'est porpose est pas pour représenter une date et une heure dans le fuseau horaire local.

Par conséquent, chaque conversion supprime simplement le fuseau horaire.

, Donc pour vos besoins vous avez besoin d'un ZonedDateTime avec ZoneId.systemDefault() comme vous l'avez déjà utilisé dans votre troisième exemple.

Pour votre deuxième exemple, cela pourrait être:

String ts = "2016-09-12T13:15:17.309Z";
ZonedDateTime parse = 
    ZonedDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME)
        .withZoneSameInstant(ZoneId.systemDefault());
System.out.println(parse);
System.out.println(parse.toLocalDateTime());
 6
Author: Michaela Elschner, 2016-10-23 21:47:12

Tl; dr

Exemple:

Instant.parse( "2016-09-12T13:15:17.309Z" )
       .atZone( ZoneId.of( "Europe/London" ) )
       .toString();

2016-09-12T14:15:17.309+01:00[Europe/Londres]

Cours IdeOne.com .

Détails

LaRéponse de Krüske est correcte. Vous comprenez mal la signification de la classe LocalDateTime. Il ne pas représente la date-heure d'une localité particulière. Juste au contraire, il nepas du tout représente un moment réel.

Je suggère de penser à Instant comme votre classe de blocs de construction de base en java.temps. L'Instant la classe représente un moment dans le scénario de UTC, avec une résolution de nanosecondes (jusqu'à neuf (9) chiffres d'une fraction décimale).

Votre chaîne d'entrée est conforme au format ISO 8601 utilisé par défaut dans la classe Instant pour l'analyse et la génération de chaîne représentation. Le Z à la fin est l'abréviation de Zulu et signifie UTC. Pas besoin de spécifier un modèle de mise en forme.

Instant instant = Instant.parse( "2016-09-12T13:15:17.309Z" );

En tant que programmeur, vous devriez apprendre à penser et à travailler en UTC principalement. Oubliez votre propre fuseau horaire. Pensez à UTC comme le Seul Temps vrai. Appliquez un fuseau horaire en tant que variation, et uniquement au besoin.

Spécifier un fuseau horaire nom dans le format continent/region, tels que America/Montreal, Africa/Casablanca, ou Pacific/Auckland. N'utilisez jamais la lettre 3-4 abréviations telles que BST ou EST ou IST car ce ne sont pas de vrais fuseaux horaires, non standardisés et même pas uniques(!). Si par BST vous vouliez dire Heure d'été britannique, alors le nom du fuseau horaire réel serait Europe/London. Java.les classes de temps détermineront comment ajuster pour toutes les anomalies, y compris l'heure d'été (DST).

ZoneId z = ZoneId.of( "Europe/London" );
ZonedDateTime zdt = instant.atZone( z );

À propos de java.temps

Le java.time framework est intégré à Java 8 et versions ultérieures. Ces classes supplantent les gênants vieux - héritage date-heure classes telles que java.util.Date, Calendar, & SimpleDateFormat.

Le projet Joda-Time, maintenant en mode maintenance, conseille la migration vers java.temps.

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

Où obtenir le java.les classes de temps?

  • Java SE 8 et SE 9 et plus tard
    • Intégré.
    • Partie de l'API Java standard avec une implémentation groupée.
    • Java 9 ajoute quelques fonctionnalités et corrections mineures.
  • Java SE 6 et SE 7
    • Une grande partie du java.la fonctionnalité time est back-ported vers Java 6 & 7 dans ThreeTen-Backport.
  • Android

Le projetThreeTen-Extra étend java.temps avec des cours supplémentaires. Ce projet est un terrain d'essai pour de futurs possibles ajouts à java.temps. Vous pouvez trouver quelques classes utiles ici comme Interval, YearWeek, YearQuarter, et plus.

 3
Author: Basil Bourque, 2017-05-23 12:34:17