2016-05-14 4 views
-1

Ich erhalte Datetime-Standard CURRENT_TIMESTAMP Ergebnis von MSSQL Server-Datenbank, Jetzt muss ich dieses Datum analysieren, Zeit usw. Database Ergebnis ist wie 2016.05.14 12: 54: 01.363java.text.ParseException: unparseable Datum in JAVA Android

Alles, was ich brauche, ist dieses Format zu überqueren. Wie ich es unten mache.

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    try 
    { 
     Date date = format.parse(dateStr); 
     SimpleDateFormat todayFormat = new SimpleDateFormat("dd"); 
     String dateToday = todayFormat.format(date); 
     format = dateToday.equals(today) ? new SimpleDateFormat("hh:mm a") : new SimpleDateFormat("dd LLL, hh:mm a"); 
     String date1 = format.format(date); 
     timestamp = date1.toString(); 
     // 
    } 
    catch (ParseException e) 
    { 
     e.printStackTrace(); 
    } 

Aber ich bin immer Fehler:

java.text.ParseException: Unparseable date: "{"date":"2016-05-14 12:54:01.363000","timezone":"UTC","timezone_type":3}" (at offset 0) 

in Zeile 3 .i.e Datum date = format.parse (dateStr);

Brauchen Sie Hilfe!

+0

Bitte suchen Sie vor dem Posten Stack Overflow. –

+0

@BasilBourque Ihre Markierung als Duplikat führt mich nicht zu meiner Antwort, weil ich einen Fehler von ** Unrated Datum bekomme: "{" Datum ":" 2016-05-14 12: 54: 01.363000 "," Zeitzone ":" UTC "," timezone_type ": 3}" ** nicht ** java.text.ParseException: Nicht übertragbares Datum: "2015-03-26 1624: 32: 39" **. Heben Sie die Markierung dieser Frage als Duplikat auf. –

+0

[A] Du hast Recht, du Frage ist kein Duplikat dieser speziellen Frage, also habe ich sie wieder geöffnet. Aber es ist ein Duplikat von anderen. [B] Ihr zitiertes Ergebnis im ersten Absatz ist * nicht * das tatsächliche Vergehen. Sie haben die zusätzlichen drei Nullen am Ende weggelassen, was die Ursache Ihres Problems ist. Bitte bearbeiten Sie Ihre Frage, um korrekt zu sein. [C] Du hast zu viel Code, irrelevanten Code gepostet. Nur die zwei 'format =' und 'date =' Zeilen sind relevant. Stellen Sie beim Verfassen ein [minimales, vollständiges und überprüfbares Beispiel] (http://stackoverflow.com/help/mcve) bereit. –

Antwort

2

Mikrosekunden

Ihr Fragetext zitiert die Eingabezeichenfolge als 2016-05-14 12:54:01.363, aber Ihre Fehlermeldung sagt andernfalls 2016-05-14 12:54:01.363000. Diese zusätzlichen drei Ziffern sind microseconds.

Die alten Datum/Uhrzeit-Klassen wie java.util.Date werden nur auf milliseconds aufgelöst (3 Nachkommastellen für Sekundenbruchteile). So SimpleDateFormat kann nicht mit solchen Eingaben umgehen. Entweder die Eingabezeichenfolge abschneiden oder stattdessen moderne Datums-/Uhrzeitklassen verwenden.

java.time

Das größere Problem ist, dass Sie alte veraltete Datum Zeitklassen von den frühesten Versionen von Java verwenden. Diese Klassen wurden durch das in Java 8 und höher integrierte Framework java.time ersetzt. Viel von dieser java.time-Funktionalität wurde durch das ThreeTen-Backport Projekt in Java 6 & 7 zurück portiert und weiter an Android von ThreeTenABP angepasst. Also kein Grund, mit diesen alten und notorisch lästigen Klassen zu ringen.

Die java.time-Klassen haben eine viel feinere Granularität und werden in nanoseconds aufgelöst (9 Dezimalstellen der Sekunden).

In java.time ist die Klasse Instant ein Moment auf der Timeline in UTC mit einer Auflösung von Nanosekunden. Ein Instant ist das Äquivalent zu einem java.util.Date, außer mit feinerer Auflösung.

Für weitere Informationen über die Konvertierung zwischen alten Typen und Java.Zeittypen, siehe my Answer with diagram zu einer anderen Frage.

abrufen Datum Zeitwert als Datum Zeittyp

Sie sollten Datum Zeitwert aus der Datenbank als Datum-Zeit-Typen, nicht als Strings werden abruft. Wenn Ihr JDBC-Treiber JDBC 4.2 entspricht (ein Update auf JSR 221 und described here), können Sie möglicherweise direkt in eine OffsetDateTime abrufen. Sie können sich eine OffsetDateTime als Instant plus eine offset-from-UTC (eine Anzahl Stunden, Minuten und Sekunden) vorstellen.

Wenn nicht, greifen Sie auf die alten java.sql Typen zurück. Für Datum-Uhrzeit bedeutet das java.sql.Timestamp.

java.sql.Timestamp ts = resultSet.getTimestamp(1); 

Minimieren Sie Ihre Nutzung der alten java.sql Typen, wie sie Teil des Chaos sind die java.util.Date/.Calendar ist und so weiter. Sofort in java.time konvertieren. Suchen Sie zum Konvertieren nach neuen Methoden, die zu den alten Klassen hinzugefügt wurden, z. B. toInstant.

Instant instant = ts.toInstant(); 

Parsing

Wenn Sie diese Eingabezeichenfolge analysieren muss, ist der einfachste Weg, um es mit den ISO 8601 Standardformate zu machen entsprechen. Die Klassen java.time verwenden beim Analysieren/Erzeugen von Strings standardmäßig ISO 8601-Formate.

Um die Anforderungen zu erfüllen, ersetzen Sie den RAUM in der Mitte mit einem T. Und angenommen, diese Zeichenfolge stellt tatsächlich einen Moment in UTC dar, fügen Sie eine Z hinzu. Die Z ist die Abkürzung für Zulu, was UTC bedeutet.

String input = "2016-05-14 12:54:01.363000"; 
String inputModified = input.replace(" " , "T"); 
Instant instant = Instant.parse(inputModified); 

Zeitzone

Die Frage ignoriert die entscheidende Frage der Zeitzonen.

Die beste Vorgehensweise besteht darin, Datums- und Uhrzeitwerte in UTC zu speichern. Die besseren Datenbanken passen eingehende Daten in UTC an. Wenn der Wert als java.sql.Timestamp abgerufen wird, ist Ihr Wert in UTC und auch in Instant konvertiert.

Ein Datum und eine Uhrzeit hängen von der Zeitzone ab. Wenden Sie eine Zeitzone (ZoneId) auf Ihre Instant an, um eine ZonedDateTime zu erhalten.

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

Dann fragen Sie den Tag des Monats und die Zeit, die Sie benötigen.

int dayOfMonth = zdt.getDayOfMonth(); 

Wenn Sie die Zeit-of-Tag als ein Objekt in seinem eigenen Recht, verwenden Sie die LocalTime Klasse.

LocalTime localTime = zdt.toLocalTime(); 

Wenn Sie wirklich ein String der Time-of-Tag, verwenden Sie die java.time.format Paket.

Noch besser, lassen Sie java.time die Arbeit der automatischen Formatierung erledigen.Beachten Sie die Verwendung von Locale, die (a) die menschliche Sprache für den Namen des Monats und so definiert, und (b) kulturelle Normen wie die Reihenfolge der Elemente wie Jahr-Monat-Tag. Besser, das Gebietsschema explizit anzugeben, als sich implizit auf das aktuelle Standardgebietsschema der JVM zu verlassen, das sich zur Laufzeit ändern kann.

DateTimeFormatter timeOfDayFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT); 
timeOfDayFormatter = timeOfDayFormatter.withLocale(Locale.CANADA_FRENCH); 
String output = zdt.toLocalTime().format(timeOfDayFormatter); 
+0

