Perdere un'ora al ritorno di un gennaio 1970 Data di millisecondi
-
26-10-2019 - |
Domanda
ho il seguente codice che prende una stringa di millisecondi (sarà da un feed RSS così sarà una stringa, l'esempio seguente è un programma di test rapido) e converte tali Millis in un oggetto Date.
public static void main(String[] args) {
String ms = "1302805253";
SimpleDateFormat dateFormatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(Long.parseLong(ms));
try {
String dateFormat = dateFormatter.format(calendar.getTime());
System.out.println("Date Format = " + dateFormat);
Date dateParse = dateFormatter.parse(dateFormatter.format(calendar.getTime()));
System.out.println("Date Parse = " + dateParse);
} catch (ParseException e) {
// TODO: handle exception
}
}
Output:
Date Format = Fri, 16 Jan 1970 02:53:25 GMT
Date Parse = Fri Jan 16 03:53:25 GMT 1970
Come si può vedere, tra la formattazione dell'oggetto di calendario e l'analisi della risultante String, un'ora si sta perdendo. Inoltre, la formattazione dell'output è cambiato. Qualcuno può aiutarmi per spiegare perché questo sta accadendo, e come ottenere intorno ad esso? Voglio che l'oggetto Date per essere lo stesso formato di uscita "Formato data".
Soluzione
Credo che sta accadendo, perché il Regno Unito non effettivamente usare GMT nel 1970 ha fatto, e Java ha un bug in giro che ... lo farà formato una data nel 1970 come se il Regno Unito sono state usando GMT, ma senza realmente cambiare l'offset. Semplice esempio:
Date date = new Date(0);
SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss zzz");
sdf.setTimeZone(TimeZone.getTimeZone("Europe/London"));
System.out.println(sdf.format(date));
Risultato:
01 Jan 1970 01:00:00 GMT
Si noti che afferma che di 1:00 GMT ... che non è corretto. E ' è stata ??em> 01:00 in tempo Europe / London, ma l'Europa / Londra non stava osservando GMT.
Joda Tempo ottiene questo diritto in quanto esso stampa BST - ma Joda il tempo non come < em> analisi i valori con le abbreviazioni di fuso orario. Tuttavia, è possibile ottenere in modo da utilizzare il fuso orario offets , invece:
import org.joda.time.*;
import org.joda.time.format.*;
public class Test {
public static void main(String[] args) throws Exception {
DateTime date = new DateTime(0, DateTimeZone.forID("Europe/London"));
DateTimeFormatter formatter = DateTimeFormat.forPattern(
"dd MMM yyyy HH:mm:ss Z");
String text = formatter.print(date); // 01 Jan 1970 01:00:00 +0100
System.out.println(text);
DateTime parsed = formatter.parseDateTime(text);
System.out.println(parsed.equals(date)); // true
}
}
Altri suggerimenti
La risposta da Jon Skeet è corretta.
java.time
corriamo lo stesso ingresso attraverso java.time per vedere i risultati.
corretta oraria Nome . Non usare mai il 3-4 lettera sigla come BST
, EST
, o IST
in quanto non sono zone tempo vero, non standardizzati, e nemmeno unico (!). Quindi usiamo Europe/London
.
Il Instant
classe rappresenta un momento sulla timeline in UTC con una risoluzione di nanosecondi .
String input = "1302805253";
long millis = Long.parseLong ( input );
Instant instant = Instant.ofEpochMilli ( millis );
Applicare un fuso orario per la produzione di un oggetto ZonedDateTime
.
ZoneId zoneId = ZoneId.of ( "Europe/London" );
ZonedDateTime zdt = instant.atZone ( zoneId );
Dump alla console. Vediamo infatti che il tempo è un Europe/London
avanti ora UTC in quel momento. Così il giorno tempo di è ora 02
anziché ore 01
. Entrambi rappresentano lo stesso momento simultanea sulla timeline, visto solo attraverso le lenti di due differenti volte parete orologio .
System.out.println ( "input: " + input + " | instant: " + instant + " | zdt: " + zdt );
ingresso: 1302805253 | istante: 1970-01-16T01: 53: 25.253Z | zdt: 1970-01-16T02: 53: 25,253 + 01: 00 [Europe / London]
secondi interi
A proposito, ho il sospetto la stringa di input rappresenta interi secondi dal periodo del 1970 UTC, piuttosto che millisecondi . Interpretato che come secondi si ottiene una data nel 2011, nel corso del mese a questa Domanda pubblicato.
String output = Instant.ofEpochSecond ( Long.parseLong ( "1302805253" ) ).atZone ( ZoneId.of ( "Europe/London" ) ).toString ();
2011-04-14T19: 20: 53 + 01: 00 [Europe / London]
A proposito di java.time
Il java.time quadro è integrato in Java 8 e versioni successive. Queste classi soppiantare le vecchie classi data-ora problematici, come java.util.Date
, .Calendar
, e java.text.SimpleDateFormat
.
Il Joda Time progetto, ora in modalità manutenzione , consiglia migrazione java.time.
Per ulteriori informazioni, vedere la Oracle Tutorial . E cercare Stack Overflow per molti esempi e spiegazioni.
La maggior parte delle funzionalità java.time è di back-porting per Java 6 & 7 a ThreeTen-Backport e in seguito atto a Android in ThreeTenABP .