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.
Instant.parse( "2015-08-20T08:26:21.000Z" )
.toString()
2015-08-20T08: 26: 21Z
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.
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 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.
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.
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" ) ) ;
Die Konvertierung eines Datums String
mit unbekannter Formatierung in ein Datum String
name__, das bekannte Formatierungen verwendet, kann mit zwei DateFormat
name__-Objekten erfolgen, die dynamisch konfiguriert sind, um das Format der Eingabe String
zu parsen, und eines, das konfiguriert ist, um die formatierte Ausgabe String
name zu erzeugen. In Ihrer Situation ist die Eingabe String
name__-Formatierung nicht spezifiziert und muss vom Aufrufer angegeben werden. Die Ausgabe String
name__-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 String
zwei vom Aufrufer bereitgestellte Eingaben: String
name__, die das formatierte Datum enthalten, und eine weitere String
name__, die das SimpleDateFormat
name__-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 SimpleDateFormat
nicht threadsicher ist und dass Sie sie nicht aus einem statischen Kontext ohne Umgehung für Multithreadcode verwenden sollten (ThreadLocal
wird im Allgemeinen verwendet, um eine solche Problemumgehung für SimpleDateFormat
auszuführen.) .
Ein zusätzliches "gotcha" ist die Verwendung eines Locale
beim Erstellen der SimpleDateFormat
name__-Objekte. Entfernen Sie nicht die Locale
name__-Konfiguration. Es ist nicht sicher, dem System zu erlauben, die Standardeinstellung Locale
zu verwenden, da dies benutzer-/maschinenspezifisch ist. Wenn Sie die Verwendung der Standardeinstellung Locale
zulassen, besteht das Risiko vorübergehender Fehler, da Ihr Entwicklungsrechner einen Locale
verwendet, der sich von dem Locale
Ihres Endbenutzers unterscheidet. Sie müssen mein ausgewähltes ENGLISH Locale
nicht verwenden, es ist vollkommen in Ordnung, ein anderes Gebietsschema zu verwenden (Sie sollten die Regeln von Locale
verstehen und den Code entsprechend modifizieren). Die Angabe von noLocale
und 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 Instant
name__. 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.
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();
}