Das ist wirklich eine tolle Erklärung, die ich je gelesen habe. Ich verstehe alles klar. Aber ** Instant ** wird nicht aufgelöst. Es besagt, ** kann das Symbol Instant ** nicht auflösen. +1 für diese Art von Erklärung. Vielen Dank! –

+0

@KamranBhatti Sie müssen 'java.time.Instant' oder' java.time. * 'Importieren. Die anderen Klassen 'ZoneId',' ZonedDateTime', 'LocalTime',' OffsetDateTime' sind ebenfalls alle im Paket java.time enthalten. Die 'DateTimeFormatter'-Klasse befindet sich im Paket' java.time.format'. Diese Pakete sind in Java 8 integriert. Ihre IDE sollte das herausfinden können. Stellen Sie sicher, dass Ihr Projekt in der IDE für die Kompilierung mit Java 8 (nicht Java 6 oder 7) konfiguriert ist. –

+0

Ich verifizierte und verwendete Java 7, jetzt konfigurierte ich es zu Java 8 als ** C: \ Programme \ Java \ jdk1.8.0_25 **, aber immer noch den gleichen Fehler bei ** Instant ** –

1

Das Problem hängt davon ab, wie Sie die Formatvariable erstellen, und es ist eine gute Methode, ein passendes Muster anstelle des Standardmusters zu verwenden. In Ihrem Fall (das Argument ist wie „2016.05.14 12: 54: 01,363“, dann könnte das Format aussehen:

DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); 
Date date = format.parse(dateStr); 

Wenn Ihr dataStr wird von einem json Web-Service-Aufruf mit dem Format zurückgegeben wie in der Ausnahme angegeben ist, dann können Sie die dateStr des Antworttyp zuordnen, zum Beispiel angenommen, es MyDate Klasse genannt wird.

ObjectMapper mapper = new ObjectMapper(); 
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")); 
MyDate myDate = mapper.readValue(dateStr, MyDate.class); 
Date date = myDate.getDate(); 

Wenn Sie den Rückgabetyp nicht kennen, können Sie einfach auf eine Karte es Kartenklasse:

Map dateMap = new ObjectMapper().readValue(dateStr, Map.class); 
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); 
Date date = format.parse(dateMap.get("date")); 
+0

Ich habe ** neu SimpleDateFormat ("JJJJ-MM-TT HH: mm: ss"); ** bis ** neu SimpleDateFormat ("JJJJ-MM-TT HH: mm: ss.SSS"); **. Aber immer noch den gleichen Fehler. Warum? –

+0

@Kamran Bhatti - Bitte stellen Sie sicher, dass die Eingabe dateStr ist etwas wie "** 2016-05-14 12: 54: 01.363 **", aber nichts wie "** {" date ":" 2016-05-14 12 : 54: 01.363000 "," timezone ":" UTC "," timezone_type ": 3} **". –

+0

meine Datenbank Spalte zeigt mir, es ist nur ** 2016-05-14 12: 54: 01.363 ** aber dateStr zeigt mir ** "{" date ":" 2016-05-14 12: 54: 01.363000 "," timezone ":" UTC "," timezone_type ": 3}" ** wenn ich diese Spalte in json bekomme. Ich weiß nicht, was das Problem ist –

Verwandte Themen