2011-07-19 140 views
7

我收到了一些令人費解的結果SimpleDateFormat,並希望有人可以在這個問題上提出一些看法。輸出:SimpleDateFormat周計算

Time   = Mon Dec 27 00:00:00 PST 2010 
2010-01 <--- THIS IS WHAT I DON'T UNDERSTAND 
Start of week = Sun Dec 26 00:00:00 PST 2010 
2010-01 
End of Week = Sat Jan 01 23:59:59 PST 2011 
2011-01 

我應該處理延伸到明年作爲一個特殊的情況下,一年的最後一個「周」?或者這是解釋這個問題的正確方法?很顯然,當試圖按順序組織周時,訂單是不正確的。調整初始值,2005年12月25日被認爲是第53周。我還沒有看過喬達,看看喬達是否也有類似的結果。

相關的代碼:

private static Date getStartOfWeek(Date d) { 
    Calendar calendar = Calendar.getInstance(); 
    calendar.clear(); 
    calendar.setTime(d); 

    calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek()); 

    return calendar.getTime(); 
} 

private static Date getEndOfWeek(Date d) { 
    Calendar calendar = Calendar.getInstance(); 
    calendar.clear(); 

    calendar.setTime(d); 
    calendar.add(Calendar.WEEK_OF_YEAR, 1); 
    calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek()); 
    calendar.add(Calendar.MILLISECOND, -1); 

    return calendar.getTime(); 
} 


Calendar calendar = Calendar.getInstance(); 
calendar.clear(); 
calendar.set(2010, Calendar.DECEMBER, 27); 
Date d = calendar.getTime(); 
Date start = getStartOfWeek(d); 
Date end = getEndOfWeek(d); 
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-ww"); 

System.out.println("Time   = " + d); 
System.out.println(fmt.format(d)); 
System.out.println("Start of week = " + start); 
System.out.println(fmt.format(start)); 
System.out.println("End of Week = " + end); 
System.out.println(fmt.format(end)); 

背景:我發現這個使用JasperReports的交叉表(日期分爲周)時。

編輯:我使用的是JDK 1.6.0_25

編輯:看來,我將不得不使用喬達來得到正確的結果。爲了獲得一週的開始/結束,我結束了使用:LocalDate.withDayOfWeek。爲了檢索年份和週數,我使用了DateTime.getWeekyearDateTime.getWeekOfWeekyear

+0

+1在日期表示中引發一個微妙的問題。請參閱下面的答案。 –

回答

14

該錯誤發生在您的格式化代碼中,而不是Java。

令人驚訝的行爲是由於日期符號中的祕法。請注意,使用星期編號時,ISO 8601(相當困惑地)爲年邊界規定了不同的規則。尤其是,2010-12-27在使用週數時被認爲是2011年的一部分。

因此,您應該使用「週年」YYYY而不是通常的年份yyyy。 (見http://download.oracle.com/javase/7/docs/api/java/util/GregorianCalendar.html#week_yearhttp://download.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html最後一個例子。)

此外,對於日期的標準符號使用顯式'W',所以你應該使用new SimpleDateFormat("YYYY-'W'ww")代替。

編輯:還有一個問題。 Java的似乎默認爲非標準calendar.getMinimalDaysInFirstWeek() == 1,所以你必須設置

calendar.setMinimalDaysInFirstWeek(4); 

,以獲得正確的年份。

編輯:從閱讀Calendar javadocs,你可能需要開始日期設置爲星期一。此外,YYYY格式說明符在Java 1.7中似乎是新的。鑑於此,除非您願意升級到預發佈Java版本,否則我建議僅使用Joda Time。

+0

那麼升級到Java 1.7是不可能的,所以我將不得不暫時使用Joda。 – nevets1219

1

standadr java日期&時間等級設計不好,有時無法按預期工作。改用Joda Time

+0

雖然您的陳述是正確的,但在這種情況下,應該沒有任何區別。問題是如何計算「週數」 – Nivas

-2

是的,這看起來是Java中的一個錯誤,而不是格式化代碼。如果您打印:

System.out.println("Week = " + calendar.get(Calendar.WEEK_OF_YEAR)); 

它也顯示1

如果你更改日期的東西不那麼接近年底,如:

calendar.set(2010, Calendar.NOVEMBER, 27); 

那麼輸出看起來正確。順便說一句,我使用Sun 1.6.0_25 64位VM進行測試。

1

ISO Week

一年的第一週是包含第一個星期四今年 一週。

所以這個行爲與Java或Joda無關。這就是「全年的一週」如何在全球實施(如果他們遵循ISO標準)