java SimpleDateFormat 周计算
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6754024/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SimpleDateFormat Week Calculations
提问by nevets1219
I'm getting some puzzling results with SimpleDateFormat and am hoping that someone can shed some light on the issue. The output:
我用 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
Should I be treating the last "week" of the year that extends to the next year as a special case? Or is this the correct way to interpret this? Obviously when attempting to organize week sequentially, the order is incorrect. Adjusting the initial values, Dec 25, 2005 is considered the 53rd week. I haven't looked at Joda yet to see if Joda produces similar results.
我是否应该将延续到明年的一年中的最后“一周”视为特殊情况?或者这是解释这个的正确方法吗?显然,当尝试按顺序组织一周时,顺序是不正确的。调整初始值,2005 年 12 月 25 日被视为第 53 周。我还没有看过 Joda,看看 Joda 是否会产生类似的结果。
The relevant code:
相关代码:
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 ) );
Background: I found this when using the crosstab (date grouped into week) in JasperReports.
背景:我在 JasperReports 中使用交叉表(按周分组的日期)时发现了这一点。
EDIT: I am using JDK 1.6.0_25
编辑:我使用的是 JDK 1.6.0_25
EDIT: It seems that I will have to use Joda to get the correct result. TO get the week start/end, I ended up using: LocalDate.withDayOfWeek
. To retrieve the year and week number, I used DateTime.getWeekyear
and DateTime.getWeekOfWeekyear
.
编辑:看来我将不得不使用 Joda 来获得正确的结果。为了让一周开始/结束,我最终使用了:LocalDate.withDayOfWeek
. 为了检索年和周数,我使用了DateTime.getWeekyear
和DateTime.getWeekOfWeekyear
。
回答by Mechanical snail
The bug is in your formatting code, not Java.
错误在于您的格式化代码,而不是 Java。
The surprising behavior is due to an esoteric rule in date notation. Note that ISO 8601 (rather confusingly) specifies different rules for year boundaries when using week numbers. In particular, 2010-12-27 is considered part of 2011 when using week numbers.
令人惊讶的行为是由于日期表示法中的深奥规则。请注意,当使用周数时,ISO 8601(相当令人困惑)为年份边界指定了不同的规则。特别是,在使用周数时,2010-12-27 被认为是 2011 年的一部分。
As a result, you should be using the "week year" YYYY
rather than the usual year yyyy
. (See http://download.oracle.com/javase/7/docs/api/java/util/GregorianCalendar.html#week_yearand the last example in http://download.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html.)
因此,您应该使用“week year”YYYY
而不是通常的 year 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。)
Also, the standard notation for dates uses an explicit 'W'
, so you should use new SimpleDateFormat( "YYYY-'W'ww" )
instead.
此外,日期的标准表示法使用显式'W'
,因此您应该new SimpleDateFormat( "YYYY-'W'ww" )
改用。
Edit: There's another problem. Java seems to default to the non-standard calendar.getMinimalDaysInFirstWeek() == 1
, so you have to set
编辑:还有一个问题。Java 似乎默认为 non-standard calendar.getMinimalDaysInFirstWeek() == 1
,因此您必须设置
calendar.setMinimalDaysInFirstWeek( 4 );
in order to get the correct year.
以获得正确的年份。
Edit: From reading the Calendar
javadocs, you might alsoneed to set the starting day to Monday. Further, the YYYY
format specifier seems to be new in Java 1.7. In light of this, unless you're willing to upgrade to a pre-release Java version, I recommend just using Joda Time.
编辑:通过阅读Calendar
javadocs,您可能还需要将开始日期设置为星期一。此外,YYYY
格式说明符似乎是 Java 1.7 中的新内容。鉴于此,除非您愿意升级到预发布的 Java 版本,否则我建议您只使用 Joda Time。
回答by Nivas
From ISO Week
The first week of a year is the week that contains the first Thursday of the year.
一年的第一周是包含一年的第一个星期四的那一周。
So the behavior has nothing to do with Java or Joda. This is how the "week of the year" is implemented worldwide (if they follow the ISO standard)
因此该行为与 Java 或 Joda 无关。这就是“一年中的一周”在全球范围内的实施方式(如果他们遵循 ISO 标准)
回答by othman
回答by Dilum Ranatunga
Yes, this looks to be a bug in Java, and not in the formatting code. If you print:
是的,这看起来是 Java 中的错误,而不是格式化代码中的错误。如果打印:
System.out.println("Week = " + calendar.get(Calendar.WEEK_OF_YEAR));
It also shows 1
.
它还显示1
.
If you change your date to something not so close to the end of the year, eg:
如果您将日期更改为不太接近年底的日期,例如:
calendar.set(2010, Calendar.NOVEMBER, 27);
Then the output looks right. BTW, I tested using Sun 1.6.0_25 64bit VM.
然后输出看起来正确。顺便说一句,我使用 Sun 1.6.0_25 64 位 VM 进行了测试。