2011-07-19 105 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标准)