Quel est ce format de date? 2011-08-12T20: 17: 46.384Z


385

J'ai la date suivante: 2011-08-12T20:17:46.384Z. De quel format s'agit-il? J'essaie de l'analyser avec Java 1.4 via DateFormat.getDateInstance().parse(dateStr)et je reçois

java.text.ParseException: Date non comparable: "2011-08-12T20: 17: 46.384Z"

Je pense que je devrais utiliser SimpleDateFormat pour l'analyse, mais je dois d'abord connaître la chaîne de format. Tout ce que j'ai pour le moment, c'est yyyy-MM-ddparce que je ne sais pas ce que Tsignifie cette chaîne - quelque chose de fuseau horaire? Cette chaîne de date provient de la lcmis:downloadedOnbalise affichée sur le type de support de l'historique des téléchargements CMIS Fichiers .



3
@TomaszNurkiewicz, ce n'est pas le cas. ISO8601 n'a pas le Z à la fin.
t1gor

5
La biche ISO8601 autorise un Z à la fin. Voir le lien ci-dessus, recherchez UTC.
Jonathan Rosenne

2
@ t1gor Le Zà la fin est l'abréviation de Zuluet signifie UTC . Ce format certainement est une partie de la norme ISO 8601 collection des formats de texte date-heure standard. Par ailleurs, ces formats standard sont utilisés par défaut dans les classes java.time .
Basil Bourque

3
Pour info, les anciennes classes de date-heure gênantes telles que java.util.Date, java.util.Calendaret java.text.SimpleDateFormatsont désormais héritées , supplantées par les classes java.time intégrées à Java 8 et Java 9. Voir Tutorial by Oracle .
Basil Bourque

Réponses:


513

Le T est juste un littéral pour séparer la date de l'heure, et le Z signifie "décalage horaire zéro" également connu comme "heure zoulou" (UTC). Si vos chaînes ont toujours un "Z", vous pouvez utiliser:

SimpleDateFormat format = new SimpleDateFormat(
    "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));

Ou en utilisant Joda Time , vous pouvez utiliser ISODateTimeFormat.dateTime().


7
Pourquoi avons-nous besoin des guillemets simples autour Tet Z?
Maroun

7
@MarounMaroun: Fondamentalement, nous voulons ces caractères littéraux . Cela peut ne pas être nécessaire pour T(je ne me souviens pas comment SimpleDateFormat gère les spécificateurs inconnus) mais pour Znous voulons que ce soit le caractère 'Z' plutôt que "une valeur de décalage UTC" (par exemple "00").
Jon Skeet

2
@nyedidikeke: Dans la page Wikipédia à laquelle vous êtes lié, il montre "fuseau horaire zoulou" pour UTC. Je ne sais pas ce que vous pensez corriger.
Jon Skeet

9
@JonSkeet: cela peut générer un débat inutile; ne contestant pas votre réponse mais destiné à attirer l'attention du Z qui a obtenu sa lettre initiale de "décalage UTC zéro". La lettre Z est appelée "zoulou" dans l' alphabet phonétique de l' OTAN . À son tour, l'approche militaire pour se référer au décalage zéro UTC est ancrée sur la lettre Z qu'ils identifient comme Zulu, ce qui lui vaut leur nom codé: fuseau horaire Zulu. Il est important de noter que le Z n'a pas perdu son sens et qu'il est toujours le désignateur de zone pour le décalage UTC zéro car le fuseau horaire Zulu (de Z) est simplement un langage codé hérité pour s'y référer.
nyedidikeke

2
@nyedidikeke: Je ne suis toujours pas d'accord pour savoir si quelqu'un d'autre se souciera jamais de la distinction en référence à ma réponse, mais je l'ai mise à jour. Je ne vais pas entrer dans tous les détails cependant, car l'histoire est largement sans rapport avec la réponse.
Jon Skeet

86

tl; dr

Le format ISO 8601 standard est utilisé par votre chaîne d'entrée.

Instant.parse ( "2011-08-12T20:17:46.384Z" ) 

ISO 8601

Ce format est défini par la norme pratique sensible ISO 8601 .

Le Tsépare la partie date de la partie heure. L' Zextrémité signifie UTC (c'est-à-dire un décalage par rapport à UTC de zéro heure-minute-seconde). Le Zse prononce «zoulou» .

java.time

Les anciennes classes de date-heure regroupées avec les premières versions de Java se sont avérées mal conçues, déroutantes et gênantes. Évite-les.

Utilisez plutôt le framework java.time intégré à Java 8 et versions ultérieures. Les classes java.time supplantent à la fois les anciennes classes date-heure et la bibliothèque Joda-Time très réussie.

Les classes java.time utilisent ISO 8601 par défaut lors de l'analyse / génération de représentations textuelles de valeurs date-heure.

