it-swarm.com.de

Konvertieren einer Zeitzeichenfolge in das ISO 8601-Format

Ich versuche, einen String in einem Format wie 2015-08-20T08: 26: 21.000Z zu erstellen.
bis 2015-08-20T08: 26: 21Z

Ich weiß, dass es mit einigen String-Splitting-Techniken möglich ist, aber ich frage mich, ob es dafür eine elegante Lösung gibt (mit minimalen Code-Änderungen).

Beide der oben genannten sind Zeichenfolgen, die letzte, die ich brauche, ist Date in ISO 8601. http://tools.ietf.org/html/rfc3339#section-5.6

Ich habe ein paar ähnliche Fragen ausprobiert wie Konvertieren eines Datumsstrings in Millisekunden in Java aber sie lösen den Zweck nicht wirklich. 

Auch versucht mit: 

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ");
String nowAsString = df.format(new Date());

Es führt jedoch immer noch keine Konvertierung von String in String durch. Folgende Fehlermeldung wird angezeigt:

23: 04: 13,829 WARN [RuntimeExceptionMapper] hat RuntimeException abgefangen: {}: Java.lang.IllegalArgumentException: Das angegebene Objekt kann nicht als Datum formatiert werden.

Gibt es eine Bibliothek, die jemand vorschlagen kann?

Vielen Dank. 

7
CodeMonkey

tl; dr

Instant.parse( "2015-08-20T08:26:21.000Z" )
       .toString()

2015-08-20T08: 26: 21Z

Date-Time-Formatierer

Wenn Sie lediglich .000 entfernen möchten, verwenden Sie Datum-Uhrzeit-Objekte, um Ihren Eingabezeichenfolgenwert zu analysieren, und generieren Sie eine neue Zeichenfolgendarstellung dieses Datumszeitwerts in einem anderen Format.

ISO 8601

Wenn dies Ihr Ziel ist, macht der Titel der Frage übrigens keinen Sinn, da beide im ersten Satz genannten Zeichenfolgen gültige ISO 8601 formatierte Zeichenfolgen sind.

  • 2015-08-20T08:26:21.000Z
  • 2015-08-20T08:26:21Z

Java.time

Java 8 und höher enthält das neue Paket Java.time . Diese neuen Klassen ersetzen die alten Klassen Java.util.Date/.Calendar und Java.text.SimpleDateFormat. Diese alten Klassen waren verwirrend, lästig und fehlerhaft.

Sofortig

Wenn Sie nur die UTC-Zeitzone wünschen, können Sie die Instant -Klasse verwenden. Diese Klasse stellt einen Punkt entlang der Zeitleiste dar, unabhängig von einer bestimmten Zeitzone (im Wesentlichen UTC).

DateTimeFormatter.ISO_INSTANT

Durch Aufrufen eines Instant’s toString wird eine String-Darstellung des Datums/Zeitwerts mithilfe einer DateTimeFormatter.ISO_INSTANT formatter-Instanz generiert. Dieses Formatierungsprogramm ist um die Sekundenbruchteil automatisch flexibel. Wenn der Wert eine ganze Sekunde hat, werden keine Dezimalstellen generiert (scheinbar was die Frage will). Für einen Bruchteil einer Sekunde werden die Ziffern in Gruppen von 3, 6 oder 9 angezeigt, um den Wert bis zur Auflösung im Nanosekundenbereich darzustellen. Hinweis: Dieses Format kann die Grenze von Millisekunden (3 Dezimalstellen) nach ISO 8601 überschreiten.

Beispielcode

Hier ist ein Beispielcode in Java 8 Update 51.

String output = Instant.parse( "2015-08-20T08:26:21.000Z" ).toString( );
System.out.println("output: " + output );

ausgabe: 2015-08-20T08: 26: 21Z

Umschalten auf eine Sekundenbruchstelle, .08

String output = Instant.parse( "2015-08-20T08:26:21.08Z" ).toString( );

ausgabe: 2015-08-20T08: 26: 21.080Z

