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.
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.
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.
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());
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:
Ainsi, les 2e et 3e cas sont les cas où toString () ne sera pas conforme à ISO-8601.