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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 17:08:10  来源:igfitidea点击:

SimpleDateFormat Week Calculations

javadatesimpledateformat

提问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.getWeekyearand DateTime.getWeekOfWeekyear.

编辑:看来我将不得不使用 Joda 来获得正确的结果。为了让一周开始/结束,我最终使用了:LocalDate.withDayOfWeek. 为了检索年和周数,我使用了DateTime.getWeekyearDateTime.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" YYYYrather 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 Calendarjavadocs, you might alsoneed to set the starting day to Monday. Further, the YYYYformat 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.

编辑:通过阅读Calendarjavadocs,您可能需要将开始日期设置为星期一。此外,YYYY格式说明符似乎是 Java 1.7 中的新内容。鉴于此,除非您愿意升级到预发布的 Java 版本,否则我建议您只使用 Joda Time。

回答by Nivas

From ISO Week

ISO 周

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

the standadr java Date & Time classes are not well designed and sometimes don't work as expected. use instead Joda Time

标准 java 日期和时间类设计得不好,有时不能按预期工作。改用Joda 时间

回答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 进行了测试。