Wenn Sie an einer anderen Zeitzone als UTC interessiert sind, erstellen Sie ein ZonedDateTime - Objekt aus dieser Instant.

ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , ZoneId.of( "America/Montreal" ) ) ;
10
Basil Bourque

Die Konvertierung eines Datums Stringmit unbekannter Formatierung in ein Datum Stringname__, das bekannte Formatierungen verwendet, kann mit zwei DateFormatname__-Objekten erfolgen, die dynamisch konfiguriert sind, um das Format der Eingabe Stringzu parsen, und eines, das konfiguriert ist, um die formatierte Ausgabe Stringname zu erzeugen. In Ihrer Situation ist die Eingabe Stringname__-Formatierung nicht spezifiziert und muss vom Aufrufer angegeben werden. Die Ausgabe Stringname__-Formatierung kann jedoch so konfiguriert werden, dass die ISO 8601-Formatierung ohne zusätzliche Eingabe verwendet wird. Im Wesentlichen erfordert das Erzeugen einer nach ISO 8601 formatierten Ausgabe Stringzwei vom Aufrufer bereitgestellte Eingaben: Stringname__, die das formatierte Datum enthalten, und eine weitere Stringname__, die das SimpleDateFormatname__-Format enthält. 

Hier ist die beschriebene Konvertierung als Java-Code (Ich habe absichtlich auf Nullprüfungen und Validierungen verzichtet, fügen Sie diese entsprechend Ihrem Code hinzu):

private String formatDateAsIso8601(final String inputDateAsString, final String inputStringFormat) throws ParseException {

     final DateFormat iso8601DateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.ENGLISH);
     iso8601DateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));

     final DateFormat inputDateFormatter = new SimpleDateFormat(inputStringFormat, Locale.ENGLISH);
     final Date inputDate = inputDateFormatter.parse(inputDateAsString);

     return iso8601DateFormatter.format(inputDate);
}

Wenn Sie diese Methode ändern möchten, beachten Sie, dass SimpleDateFormatnicht threadsicher ist und dass Sie sie nicht aus einem statischen Kontext ohne Umgehung für Multithreadcode verwenden sollten (ThreadLocalwird im Allgemeinen verwendet, um eine solche Problemumgehung für SimpleDateFormatauszuführen.) . 

Ein zusätzliches "gotcha" ist die Verwendung eines Localebeim Erstellen der SimpleDateFormatname__-Objekte. Entfernen Sie nicht die Localename__-Konfiguration. Es ist nicht sicher, dem System zu erlauben, die Standardeinstellung Localezu verwenden, da dies benutzer-/maschinenspezifisch ist. Wenn Sie die Verwendung der Standardeinstellung Localezulassen, besteht das Risiko vorübergehender Fehler, da Ihr Entwicklungsrechner einen Localeverwendet, der sich von dem LocaleIhres Endbenutzers unterscheidet. Sie müssen mein ausgewähltes ENGLISH Localenicht verwenden, es ist vollkommen in Ordnung, ein anderes Gebietsschema zu verwenden (Sie sollten die Regeln von Localeverstehen und den Code entsprechend modifizieren). Die Angabe von noLocaleund die Verwendung der Systemvorgaben ist jedoch falsch und führt wahrscheinlich zu vielen frustrierenden Stunden, die versuchen, einen schwer fassbaren Fehler zu diagnostizieren.

Bitte haben Sie Verständnis dafür, dass diese Lösung ab Java 8 nicht ideal ist und die Verwendung von JodaTime-basierten Klassen wie Instantname__. Ich habe mich für die Antwort mit den veralteten APIs entschieden, weil Sie sich in Ihrer Frage damit beschäftigt haben. Wenn Sie Java 8 verwenden, möchte ich unbedingt die neuen Klassen erlernen und anwenden, da sie in fast jeder Hinsicht eine Verbesserung darstellen.

2
Emily Mabrey

Dein Format ist einfach nicht richtig, probiere es aus: -

try {
        String s = "2015-08-20T08:26:21.000Z";
         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
    Date d = df.parse(s);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
        System.out.println(sdf.format(d));
    } catch (ParseException e) {
        e.printStackTrace();
    }
2
karim mohsen