【问题标题】:SimpleDateFormat Week CalculationsSimpleDateFormat 周计算
【发布时间】:2011-07-19 20:55:35
【问题描述】:

我在使用 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

【问题讨论】:

  • +1 用于提出日期表示中的一个微妙问题。请参阅下面的答案。

标签: java date simpledateformat


【解决方案1】:

错误在于您的格式化代码,而不是 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。

【讨论】:

  • 好吧,升级到 Java 1.7 是不可能的,所以我暂时只能使用 Joda。
【解决方案2】:

来自ISO Week

一年的第一周是包含第一个星期四的那一周 年度最佳。

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

【讨论】:

    【解决方案3】:

    standadr java Date & Time 类设计得不好,有时不能按预期工作。改用Joda Time

    【讨论】:

    • 虽然你的说法是正确的,但在这种情况下应该没有任何区别。问题是如何计算“周数”
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 2020-04-23
      • 1970-01-01
      • 1970-01-01
      • 2020-11-22
      • 2016-09-15
      • 1970-01-01
      • 1970-01-01
      • 2011-04-06
      相关资源
      最近更新 更多