date de l'analyse syntaxique SimpleDateFormat avec littérale [double] 'Z'
-
24-09-2019 - |
Question
Cette question a déjà une réponse ici:
Je suis en train d'analyser une date qui ressemble à ceci:
2010-04-05T17:16:00Z
Ceci est une date valide par http://www.ietf.org/rfc/rfc3339. txt . Le « Z » littérale « impliquent que UTC est le point de référence préféré pour la durée spécifiée. "
Si je tente de l'analyser en utilisant SimpleDateFormat et ce modèle:
yyyy-MM-dd'T'HH:mm:ss
Il sera analysé comme un LUN. 5 avril 2010 17:16:00 HAE
SimpleDateFormat ne parvient pas à analyser la chaîne avec ces motifs:
yyyy-MM-dd'T'HH:mm:ssz
yyyy-MM-dd'T'HH:mm:ssZ
Je peux définir explicitement le décalage horaire à utiliser sur le SimpleDateFormat pour obtenir le résultat attendu, mais je ne pense pas que cela devrait être nécessaire. Y at-il quelque chose que je suis absent? Y at-il un analyseur de date alternative?
La solution
Dans le modèle, l'inclusion d'une composante date-heure « z » indique que le format fuseau horaire doit se conformer à la fuseau horaire général "standard", dont des exemples sont Pacific Standard Time; PST; GMT-08:00
.
A 'Z' indique que le fuseau horaire est conforme à la RFC 822 fuseau horaire standard, par exemple -0800
.
Je pense que vous avez besoin d'une DatatypeConverter ...
@Test
public void testTimezoneIsGreenwichMeanTime() throws ParseException {
final Calendar calendar = javax.xml.bind.DatatypeConverter.parseDateTime("2010-04-05T17:16:00Z");
TestCase.assertEquals("gotten timezone", "GMT+00:00", calendar.getTimeZone().getID());
}
Autres conseils
Java ne pas analyser correctement les dates ISO.
Tout comme la réponse de McKenzie.
Il suffit de fixer le Z
avant l'analyse syntaxique.
code
String string = "2013-03-05T18:05:05.000Z";
String defaultTimezone = TimeZone.getDefault().getID();
Date date = (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")).parse(string.replaceAll("Z$", "+0000"));
System.out.println("string: " + string);
System.out.println("defaultTimezone: " + defaultTimezone);
System.out.println("date: " + (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")).format(date));
Résultat
string: 2013-03-05T18:05:05.000Z
defaultTimezone: America/New_York
date: 2013-03-05T13:05:05.000-0500
La date que vous analyse syntaxique est au format ISO 8601.
En java 7 le motif à lire et appliquer le suffixe de fuseau horaire doit lire yyyy-MM-dd'T'HH:mm:ssX
tl; dr
Instant.parse ( "2010-04-05T17:16:00Z" )
ISO 8601 standard
Votre chaîne est conforme à la ISO 8601 standard (dont le dit RFC 3339 est un profil).
Évitez j.u.Date
Les classes java.util.Date et .Calendar avec Java sont notoirement gênants. Évitez les.
Au lieu d'utiliser soit le bibliothèque Joda-Time ou le nouveau package java.time en Java 8. les deux utilisent ISO 8601 que leurs valeurs par défaut pour l'analyse syntaxique et de générer des représentations de chaîne de valeurs date-heure.
java.time
Le java.time cadre construit en Java 8 et évince plus tard les classes gênants vieux java.util.Date/.Calendar. Les nouvelles classes sont inspirés par le Joda-Time cadre, conçu comme son successeur, similaire dans le concept, mais re-architecturé. Défini par JSR 310 . Prolongée par le ThreeTen-Extra projet . Voir la Tutoriel.
La classe Instant
dans java.time représente un moment sur la timeline dans UTC fuseau horaire.
Le Z
à la fin de votre chaîne d'entrée signifie Zulu
qui signifie UTC
. Une telle chaîne peut être analysée directement par la classe Instant
, sans avoir besoin de spécifier un formatter.
String input = "2010-04-05T17:16:00Z";
Instant instant = Instant.parse ( input );
Dump à la console.
System.out.println ( "instant: " + instant );
instant: 2010-04-05T17: 16: 00Z
De là, vous pouvez appliquer un fuseau horaire ( ZoneId
) pour régler cette Instant
en ZonedDateTime
. Rechercher Stack Overflow pour la discussion et des exemples.
Si vous devez utiliser un java.util.Date
objet, vous pouvez convertir en appelant les nouvelles méthodes de conversion ajoutés aux anciennes classes telles que la méthode statique java.util.Date.from( Instant )
.
java.util.Date date = java.util.Date.from( instant );
Joda-Time
Exemple de Joda-Time 2.5.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" ):
DateTime dateTime = new DateTime( "2010-04-05T17:16:00Z", timeZone );
Convertir en UTC.
DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC );
Convertir un java.util.Date si nécessaire.
java.util.Date date = dateTime.toDate();
Selon la dernière ligne sur la date et heure modèles table des API Java 7
X Fuseau horaire ISO 8601 fuseau horaire -08; -0800; -08: 00
Pour la zone de temps ISO 8601 vous devez utiliser:
- X pour (-08 ou Z),
- XX pour (-0800 ou Z),
- XXX pour (-08: 00 ou Z);
pour analyser votre « 2010-04-05T17: 16: 00Z » vous pouvez utiliser "aaaa-MM-jj'T'HH: mm: SSX" ou "aaaa-MM-jj'T'HH: mm: ssXX" ou « aaaa-MM-jj'T'HH: mm : ssXXX " .
System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX").parse("2010-04-05T17:16:00Z"));
System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXX").parse("2010-04-05T17:16:00Z"));
System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").parse("2010-04-05T17:16:00Z"));
sera correctement imprimer 'Mon 5 avril 2010 13:16:00 HAE
« X » ne fonctionne que si secondes partielles ne sont pas présents: à savoir motif de SimpleDateFormat
"aaaa-MM-jj'T'HH: mm: SSX"
est correctement analyser
"2008-01-31T00: 00: 00Z"
"aaaa-MM-jj'T'HH: mm: ss.SX"
Pas d'analyser
"2008-01-31T00: 00: 00.000Z"
Triste mais vrai, une date-heure avec les secondes partielles ne semble pas être une date valide ISO: http : //en.wikipedia.org/wiki/ISO_8601
Le fuseau horaire doit être quelque chose comme « GMT + 00: 00 ». Ou 0000 afin d'être correctement analysées par le SimpleDateFormat - vous pouvez remplacer Z avec cette construction
Le projet comprend Restlet une classe InternetDateFormat qui peut analyser les dates RFC 3339.
Bien, vous pourriez vouloir remplacer la fuite « Z » avec « UTC » avant de l'analyser.
Je donne une autre réponse que j'ai trouvé par api-client-library
par Google
try {
DateTime dateTime = DateTime.parseRfc3339(date);
dateTime = new DateTime(new Date(dateTime.getValue()), TimeZone.getDefault());
long timestamp = dateTime.getValue(); // get date in timestamp
int timeZone = dateTime.getTimeZoneShift(); // get timezone offset
} catch (NumberFormatException e) {
e.printStackTrace();
}
Guide d'installation,
https://developers.google.com / api-client-bibliothèque / java / google-api-java-client / setup # télécharger
est ici référence API,
https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/util/DateTime
Le code source de la classe DateTime
,
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/main/java/com/google/api/client /util/DateTime.java
tests unitaires DateTime
,
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/test/java/com/google/api /client/util/DateTimeTest.java#L121
En ce qui concerne JSR-310 un autre projet d'intérêt pourrait être threetenbp .
JSR-310 fournit une nouvelle bibliothèque de date et l'heure pour Java SE 8. Ce projet est le backport Java SE 6 et 7.
Si vous travaillez sur un Android projet vous voudrez peut-être à la caisse ThreeTenABP bibliothèque .
compile "com.jakewharton.threetenabp:threetenabp:${version}"
JSR-310 a été inclus dans Java 8 comme java.time. * Package. Il est un remplacement complet pour les API de date et souffrants Calendrier dans Java et Android. JSR-310 a été backported à Java 6 par son créateur, Stephen Colebourne, dont cette bibliothèque est adaptée.
Sous Java 8 Utilisez le DateTimeFormatter.ISO_DATE_TIME prédéfini
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
ZonedDateTime result = ZonedDateTime.parse("2010-04-05T17:16:00Z", formatter);
Je suppose que la meilleure façon
Depuis java 8 il suffit d'utiliser ZonedDateTime.parse("2010-04-05T17:16:00Z")