La Instantclasse représente un moment sur la timeline en UTC avec une résolution de nanosecondes . Cette classe peut analyser directement votre chaîne d'entrée sans se soucier de définir un modèle de formatage.

Instant instant = Instant.parse ( "2011-08-12T20:17:46.384Z" ) ;

Tableau des types de date-heure en Java, à la fois modernes et hérités


À propos de java.time

Le framework java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciens gênants hérités des classes date-heure tels que java.util.Date, Calendar, et SimpleDateFormat.

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

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

Où obtenir les classes java.time?

  • Java SE 8 , Java SE 9 et versions ultérieures
    • Intégré.
    • Une partie de l'API Java standard avec une implémentation groupée.
    • Java 9 ajoute quelques fonctionnalités et correctifs mineurs.
  • Java SE 6 et Java SE 7
    • Une grande partie de la fonctionnalité java.time est rétroportée vers Java 6 et 7 dans ThreeTen-Backport .
  • Android

Tableau de la bibliothèque java.time à utiliser avec quelle version de Java ou Android

Le projet ThreeTen-Extra étend java.time avec des classes supplémentaires. Ce projet est un terrain d'essai pour de futurs ajouts possibles à java.time. Vous trouverez peut - être des classes utiles ici, comme Interval, YearWeek, YearQuarteret plus .


3
@star Le «zoulou» vient de la tradition militaire et aéronautique où 25 lettres de l'alphabet AZ (pas de «J»), chaque lettre ayant un nom prononçable, représentent leur version des fuseaux horaires . La zone "Zulu" est à zéro heure de décalage par rapport à UTC. Voir ceci et cela .
Basil Bourque

27

Pas sûr de l'analyse Java, mais c'est ISO8601: http://en.wikipedia.org/wiki/ISO_8601


Est-ce "2016-01-27T17: 44: 55UTC", ISO8601 aussi?
user1997292

Je ne le crois pas. Il est proche mais UTC en tant que suffixe n'est pas autorisé. Il doit être Z ou un décalage de fuseau horaire, par exemple +0100. Z et UTC ont la même signification, cependant, donc changer l' UTC en Z donnerait une ISO 8601. valide
smparkes

9

Il existe d'autres façons de l'analyser plutôt que la première réponse. Pour l'analyser:

(1) Si vous souhaitez récupérer des informations sur la date et l'heure, vous pouvez l'analyser vers un objet ZonedDatetime(depuis Java 8 ) ou Date(ancien):

// ZonedDateTime's default format requires a zone ID(like [Australia/Sydney]) in the end.
// Here, we provide a format which can parse the string correctly.
DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;
ZonedDateTime zdt = ZonedDateTime.parse("2011-08-12T20:17:46.384Z", dtf);

ou

// 'T' is a literal.
// 'X' is ISO Zone Offset[like +01, -08]; For UTC, it is interpreted as 'Z'(Zero) literal.
String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX";

// since no built-in format, we provides pattern directly.
DateFormat df = new SimpleDateFormat(pattern);

Date myDate = df.parse("2011-08-12T20:17:46.384Z");

(2) Si vous ne vous souciez pas de la date et de l'heure et que vous souhaitez simplement traiter les informations comme un instant en nanosecondes, vous pouvez utiliser Instant:

// The ISO format without zone ID is Instant's default.
// There is no need to pass any format.
Instant ins = Instant.parse("2011-08-12T20:17:46.384Z");

1

Si vous cherchez une solution pour Android, vous pouvez utiliser le code suivant pour obtenir les secondes de l'époque à partir de la chaîne d'horodatage.

