wake-up-neo.com

vereinfachtes Formatieren des Datums mit 'Z'

Ich versuche ein Datum zu analysieren, das so aussieht:

2010-04-05T17:16:00Z

Dies ist ein gültiges Datum gemäß http://www.ietf.org/rfc/rfc3339.txt . Das Z-Literal "impliziert, dass UTC Der bevorzugte Bezugspunkt für die angegebene Zeit ist."

Wenn ich versuche, es mit SimpleDateFormat und diesem Muster zu analysieren:

yyyy-MM-dd'T'HH:mm:ss

Es wird als Mo Apr 05 17:16:00 EDT 2010 analysiert

SimpleDateFormat kann die Zeichenfolge nicht mit den folgenden Mustern analysieren:

yyyy-MM-dd'T'HH:mm:ssz
yyyy-MM-dd'T'HH:mm:ssZ

Ich kann die TimeZone explizit so einstellen, dass sie im SimpleDateFormat verwendet wird, um die erwartete Ausgabe zu erhalten, aber ich denke nicht, dass dies notwendig sein sollte. Fehlt mir etwas? Gibt es einen alternativen Datums-Parser?

69
DanInDC

In dem Muster zeigt die Einbeziehung einer 'z'-Datum/Uhrzeit-Komponente an, dass das Zeitzonenformat der Allgemeinen Zeitzone "Standard" entsprechen muss. Beispiele hierfür sind Pacific Standard Time; PST; GMT-08:00

Ein "Z" zeigt an, dass die Zeitzone der RFC 822-Zeitzone Standard entspricht, z. -0800.

Ich denke du brauchst einen 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());
}
30
Paul McKenzie

ISO analysiert Datumsangaben nicht korrekt.

Ähnlich wie McKenzies Antwort.

Fixiere einfach die Z vor der Analyse.

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));

Ergebnis

string: 2013-03-05T18:05:05.000Z
defaultTimezone: America/New_York
date: 2013-03-05T13:05:05.000-0500
48
Alex

Das Datum, das Sie analysieren, hat das ISO8601-Format.

In Java 7 sollte das Muster zum Lesen und Anwenden des Zeitzonen-Suffixes yyyy-MM-dd'T'HH:mm:ssX lauten.

34
Dave Patterson

tl; dr

Instant.parse ( "2010-04-05T17:16:00Z" )

ISO 8601 Standard

Ihr String entspricht der Norm ISO 8601 (von der der angegebene RFC 3339 ein Profil ist).

Vermeiden Sie j.u.Date

Die mit Java gebündelten Klassen Java.util.Date und .Calendar sind notorisch lästig. Vermeide sie.

Verwenden Sie stattdessen entweder die Bibliothek Joda-Time oder das neue Java.time-Paket in Java 8. Beide verwenden ISO 8601 als Standardeinstellungen für das Analysieren und Generieren von Zeichenfolgendarstellungen von Datums-/Zeitwerten. 

Java.time

Das Java.time - Framework, das in Java 8 und später integriert ist, ersetzt die problematischen alten Java.util.Date/.Calendar-Klassen. Die neuen Klassen sind von dem sehr erfolgreichen Joda-Time - Framework inspiriert, das als Nachfolger gedacht ist und im Konzept ähnlich ist, aber neu konzipiert wurde. Definiert durch JSR 310 . Erweitert um das ThreeTen-Extra Projekt. Siehe das Tutorial .

Die Instant-Klasse in Java.time repräsentiert einen Moment auf der Zeitleiste in der Zeitzone UTC .

Die Variable Z am Ende Ihrer Eingabezeichenfolge bedeutet Zulu, die für UTC steht. Eine solche Zeichenfolge kann direkt von der Instant-Klasse analysiert werden, ohne dass ein Formatierer angegeben werden muss.

String input = "2010-04-05T17:16:00Z";
Instant instant = Instant.parse ( input );

Auf die Konsole ausgeben.

System.out.println ( "instant: " + instant );

augenblick: 2010-04-05T17: 16: 00Z

Von dort aus können Sie eine Zeitzone ( ZoneId ) anwenden, um diese Instant in eine ZonedDateTime anzupassen. Durchsuchen Sie den Stack Overflow für Diskussionen und Beispiele.

Wenn Sie ein Java.util.Date - Objekt verwenden müssen, können Sie die Konvertierung durchführen, indem Sie die neuen Konvertierungsmethoden aufrufen, die den alten Klassen hinzugefügt wurden, z. B. die statische Methode Java.util.Date.from( Instant ) .

