2013-07-15 144 views
0

我想以字符串格式比較兩個日期,並以HH:MM:SS:SSS的結果作爲字符串返回結果。 當我嘗試使用15 Jul 2013 17:08:34.903的開始日期和結束日期 15 Jul 2013 17:08:51.247運行以下內容時,我期望看到00:00:16.344的結果。相反,我得到01:00:16.344的差異。任何想法,爲什麼會這樣?SimpleDateFormat比較問題

private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("d MMM yyyy HH:mm:ss.SSS"); 
    private static final SimpleDateFormat DATE_FORMAT_HH_MM_SS = new SimpleDateFormat("HH:mm:ss.SSS"); 

    public String calculateDuration(String startDateStr, String endDateStr){ 

     String methodName = "calculateDuration"; 
     try {   
      Date startDate = DATE_FORMAT.parse(startDateStr); 
      Date endDate = DATE_FORMAT.parse(endDateStr);   
      long diff = endDate.getTime() - startDate.getTime();   
      return DATE_FORMAT_HH_MM_SS.format(diff); 
+0

這是Java嗎?考慮給它語言標記 – doctorlove

+0

是你的TZ UTC + 1? –

+2

我認爲你應該使用[* JodaTime *](http://joda-time.sourceforge.net/)來計算時間差(持續時間)。這將簡化你的生活。 – LaurentG

回答

0

JDK Date API太糟糕了。我建議使用Joda Time庫,但如果必須使用JDK日期API試試這個代碼:

private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(
     "d MMM yyyy HH:mm:ss.SSS"); 

public String calculateDuration(String startDateStr, String endDateStr) 
     throws ParseException { 

    String methodName = "calculateDuration"; 
    Date startDate = DATE_FORMAT.parse(startDateStr); 
    Date endDate = DATE_FORMAT.parse(endDateStr); 

    // in milliseconds 
    long diff = endDate.getTime() - startDate.getTime(); 

    long diffMiliseconds = diff % 1000; 
    long diffSeconds = diff/1000 % 60; 
    long diffMinutes = diff/(60 * 1000) % 60; 
    long diffHours = diff/(60 * 60 * 1000) % 24; 

    return String.format("%02d:%02d:%02d.%02d", diffHours, diffMinutes, 
      diffSeconds, diffMiliseconds); 
} 
0

您還沒有初始化日曆對象你的SimpleDateFormat格式化,所以它使用的是默認的一個做的映射。我猜測這個默認日曆正在識別DST。這在您使用.parse()日期時間時不會顯示,因爲DST調整會在相減中取消。

當您將結果轉換爲HMS格式時,格式化程序會再次應用DST調整。由於在這一步中沒有減法,它會出現在你的結果中。

在我看來,只要有人有日期算術問題,橡皮圖章,膝蓋反射回應就是「使用JodaTime」。我們都喜歡JodaTime;它是一個精心設計的API。但使用它仍然是一個外部依賴,除非你需要 - 它不應該使用它。在我看來,對於這種情況,您根本不需要JodaTime ...您只需要Java日曆API就可以將日期時間解析爲日期。這就是你需要的。

一旦你在毫秒的差異,你真的應該避免使用格式化器轉換結果。使用簡單的算術題會更高性能:

private static final SimpleDateFormat DATE_FORMAT = 
    new SimpleDateFormat("d MMM yyyy HH:mm:ss.SSS"); 

private static final int DAYS = 0; 
private static final int HOURS = 1; 
private static final int MINUTES = 2; 
private static final int SECONDS = 3; 
private static final int MILLIS = 4; 
private final int[] result = new int[MILLIS]; 

public String calculateDuration(String startDateStr, String endDateStr){ 

    try {   
     Date startDate = DATE_FORMAT.parse(startDateStr); 
     Date endDate = DATE_FORMAT.parse(endDateStr); 
    } catch (Exception e) { /* exception processing */ } 

    long diff = endDate.getTime() - startDate.getTime();   

    double d; 
    for (int i = DAYS; i <= MILLIS; i++) {  
     switch(i) { 
      case DAYS: 
       d = ((double) diff)/(86400.0 * 1000.0); 
       break; 
      case HOURS: 
       d = d * 24.0; break; 
      case MINUTES: case SECONDS: 
       d = d * 60.0; break; 
      case MILLIS: 
       d = d * 1000.0; break; 
     } 
     result[i] = (int) Math.floor(d); 
     d = d - (double) result[i]; 
    } 

在這最後for循環結束時,陣列result包含對應天數的整數,小時,分鐘,秒和MILLIS從您的日期派生減法。爲了得到這個結果,不需要創建,分配或調用對象。您現在可以輕鬆使用String.format()函數將這些整數轉換爲您選擇的字符串格式。

+0

我要求在JodaTime的問題上有所不同。儘管我同意一個人不必總是使用它,但我仍然喜歡指出這些問題,因爲它使日曆數據的處理變得更容易,有些人還沒有聽說過。我很高興當我第一次詢問有關日曆和日期的事情時,我向喬達指出了這一點。 –

+0

@JannisAlexakis:日期對象之間的減法通常不需要日曆API。在這種情況下,使用Calendar API不僅會慢很多,而且會導致錯誤,因爲生成的時間間隔會映射(有點錯誤)到日曆日期。外部依賴關係就是它們。如果普遍認爲在可能的情況下最好放棄它們,那麼我認爲我們可以同意在這種情況下可以放棄一個。 – scottb

0

由於在評論中你說你只是測量應用程序的運行時間,所以根本不涉及Date,SimpleDateFormat或Calendar。

long tic = System.nanoTime(); 

...就是你所需要的。當你手上有蒼蠅拍時,不要使用大炮殺死蚊子。