J'essaie de nettoyer un mélange de divers codes autour de la gestion datetime pour seulement Java 8 Java.time
espace de noms. En ce moment, j'ai un petit problème avec la valeur par défaut DateTimeFormatter
pour Instant
. Le DateTimeFormatter.ISO_INSTANT
le formateur affiche uniquement les millisecondes quand elles ne sont pas égales à zéro.
L'époque est représentée par 1970-01-01T00:00:00Z
au lieu de 1970-01-01T00:00:00.000Z
.
J'ai fait un test unitaire pour expliquer le problème et comment nous devons comparer les dates finales les unes aux autres.
@Test
public void Java8Date() {
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
String Epoch, almostEpoch, afterEpoch;
{ // before Epoch
Java.time.Instant instant = Java.time.Instant.ofEpochMilli(-1);
almostEpoch = formatter.format(instant);
assertEquals("1969-12-31T23:59:59.999Z", almostEpoch );
}
{ // Epoch
Java.time.Instant instant = Java.time.Instant.ofEpochMilli(0);
Epoch = formatter.format(instant);
// This fails, I get 1970-01-01T00:00:00Z instead
assertEquals("1970-01-01T00:00:00.000Z", Epoch );
}
{ // after Epoch
Java.time.Instant instant = Java.time.Instant.ofEpochMilli(1);
afterEpoch = formatter.format(instant);
assertEquals("1970-01-01T00:00:00.001Z", afterEpoch );
}
// The end game is to make sure this rule is respected (this is how we order things in dynamo):
assertTrue(Epoch.compareTo(almostEpoch) > 0);
assertTrue(afterEpoch.compareTo(Epoch) > 0); // <-- This assert would also fail if the second assert fails
{ // to confirm we're not showing nanos
assertEquals("1970-01-01T00:00:00.000Z", formatter.format(Instant.Epoch.plusNanos(1)));
assertEquals("1970-01-01T00:00:00.001Z", formatter.format(Instant.Epoch.plusNanos(1000000)));
}
}
OK, j'ai regardé le code source et c'est assez simple:
DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendInstant(3).toFormatter();
J'espère que cela fonctionne pour tous les scénarios et qu'il peut aider quelqu'un d'autre. N'hésitez pas à ajouter une réponse meilleure/plus propre.
Juste pour expliquer d'où ça vient, dans le code du JDK ,
ISO_INSTANT
est défini comme ceci:
public static final DateTimeFormatter ISO_INSTANT;
static {
ISO_INSTANT = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendInstant()
.toFormatter(ResolverStyle.STRICT, null);
}
Et DateTimeFormatterBuilder::appendInstant
est déclaré comme:
public DateTimeFormatterBuilder appendInstant() {
appendInternal(new InstantPrinterParser(-2));
return this;
}
Et la signature du constructeur InstantPrinterParser
est:
InstantPrinterParser(int fractionalDigits)
--- Réponse acceptée par Florent est correcte et bonne.
Je veux juste ajouter quelques éclaircissements.
Le formateur mentionné, DateTimeFormatter.ISO_INSTANT , est par défaut uniquement pour la classe Instant
. D'autres classes telles que OffsetDateTime
et ZonedDateTime
peuvent utiliser d'autres formateurs par défaut.
Les classes Java.time offrent une résolution jusqu'à nanoseconde , une granularité beaucoup plus fine que millisecondes . Cela signifie jusqu'à 9 chiffres dans la fraction décimale plutôt que simplement 3 chiffres.
Le comportement de DateTimeFormatter.ISO_INSTANT
varie en fonction du nombre de chiffres dans la fraction décimale. Comme le dit le doc (soulignement le mien):
Lors du formatage, la seconde est toujours sortie. La nano-seconde génère zéro, trois, six ou neuf chiffres selon les besoins.
Ainsi, selon la valeur de données contenue dans l'objet Instant
, vous pouvez voir l'une de ces sorties:
2011-12-03T10: 15: 30Z
2011-12-03T10: 15: 30.100Z
2011-12-03T10: 15: 30.120Z
2011-12-03T10: 15: 30.123Z
2011-12-03T10: 15: 30.123400Z
2011-12-03T10: 15: 30.123456Z
2011-12-03T10: 15: 30.123456780Z
2011-12-03T10: 15: 30.123456789Z
La classe Instant
est censée être le bloc de construction de base de Java.time. Utilisez-le fréquemment pour le passage de données, le stockage de données et l'échange de données. Lors de la génération de représentations String des données à présenter aux utilisateurs, utilisez OffsetDateTime
ou ZonedDateTime
.