public static long timestampToEpochSeconds(String srcTimestamp) {
    long epoch = 0;

    try {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            Instant instant = Instant.parse(srcTimestamp);
            epoch = instant.getEpochSecond();
        } else {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSS'Z'", Locale.getDefault());
            sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
            Date date = sdf.parse(srcTimestamp);
            if (date != null) {
                epoch = date.getTime() / 1000;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    return epoch;
}

Exemple d'entrée: 2019-10-15T05: 51: 31.537979Z

Exemple de sortie: 1571128673


0

Vous pouvez utiliser l'exemple suivant.

    String date = "2011-08-12T20:17:46.384Z";

    String inputPattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    String outputPattern = "yyyy-MM-dd HH:mm:ss";

    LocalDateTime inputDate = null;
    String outputDate = null;


    DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(inputPattern, Locale.ENGLISH);
    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(outputPattern, Locale.ENGLISH);

    inputDate = LocalDateTime.parse(date, inputFormatter);
    outputDate = outputFormatter.format(inputDate);

    System.out.println("inputDate: " + inputDate);
    System.out.println("outputDate: " + outputDate);

Vous ne devriez pas mettre des apostrophes autour du Z. Cela signifie attendre mais ignorer cette lettre. Mais cette lettre ne doit pas être ignorée. Cette lettre fournit des informations précieuses, le fait que la chaîne était destinée à UTC, un décalage de zéro. Votre format ignore ce fait important. De plus, il n'est même pas nécessaire de prendre la peine de définir ce modèle de formatage. Un formateur pour ce modèle est intégré.
Basil Bourque

-1

Cette technique traduit java.util.Date au format UTC (ou tout autre) et vice-versa.

Définissez une classe comme ceci:

import java.util.Date;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class UtcUtility {

public static DateTimeFormatter UTC = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZoneUTC();


public static Date parse(DateTimeFormatter dateTimeFormatter, String date) {
    return dateTimeFormatter.parseDateTime(date).toDate();
}

public static String format(DateTimeFormatter dateTimeFormatter, Date date) {
    return format(dateTimeFormatter, date.getTime());
}

private static String format(DateTimeFormatter dateTimeFormatter, long timeInMillis) {
    DateTime dateTime = new DateTime(timeInMillis);
    String formattedString = dateTimeFormatter.print(dateTime);
    return formattedString;
}

}

Ensuite, utilisez-le comme ceci:

Date date = format(UTC, "2020-04-19T00:30:07.000Z")

ou

String date = parse(UTC, new Date())

Vous pouvez également définir d'autres formats de date si vous le souhaitez (pas seulement UTC)


Les deux java.util.Dateet le Joda-Time projet ont été supplanté il y a quelques années par les modernes java.time classes définies dans JSR 310. Le conseil est dépassée depuis longtemps.
Basil Bourque

java.time a été introduit dans Java 8. Cette question fait spécifiquement référence à Java 1.4 et j'ai donc délibérément évité d'utiliser les classes les plus récentes. Cette solution répond aux anciennes bases de code. Je suppose que l'auteur pourrait déplacer sa base de code vers Java 8, mais ce n'est pas toujours simple, efficace ou nécessaire.
Gapmeister66

-1

@ John-Skeet m'a donné l'indice pour résoudre mon propre problème. En tant que jeune programmeur, ce petit problème est facile à manquer et difficile à diagnostiquer. Donc je le partage dans l'espoir qu'il aidera quelqu'un.

Mon problème était que je voulais analyser la chaîne suivante contenant un horodatage d'un JSON sur lequel je n'ai aucune influence et le mettre dans des variables plus utiles. Mais j'ai continué à recevoir des erreurs.

Donc, étant donné ce qui suit (faites attention au paramètre de chaîne à l'intérieur de Pattern ();

String str = "20190927T182730.000Z"

LocalDateTime fin;
fin = LocalDateTime.parse( str, DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss.SSSZ") );

Erreur:

Exception in thread "main" java.time.format.DateTimeParseException: Text 
'20190927T182730.000Z' could not be parsed at index 19

Le problème? Le Z à la fin du motif doit être entouré de «Z» tout comme le «T». Changez "yyyyMMdd'T'HHmmss.SSSZ"en "yyyyMMdd'T'HHmmss.SSS'Z'"et ça marche.

La suppression totale du Z du motif a également entraîné des erreurs.

Franchement, je m'attendrais à ce qu'une classe Java ait anticipé cela.


1
Cela a déjà été demandé et répondu ici et ici . Et votre solution est fausse. Tandis que Test un littéral et doit être cité, Zest un décalage (de zéro) et doit être analysé en tant que tel, sinon vous obtiendrez des résultats erronés. Je ne sais pas ce que vous voulez dire par anticipation, je crois que oui.
Ole VV

1
Non, non, non, n'ignore pas le Z. Vous jetez des informations précieuses. Traiter une valeur date-heure tout en ignorant le fuseau horaire ou le décalage par rapport à l'UTC, c'est comme traiter une somme d'argent tout en ignorant la devise!
Basil Bourque

1
Le Tsépare simplement la partie date de la partie heure et n'ajoute aucune signification. D' Zautre part, cela ajoute définitivement du sens.
Basil Bourque

Ole, merci pour les liens. Je vais certainement les lire. Et j'accepte que je puisse certainement me tromper en tant que jeune. Tout ce que je dis, c'est qu'envelopper le Z entre guillemets simples comme un caractère dans le motif a résolu l'erreur. Ma critique est que celui qui a conçu une partie "modèle" de la classe aurait pu coder autour de la présence ou de l'absence de "Z" (ou d'un fuseau horaire différent?) Et de "T" enrobés dans "" ou non. Parce qu'ils n'étaient pas uniques. Le format avec lequel je traite provient de JSON à partir d'une API commerciale analysée dans une chaîne. Mais je dois analyser tout cela dans le calendrier date-heure, etc. pour les rendre plus utiles.
spencemw
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.