tl; dr
OffsetDateTime odt = OffsetDateTime.parse ("2016-08-18 14:27:15.103+02" , DateTimeFormatter.ofPattern ("yyyy-MM-dd HH:mm:ss.SSSX")) ;
Einzelheiten
Die Answer by greg-449 korrekt über das Problem (mit einem Nur-Datum-Objekt für ein Datum-Zeit-Wert), aber nicht die Lösung .
Diese Antwort verwendet LocalDateTime
, die unnötig wertvolle Informationen über die offset-from-UTC wegwirft. A LocalDateTime
does nicht repräsentieren einen bestimmten Moment auf der Timeline, nur eine vage Vorstellung über mögliche Momente abhängig von der Anpassung in einer bestimmten Zeitzone. Die +02
ist eine offset-from-UTC Bedeutung "zwei Stunden vor UTC". In UTC beträgt die Uhrzeit für diesen simultanen Moment also 12 Stunden, also 2 Stunden weniger als 14 Stunden. Diese stellt einen bestimmten Moment auf der Timeline dar. Dieser Offset ist die wertvolle Information, die Sie mit einem LocalDateTime
eher als ein OffsetDateTime
wegwerfen.
Das Format Ihrer Zeichenfolge ist im SQL-Format, das dem ISO 8601-Standardformat entspricht. Ersetzen Sie einfach den RAUM in der Mitte mit einem T
. Die java.time-Klassen verwenden standardmäßig ISO 8601-Formate, sodass Sie kein Formatierungsmuster angeben müssen.
String input = "2016-08-18 14:27:15.103+02";
String inputModified = input.replace (" " , "T");
Leider hat Java 8 einen Fehler beim Parsen von Offset-Werten, abgekürzt auf nur eine Stunde oder Offset-Werte unter Auslassung des Doppelpunkts zwischen Stunden und Minuten. In Java 9 behoben. Aber in Java 8 müssen wir die Eingabe anpassen.
// Workaround for Java 8 where 2-digit offset fails parsing. Fixed in Java 9.
int lengthOfAbbreviatedOffset = 3;
if (inputModified.indexOf ("+") == (inputModified.length() - lengthOfAbbreviatedOffset)) {
// If third character from end is a PLUS SIGN, append ':00'.
inputModified = inputModified + ":00";
}
if (inputModified.indexOf ("-") == (inputModified.length() - lengthOfAbbreviatedOffset)) {
// If third character from end is a PLUS SIGN, append ':00'.
inputModified = inputModified + ":00";
}
Jetzt analysieren.
OffsetDateTime odt = OffsetDateTime.parse (inputModified);
Dump zur Konsole.Beachten Sie, wie wir +02
in +02:00
umgewandelt haben.
System.out.println ("input: " + input + " | inputModified: " + inputModified + " | odt: " + odt);
input: 2016-08-18 14:27:15.103+02 | inputModified: 2016-08-18T14:27:15.103+02:00 | odt: 2016-08-18T14:27:15.103+02:00
Alternativ ein Formatierungsmuster angeben. Der Offset-Parsing-Fehler beißt nicht, wenn dieses Formatierungsmuster verwendet wird.
DateTimeFormatter f = DateTimeFormatter.ofPattern ("yyyy-MM-dd HH:mm:ss.SSSX");
OffsetDateTime odt = OffsetDateTime.parse (input , f);
Datenbank
von Postgres kommend, sollten Sie den Wert als Datetime-Objekt wurden Abrufen anstatt ein String.
Wenn Ihr JDBC-Treiber JDBC 4.2 entspricht, können Sie ResultSet::getObject
anrufen, um eine Instant
oder OffsetDateTime
zu erhalten. Wenn nicht, rufen Sie ResultSet::getTimestamp
an, um eine java.sql.Timestamp
zu erhalten, und konvertieren Sie dann sofort in java.time, indem Sie toInstant
auf dem Timestamp-Objekt aufrufen.
Bleiben Sie bei java.time für Ihre Geschäftslogik. Verwenden Sie die Typen java.sql kurz und nur für den Austausch mit der Datenbank.
Ich denke, ist der Abstand zwischen dem Datum und der Uhrzeit. Ist das ein Space-Char oder ein brechungsfreier Raum? Wenn Ihre Zeichenfolge aus einem Formular irgendeiner Art stammt, kann das ein anderes Zeichen als ein Leerzeichen sein –
Es stammt aus einer Postgre-Datenbank –