2017-04-20 2 views
1

Ich habe eine Datumszeichenkette in CST (24 Stunden) und ich möchte es in GMT (12 Stunden) konvertieren. Ich habe eine Java-Methode wie unten, die gut funktioniert, wenn meine Systemzeit Kolkata Zeit ist. (System, wo ich die Java-Methode ausführen) Aber wenn mein System in Shanghai-Zeit ist, kommt die GMT-Zeit falsch.Datumsformat Umwandlung von CST nach GMT funktioniert nicht

String inputDate = "01-19-2017 06:01 CST"; 
SimpleDateFormat inputFormatter = new SimpleDateFormat("MM-dd-yyyy hh:mm Z"); 
parsedInput = inputFormatter.parse(inputDate); 

// parsedInput -> Tue Jan 19 06:01:00 CST 2017 -> When system time is Shanghai time 
// parsedInput -> Thu Jan 19 17:31:00 IST 2017 -> When system time is Kolkata time 


SimpleDateFormat formatter = new SimpleDateFormat("MM-dd-yyyy hh:mm a Z"); 
TimeZone gmt = TimeZone.getTimeZone("GMT"); 
formatter.setTimeZone(gmt); 
String formattedDate = formatter.format(parsedInput); 

// formattedDate -> 01-18-2017 10:01 PM +0000 -> When system time is Shanghai time (Incorrect) 
// formattedDate -> 01-19-2017 12:01 PM +0000 -> When system time is Kolkata time 
+0

* „Tue 19. Januar 06.01.00 CST 2016 -> Wenn die Systemzeit ist Shanghai Zeit“ * <- Ist das nur ein Tippfehler oder ist es wirklich das Jahr ändern bis 2016? –

+1

Was meinst du mit "24 Stunden" hier? Beachten Sie, dass Sie "hh" (die 12-Stunden-Uhr) sowohl in der Eingabe als auch in der Ausgabe verwenden ... –

+4

Beachten Sie auch, dass viele Zeitzonenabkürzungen schrecklich mehrdeutig sind. Was erwarten * Sie * CST in diesem Fall? –

Antwort

4

Vermeiden Pseudozeitzonen

Die 3-4 Brief Zeitzone Abkürzungen wie CST sind nicht tatsächliche Zeit ersetzt Zonen. Sie sind nicht standardisiert. Sie sind nicht einmal einzigartig!

Ihr CST könnte "China Standard Time" oder könnte "Central Standard Time" in Amerika sein, oder könnte etwas anderes sein. Es gibt keine Möglichkeit zu wissen, welche.

Ein anderes Beispiel: IST könnte "India Standard Time" oder "Ireland Standard Time" oder andere bedeuten.

Eine zuverlässige Entschlüsselung dieser Pseudozonen ist nicht möglich. Die Joda-Time-Bibliothek hat eine weise Politik, die es sogar ablehnt, es zu versuchen. Leider machen die java.time-Klassen beim Parsen eine Schätzung, aber das Ergebnis ist möglicherweise nicht die Zone, die Sie erwarten.

Also nie diese nutzlosen Pseudo-Zonen verwenden. Verwenden Sie eine proper time zone name im Format continent/region wie America/Chicago, Asia/Kolkata, Pacific/Auckland.

Vermeiden Vermächtnis Datum Zeitklassen

Sie verwenden die lästigen alten Datum-Zeit-Klassen, die jetzt Vermächtnis sind, die von den java.time Klassen verdrängte.

Umgehung

Wenn Sie wissen alle Eingaben für die gleiche Zeitzone bestimmt sind, abreißen dann die pseudo-Zone und Verfahren als LocalDateTime gelten die vorgesehene Zone als ZoneId ein ZonedDateDate herzustellen. Von diesem können Sie eine Instant für UTC Zeit extrahieren.

String input = "01-19-2017 06:01".replace(" " , "T") ; // Insert a “T” to comply with standard ISO 8601 format used by default in java.time. 
LocalDateTime ldt = LocalDateTime.parse(input); // Lacks any concept of time zone or offset-from-UTC. So *not* an actual moment on the timeline. 
ZoneId z = ZoneId.of("America/Chicago"); // Assuming “CST” meant this zone in North America. 
ZonedDateTime zdt = ldt.atZone(z); // Assign a time zone to determine an actual moment on the timeline. 
Instant instant = zdt.toInstant(); // Extract a value in UTC. 

