2011-09-23 13 views
14
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("America/New_York")); 
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); 
df.setTimeZone(TimeZone.getTimeZone("America/New_York")); 

try { 
    System.out.println(df.format(cal.getTime())); 
    System.out.println(df.parse(df.format(cal.getTime()))); 
} catch (ParseException e) { 
    e.printStackTrace(); 
} 

Ecco il risultato:Java DateFormat parse() non rispetta il fuso orario

2011-09-24 14:10:51 -0400

sab 24 set 20:10 : 51 CEST 2011

Perché quando analizzo una data ottengo dal formato() non rispetta il fuso orario?

risposta

23

Si sta stampando il risultato della chiamata Date.toString(), che sempre utilizza il fuso orario predefinito. Fondamentalmente, non si dovrebbe usare Date.toString() per qualcosa di diverso dal debug.

Non dimenticare che un Date non avere un fuso orario - rappresenta un istante di tempo, misurato come millisecondi dalla Unix Epoch (mezzanotte del 1 Gennaio 1970 UTC).

Se si formatta di nuovo la data utilizzando il formattatore, è necessario che crei la stessa risposta di prima.

Per inciso, vorrei raccomandare l'uso di Joda Time anziché Date/Calendar se si sta facendo una quantità significativa di data/ora in Java; è una API più bella.

+1

Proprio così ... prova a stampare 'System.out.println (df.format (df.parse (df.format (cal.getTime())))); 'e funziona come previsto :-) –

+0

Ok, apparentemente il problema viene dal toString()? Grazie per il consiglio. –

+0

@MaximeLaval: Da 'Date.toString' in particolare, sì - e devi essere consapevole che un' Date' è solo un istante, non in un particolare fuso orario o calendario. –

2

DateFormat è una classe astratta per la data/ora di formattazione di sottoclassi che formatta e analizza date o tempo in un indipendente dalla lingua maniera. La sottoclasse di formattazione data/ora, come SimpleDateFormat, consente la formattazione (ad esempio, data -> testo), l'analisi (testo -> data), e la normalizzazione. La data è rappresentata come un oggetto Date o come il millisecondi dal 1 gennaio 1970, 00:00:00 GMT.

Dal spec, è restituire il tempo EPOCH

7

DateFormat.parse() non è una query (cosa che restituisce un valore e non cambia lo stato del sistema). È un comando che ha l'effetto collaterale di aggiornare un oggetto interno Calendar. Dopo aver chiamato parse() devi accedere al fuso orario accedendo allo CalendarCalendar o chiamando DateFormat.getTimeZone(). A meno che non si desideri eliminare il fuso orario originale e utilizzare l'ora locale, non utilizzare il valore restituito Date da parse(). Utilizzare invece l'oggetto del calendario dopo l'analisi. E lo stesso vale per il metodo di formattazione. Se si desidera formattare una data, passare il calendario con le informazioni sul fuso orario nell'oggetto DateFormat prima di chiamare format(). Ecco come è possibile convertire un formato ad un altro formato di preservare il fuso orario originale:

DateFormat originalDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy"); 
    DateFormat targetDateFormat = new SimpleDateFormat("EEE., MMM. dd, yyyy"); 

    originalDateFormat.parse(origDateString); 
    targetDateFormat.setCalendar(originalDateFormat.getCalendar()); 
    return targetDateFormat.format(targetDateFormat.getCalendar().getTime()); 

E 'disordinato, ma necessario in quanto parse() non restituisce un valore che conserva fuso orario e format() non accetta un valore che definisce un fuso orario (la classe Date).