web-dev-qa-db-fra.com

Compatibilité ZonedDateTime toString avec ISO 8601

J'essaie de m'assurer que l'appel de toString() sur mon ZonedDateTime Object sera conforme au format ISO-8601.

La documentation de la méthode toString() indique:

... La sortie est compatible avec ISO-8601 si le décalage et l'ID sont les même

Cela signifie-t-il qu'il existe une situation où appeler zdt.getOffset() Renverra quelque chose de différent de zdt.getZone().getRules().getOffset(zdt.toInstant())?

Cela ne semble pas avoir de sens.

Quelqu'un peut-il fournir un exemple dans lequel le décalage et l'ID ne sont pas identiques (c'est-à-dire: où toString() n'est pas conforme à ISO-8601) afin que je puisse mieux comprendre la description dans la documentation.

Je vous remercie.

11
theyuv

Ceci est la spécification complète:

 * Outputs this date-time as a {@code String}, such as
 * {@code 2007-12-03T10:15:30+01:00[Europe/Paris]}.
 * <p>
 * The format consists of the {@code LocalDateTime} followed by the {@code ZoneOffset}.
 * If the {@code ZoneId} is not the same as the offset, then the ID is output.
 * The output is compatible with ISO-8601 if the offset and ID are the same.

La spécification Javadoc fait référence au cas où la variable ZonedDateTime est construite avec une variable ZoneOffset au lieu d'une ZoneId nommée, ainsi, où offset et ID sont identiques

System.out.println(ZonedDateTime.now(ZoneId.of("Europe/Paris")));
// 2017-04-26T15:13:12.006+02:00[Europe/Paris]

System.out.println(ZonedDateTime.now(ZoneOffset.ofHours(2)));
// 2017-04-26T15:13:12.016+02:00

Comme on peut le constater, dans le deuxième cas, où ZoneOffset est utilisé, le format toString() omet la section entre crochets à la fin. En omettant cette section, le résultat est compatible ISO-8601.

boolean iso8601Compatible = zdt.getZone() instanceof ZoneOffset;

Pour garantir une sortie compatible ISO-8601, utilisez toOffsetDateTime():

String isoCompatible = zdt.toOffsetDateTime().toString();

ou un formateur.

20
JodaStephen

L'exemple dans la documentation est 2007-12-03T10:15:30+01:00[Europe/Paris]. Cela ne correspond pas à la conformité ISO car ISO-8601 n'inclut pas la partie [Europe/Paris]. Ceci a été ajouté par les développeurs de Java.time dans un compromis entre se rapprocher de la norme autant que raisonnable et fournir toujours les informations de fuseau horaire de manière non ambiguë.

La vraie question peut donc en fait être le contraire: si ZonedDateTime.toString() inclut les informations de fuseau horaire que l’ISO n’inclut pas, lorsque est le résultat est entièrement conforme à la norme ISO? Que signifie «si le décalage et l'ID sont identiques»? Nous devons ici nous rappeler que ZoneOffset est une sous-classe de ZoneID et peut être utilisée comme ID de zone dans ZonedDateTime. Dans ce cas, le décalage et l'ID sont les mêmes. Sinon, ils ne le sont pas. Pour un exemple spécifique, ZonedDateTime.now(ZoneOffset.ofHours(+2)).toString() peut produire 2017-04-26T15:04:59.828+02:00. Ceci est entièrement compatible ISO car la zone est donnée simplement +02:00, ce qui correspond au décalage. De plus, ZonedDateTime.now(ZoneOffset.UTC).toString() donne quelque chose au format 2017-04-26T13:04:59.828Z. Comme Z compte comme un décalage, cela est également compatible.

Je pense que dans la plupart des cas, cela ne sera pas très utile. Si votre zone n’est qu’un décalage, vous préféreriez généralement utiliser OffsetDateTime plutôt que ZonedDateTime et, dans l’affirmative, vous ne voudrez pas savoir si ZonedDateTime.toString() est compatible ISO ou non.

3
Ole V.V.

J'aime le dernier commentaire de JodaStephen 'ou un formateur' , car le formateur est plus robuste indépendamment des données . La raison en est OffsetDateTime toString () ignorer la deuxième partie d'unité lorsqu'il n'y a pas de valeur pour la deuxième unité et au-dessous. , il finit donc par donner aaaa-MM-jjTHTH: mmZ au lieu de aaaa-MM-jjTHH: mm: ssZ. Cela peut poser problème si un autre système attend un format statique et n’a aucune adaptabilité.

Vous trouverez ci-dessous le code que j'ai utilisé pour simuler les deux cas où il n'y a pas de portion de temps et qui en possède.

/**
 * This function is design to convert Date object from other system to ISO dateTime String 
 * which will be sent to another system. and using formatter to lock up the format
 * @param date Java.util.Date
 * @return 'yyyy-MM-ddTHH:mm:ssZ' format ISO dateTime string
 */
public String formatIsoUtcDateTime(Date date) {
    if(null == date) {
        return null;
    }
    return ZonedDateTime.ofInstant(date.toInstant(), ZoneId.of("UTC"))
                        .format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'"));
}

// no time portion with using formatter
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Date date = sdf.parse("20171010");
System.out.println(formatIsoUtcDateTime(date));

// no time portion with using OffsetDateTime toString
System.out.println(ZonedDateTime.ofInstant(date.toInstant(), ZoneId.of("UTC")).toOffsetDateTime().toString());

// just current date and probably has at least millisecond, using formatter
System.out.println(formatIsoUtcDateTime(new Date()));

// just current date and probably has at least millisecond, using OffsetDateTime toString
// this will print yyyy-MM-ddTHH:mm:ss.SSSZ format
System.out.println(ZonedDateTime.ofInstant(new Date().toInstant(), ZoneId.of("UTC")).toOffsetDateTime().toString());
0
Steve Park

Selon la documentation officielle:

Obtenir le décalage pour un instant est simple, car il existe exactement un décalage valide pour chaque instant . En revanche, obtenir le décalage pour une date/heure locale n’est pas simple. Il y a trois cas:

  • Normal, avec un décalage valide. Dans la grande majorité de l'année, le cas normal est celui où il existe un seul décalage valide pour la date et l'heure locales.
  • Écart, avec zéro décalage valide. C’est à ce moment que les horloges font un bond en avant en raison du changement d’hiver du printemps, qui passe de l’été à l’été. Dans un intervalle, il existe des valeurs de date et heure locales sans décalage valide.
  • Chevauchement, avec deux décalages valides. C’est à ce moment-là que les horloges sont généralement retardées en raison du passage de l’été à l’hiver de l’été à l’automne. Dans un chevauchement, il existe des valeurs date-heure locales avec deux décalages valides.

Ainsi, les 2e et 3e cas sont les cas où toString () ne sera pas conforme à ISO-8601.

0
VivekRatanSinha