Java.util.Date date = Java.util.Date.from( instant );

Joda-Zeit

Beispiel in Joda-Time 2.5.

DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" ):
DateTime dateTime = new DateTime( "2010-04-05T17:16:00Z", timeZone );

Konvertieren Sie in UTC.

DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC );

Konvertieren Sie bei Bedarf in ein Java.util.Date.

Java.util.Date date = dateTime.toDate();
19
Basil Bourque

Gemäß der letzten Zeile in der Tabelle Datums- und Zeitmuster der Java 7-API

X Zeitzone ISO 8601 Zeitzone -08; -0800; -08: 00

Für die ISO 8601-Zeitzone sollten Sie Folgendes verwenden: 

  • X für (-08 oder Z), 
  • XX für (-0800 oder Z),
  • XXX für (-08: 00 oder Z);

um Ihr "2010-04-05T17: 16: 00Z" zu analysieren, können Sie entweder "yyyy-MM-dd'T'HH: mm: ssX" oder "yyyy-MM-dd'T'HH: mm: ssXX") 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"));

wird 'Mo Apr 05 13:16:00 EDT 2010' korrekt ausdrucken

12
Legna

Das 'X' funktioniert nur, wenn keine Sekunden vorhanden sind: SimpleDateFormat-Muster von

"JJJJ-MM-dd'T'HH: mm: ssX"

Wird richtig analysieren

"2008-01-31T00: 00: 00Z"

aber

"JJJJ-MM-dd'T'HH: mm: ss.SX"

Wird NICHT analysiert

"2008-01-31T00: 00: 00.000Z"

Traurig, aber wahr, ein Datum/Uhrzeit mit Sekunden in Sekunden scheint kein gültiges ISO-Datum zu sein: http://en.wikipedia.org/wiki/ISO_8601

6
Sandy McPherson

Die Zeitzone sollte etwa "GMT + 00: 00" oder 0000 sein, um vom SimpleDateFormat richtig analysiert zu werden. Sie können Z durch diese Konstruktion ersetzen.

3
Cornel Creanga

Ich gebe eine weitere Antwort, die ich mit api-client-library von Google gefunden habe

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();
}

Installationsanleitung,
https://developers.google.com/api-client-library/Java/google-api-Java-client/setup#download

Hier ist eine API-Referenz,
https://developers.google.com/api-client-library/Java/google-http-Java-client/reference/1.20.0/com/google/api/client/util/DateTime

Quellcode von DateTime Class,
https://github.com/google/google-http-Java-client/blob/master/google-http-client/src/main/Java/com/google/api/client/util/DateTime .Java

DateTime Unit-Tests,
https://github.com/google/google-http-Java-client/blob/master/google-http-client/src/test/Java/com/google/api/client/util/DateTimeTest .Java # L121

2
Johnny

In Bezug auf JSR-310 könnte ein anderes Projekt von Interesse sein threetenbp .

JSR-310 bietet eine neue Datums- und Zeitbibliothek für Java SE 8. Dieses Projekt ist der Rückport auf Java SE 6 und 7.

Wenn Sie an einem Android - Projekt arbeiten, können Sie die ThreeTenABP-Bibliothek überprüfen.

compile "com.jakewharton.threetenabp:threetenabp:${version}"

JSR-310 wurde in Java 8 als Java.time. * -Paket enthalten. Es ist ein vollständiger Ersatz für die angeschlagenen Datums- und Kalender-APIs in Java und Android. JSR-310 wurde von seinem Ersteller Stephen Colebourne nach Java 6 zurückportiert, von dem diese Bibliothek angepasst wurde.

2
JJD

Das Restletprojekt enthält eine InternetDateFormat-Klasse, mit der RFC 3339-Daten analysiert werden können.

Restlet InternetDateFormat

Möglicherweise möchten Sie jedoch nur das abschließende 'Z' durch "UTC" ersetzen, bevor Sie es analysieren.

2
Marcus Adams

Verwenden Sie unter Java 8 das vordefinierte DateTimeFormatter.ISO_DATE_TIME

 DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
 ZonedDateTime result = ZonedDateTime.parse("2010-04-05T17:16:00Z", formatter);

Ich denke, es ist der einfachste Weg

1
JavaBohne

Seit Java 8 verwenden Sie einfach ZonedDateTime.parse("2010-04-05T17:16:00Z")

0