繁体   English   中英

Java Calendar WEEK_OF_YEAR不符合ISO-8601标准?

[英]Java Calendar WEEK_OF_YEAR not ISO-8601compliant?

ISO-8601标准规定了这一点

“一年的第一周是包含一年中第一个星期四的一周(因此,总是包含1月4日)。”

这意味着一年中的第一周不是包含1月1日的那一周,而是包含在新年四天的第一个星期。

根据周一,2016年1月11日是第2周。 以下是2016年的周数列表。

Ubuntu在其时间小部件中反映出:

在此输入图像描述

而且cal命令也有:

在此输入图像描述

Oracle使用TO_CHAR的“iw”参数支持它:

> select to_char(to_date('11/01/2016','dd/mm/yyyy'),'iw') weekno from dual;
> WEEKNO
    02

但Java表示2016年1月11日星期一是第3周

Calendar c = Calendar.getInstance();
System.out.println(c.getTime());
System.out.println(c.get(Calendar.WEEK_OF_YEAR));

Output:
Mon Jan 11 09:02:35 VET 2016
3

Java认为一年中的第一周是包含1月1日的那一周。

- Java是否有办法使用符合ISO-8601标准的周编号?

正如我在评论中指出的那样, 默认行为是特定于语言环境的。 一些语言环境会给出3,有些会给出2。

幸运的是,对于给定的Calendar ,您可以指定一年中第一周必须出现的天数。 如上所述,对于ISO 8601,此数字为4 ,因此以下代码应该有效:

Calendar c = Calendar.getInstance();
c.setMinimalDaysInFirstWeek(4); // For ISO 8601
System.out.println(c.getTime());
System.out.println(c.get(Calendar.WEEK_OF_YEAR));

无论语言环境如何,这都应该使输出正确。

测试输出:

Mon Jan 11 14:54:22 CET 2016
2

TL;博士

myZonedDateTime.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) 

…和…

myZonedDateTime.get( IsoFields.WEEK_BASED_YEAR )

避免遗留日期时间类

正如haraldK正确答案所解释的那样, Calendar类对周的定义因地区而异 善意的,这是令人困惑的。

您应该避免使用Calendar和相关类,例如Date 它们现在被java.time类取代。

ISO 8601周

至于ISO 8601周 ,明确表示:

  • 第一天是星期一,一直持续到星期日。
  • 基于周的年份的第一周包含该日历年的第一个星期四。
  • 以工作周为基础的一年有52周或53周。
  • 一个日历年的第一个/最后几天可能出现在上一个/下一周的年份中。

java.time

java.time类包括对ISO 8601标准周的有限支持。 在各种类(如LocalDateZonedDateTime上调用get方法。 传递在IsoFields类中作为常量找到的TemporalField实现。

int week = myZonedDateTime.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) ;
int weekBasedYear = myZonedDateTime.get( IsoFields.WEEK_BASED_YEAR ) ;

ThreeTen-EXTRA

更好的是,将ThreeTen-Extra库添加到项目中以使用YearWeek类。

org.threeten.extra.YearWeek yw = YearWeek.from( myZonedDateTime ) ;

注意日历软件设置

永远不要假设周数的定义。 确保此类数字的来源与您的周定义相同,例如ISO 8601定义。

例如, Apple提供的macOS 日历应用程序默认为星期的“格里高利”日历定义。 至于那意味着什么,我不知道,因为我找不到任何关于他们的意图/定义的文件。 对于ISO 8601周,您必须更改默认设置


关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

现在处于维护模式Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle教程 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310

使用符合JDBC 4.2或更高版本的JDBC驱动程序 ,您可以直接与数据库交换java.time对象。 不需要字符串也不需要java.sql。*类。

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM