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周。 我还没有看过Joda,看看Joda是否会产生类似的结果。

相关代码:

 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

编辑:似乎我将不得不使用Joda来获得正确的结果。 为了得到周开始/结束,我最终使用: LocalDate.withDayOfWeek 。 为了检索年份和周数,我使用了DateTime.getWeekyearDateTime.getWeekOfWeekyear

错误在您的格式化代码中,而不是Java。

令人惊讶的行为是由于日期符号中的深奥规则。 请注意,ISO 8601(相当令人困惑)在使用周数时为年份边界指定了不同的规则。 特别是,2010-12-27被认为是使用周数的2011年的一部分。

因此,您应该使用“周年” YYYY而不是通常的年份yyyy 。 (请参阅http://download.oracle.com/javase/7/docs/api/java/util/GregorianCalendar.html#week_year以及http://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。

standadr java Date&Time类设计不合理,有时无法按预期工作。 使用Joda Time代替

来自ISO周

一年的第一周是包含一年中第一个星期四的一周。

所以这种行为与Java或Joda无关。 这就是全球实施“一年中的一周”(如果它们遵循ISO标准)

是的,这看起来是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进行了测试。