2010-01-21 84 views
2

我有一個日期作爲java.sql.Timestamp存儲在數據庫中。日期爲「2010-01-20T19:10:3​​5.000Z」,相當於1264014635743毫秒。什麼可能導致此SimpleDateFormat格式錯誤?

不知何故,與開發機器相比,prod機器上的日期格式不同。

的代碼格式的日期是:

private final static String DATE_FORMAT = "yyyy-MM-dd"; 
public final static SimpleDateFormat APP_DATE_FORMATER = new SimpleDateFormat(DATE_FORMAT); 
private static final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone("Etc/UTC"); 
APP_DATE_FORMATER.setTimeZone(UTC_TIMEZONE); 
DateTimeZone.setDefault(DateTimeZone.UTC); 

String output = APP_DATE_FORMATER.format(date) 

在dev的所生成的輸出是正確的 「2010-01-20」。但是在一天之後,我有「2010-01-21」!

當然,既然督促服務器上發生的錯誤,我在我的調試選項有限...

我有雙重檢查,並且兩個服務器具有相同的時間和時區。兩個時鐘都與ntp服務器同步。


[更新]正式版數據庫的數值:「20年10月1日19:10:3​​5,743000000」爲日期字段

回答

4

我的第一個想法是,這是一個併發問題。 SimpleDateFormat不是線程安全,但您正在共享一個靜態實例。如果你需要在多線程環境中使用java.text格式化,你應該使用一個ThreadLocal追究他們:

private static ThreadLocal<DateFormat> _datetimeFormatter = new ThreadLocal<DateFormat>(); 

private static DateFormat getDatetimeFormatter() 
{ 
    DateFormat format = _datetimeFormatter.get(); 
    if (format == null) 
    { 
     format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); 
     format.setTimeZone(TimeZone.getTimeZone("GMT")); 
     _datetimeFormatter.set(format); 
    } 
    return format; 
} 

public static String formatDatetime(Date date) 
{ 
    return getDatetimeFormatter().format(date); 
} 

也有可能(但不太可能)認爲,「ETC/UTC」沒有在服務器上找到。你記錄從getTimeZone()的值?

而第三個選項是,用Inigo Montoya的意思,「你沒有運行你認爲你正在運行的代碼。」這可能是因爲您的演示文稿代碼沒有在服務器上正確卸載,或者還有其他日期格式化程序正在浮動。

+0

感謝您的線程建議。但我懷疑問題的原因是線程,因爲每次刷新頁面時,都會重新計算日期並顯示爲2010-01-21 ... – 2010-01-21 18:53:46

+0

在這種情況下,您正在查看時區問題。你能否讓系統管理員運行一個簡單的格式化並打印特定時間戳值的SSCEP? – kdgregory 2010-01-21 18:59:24

+0

我有權訪問prod服務器,但我不知道「SSCEP」是什麼(它是Windows Server 2008機器)。我通過雙擊任務欄中的日期/時間來檢查兩臺機器上的時區設置,它們是相同的。 感謝通過ThreadLocal代碼的方式! – 2010-01-21 19:32:01

2

雖然機器具有相同的時區,什麼關於數據庫設置?數據庫可能設置爲與機器不同的時區嗎?

0

您是否檢查過生產和開發機器上的JVM設置是否相同?時間可能在服務器級同步,但也許JVM設置的方式對它所處的時區有些疑惑。