Sie können wählen, dass die selben Moment durch die Linse der Wandtaktzeit in Indien zu sehen.

ZonedDateTime zdtKolkata = zdt.withZoneSameInstant(ZoneId.of("Asia/Kolkata")) ; 

Verlassen Sie sich nie auf Standardzone

Ihre aktuelle Standard-Zeitzone des JVM kann innerhalb dieser JVM ausgeführt wird in jedem Thread von jeder App von jedem Code jederzeit geändert werden.Da sich dies jederzeit ändern kann, können Sie sich nicht auf einen bestimmten Wert verlassen.

Wenn Sie das optionale Argument für die Zeitzone weglassen, wenden die Datums- und Uhrzeitklassen implizit die aktuelle Standardzeitzone an. Die Lösung ist einfach: Geben Sie immer die erwartete/gewünschte Zeitzone an.

Beachten Sie, wie das obige Codebeispiel die Zone bei jeder Gelegenheit angibt.

(Das Gleiche gilt für Locale, übrigens. Explizit angeben, anstatt auf aktuellen Standard verlassen.)

0

Versuchen Sie, die TimeZone-inputFormatter auch, zum Beispiel:

SimpleDateFormat inputFormatter = new SimpleDateFormat("MM-dd-yyyy hh:mm Z"); 
inputFormatter.setTimeZone(TimeZone.getTimeZone("GMT")); 

Wenn Sie nicht die Zeitzone angeben, es den Standardwert berücksichtigt, die ist Asia/Shanghai in Ihrem Fall und damit , falsches Ergebnis.

Sie können es in Ihrem aktuellen System reproduzieren, indem GMT mit Asia/Shanghai in dem oben snippett

+0

Einstellung der Zeitzone für 'inputFormatter' vor der Analyse hat keinen Einfluss auf .. es ist immer noch gleich .. –

2

Ihr Problem die Mehrdeutigkeit von CST ist. In den meisten Fällen versteht SimpleDateFormat CST als Central Standard Time wie Sie es erwartet hatten. Aber wenn Ihr Computer Shanghai Time ausführt, wird dies die Zeitzone des Kalenders des Formatierers, und dann versteht es CST plötzlich als China-Standardzeit, genau wie Shanghai-Zeit.

Daher Darshan Mehta’s solution, Einstellung inputFormatter 's Zeitzone zu etwas anderem als China Standard Time, funktioniert auf meinem Computer. Ich weiß nicht, warum es bei Ihnen nicht funktioniert hat (ich habe es auf TimeZone.getTimeZone("America/Chicago") gesetzt, um der beabsichtigten Interpretation von CST zu entsprechen).

Die korrekte und gute Lösung besteht jedoch darin, die drei- und vierstelligen Zeitzonenabkürzungen vollständig zu vermeiden. Ihr ist nur ein Beispiel von vielen, wo sie Ärger verursachen. Wenn Sie können, geben Sie Ihre Eingabezeichenfolge mit einer expliziten Zone von UTC-Offset, so ist nie zweideutig:

String inputDate = "01-19-2017 06:01 -0600"; 

Jetzt Ihr Code Ihres Computers wie erwartet funktioniert, egal Einstellung Zeitzone. Die Z in der Musterzeichenfolge haben Sie bereits passt -0600 schön.

All dies gesagt, wenn Sie die Java 8 Datum und Uhrzeit Klassen verwenden können, tun Sie sich einen Gefallen der Umstellung auf sie. Ich zögere, sie "Java 8 date and time classes" zu nennen, weil sie auch nach Java 6 und 7 zurückportiert wurden. Wenn Sie also mit einer Bibliotheksabhängigkeit leben können, bis Sie zu Java 8 kommen, sollten Sie alle Chancen haben. Die neueren Klassen sind wesentlich programmierfreundlicher und bequemer zu handhaben. Ein einfaches Beispiel für den Einstieg:

String inputDate = "01-19-2017 06:01 -0600"; 
    DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm Z"); 
    ZonedDateTime parsedInput = ZonedDateTime.parse(inputDate, inputFormatter); 

    OffsetDateTime gmtTime = parsedInput.toOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC); 
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd-yyyy hh:mm a Z"); 
    String formattedDate = gmtTime.format(formatter); 
    System.out.println(formattedDate); // prints 01-19-2017 12:01 PM +0000 
Verwandte Themen