简体   繁体   English

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

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

The ISO-8601 standard states that ISO-8601标准规定了这一点

"The first week of a year is the week that contains the first Thursday of the year (and, hence, always contains 4 January)." “一年的第一周是包含一年中第一个星期四的一周(因此,总是包含1月4日)。”

Meaning the first week of the year is not that which contains January the 1st but the first one that contains at leat four days into the new year. 这意味着一年中的第一周不是包含1月1日的那一周,而是包含在新年四天的第一个星期。

Acording to that Mon, January 11 2016 is on week #2. 根据周一,2016年1月11日是第2周。 Here is a list of week numbers for 2016. 以下是2016年的周数列表。

Ubuntu reflects that in its time widget: Ubuntu在其时间小部件中反映出:

在此输入图像描述

And the cal command does also: 而且cal命令也有:

在此输入图像描述

Oracle supports it with the "iw" parameter of TO_CHAR : Oracle使用TO_CHAR的“iw”参数支持它:

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

But Java says Mon, January 11 2016 is week #3 但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 thinks the first week of the year is the one that contains January the 1st. Java认为一年中的第一周是包含1月1日的那一周。

- Is there a way for Java to use the ISO-8601-copliant week numbering? - Java是否有办法使用符合ISO-8601标准的周编号?

As I noted in my comment, the default behavior is locale specific. 正如我在评论中指出的那样, 默认行为是特定于语言环境的。 Some locales will give 3, some will give 2. 一些语言环境会给出3,有些会给出2。

Luckily, you can specify the number of days that has to be present in the first week of the year, for a given Calendar . 幸运的是,对于给定的Calendar ,您可以指定一年中第一周必须出现的天数。 As you write above, for ISO 8601, this number is 4 , thus the following code should work: 如上所述,对于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));

This should make the output correct regardless of locale. 无论语言环境如何,这都应该使输出正确。

Test output: 测试输出:

Mon Jan 11 14:54:22 CET 2016
2

tl;dr TL;博士

myZonedDateTime.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) 

…and… …和…

myZonedDateTime.get( IsoFields.WEEK_BASED_YEAR )

Avoid legacy date-time classes 避免遗留日期时间类

As the correct Answer by haraldK explains, the Calendar class's definition of week varies by locale . 正如haraldK正确答案所解释的那样, Calendar类对周的定义因地区而异 While well-intentioned, this is confusing. 善意的,这是令人困惑的。

You should be avoiding Calendar and related classes such as Date . 您应该避免使用Calendar和相关类,例如Date They are now supplanted by the java.time classes. 它们现在被java.time类取代。

ISO 8601 week ISO 8601周

As for ISO 8601 week , be clear that means: 至于ISO 8601周 ,明确表示:

  • The first day is Monday, running through Sunday. 第一天是星期一,一直持续到星期日。
  • Week number one of a week-based year contains the first Thursday of the calendar year. 基于周的年份的第一周包含该日历年的第一个星期四。
  • A week-based year has either 52 or 53 weeks. 以工作周为基础的一年有52周或53周。
  • The first/last few days of a calendar year may appear in the previous/next week-based year. 一个日历年的第一个/最后几天可能出现在上一个/下一周的年份中。

java.time java.time

The java.time classes include limited support for ISO 8601 standard weeks . java.time类包括对ISO 8601标准周的有限支持。 Call the get method on various classes such as LocalDate and ZonedDateTime . 在各种类(如LocalDateZonedDateTime上调用get方法。 Pass the TemporalField implementations found as constants in the IsoFields class. 传递在IsoFields类中作为常量找到的TemporalField实现。

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

ThreeTen-Extra ThreeTen-EXTRA

Even better, add the ThreeTen-Extra library to your project to use YearWeek class. 更好的是,将ThreeTen-Extra库添加到项目中以使用YearWeek类。

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

Beware of calendaring software settings 注意日历软件设置

Never assume the definition of a week number. 永远不要假设周数的定义。 Be sure the source of such a number has the same definition of week as you, such as ISO 8601 definition. 确保此类数字的来源与您的周定义相同,例如ISO 8601定义。

For example, the Calendar app supplied by Apple with macOS defaults to a "Gregorian" calendar definition of week. 例如, Apple提供的macOS 日历应用程序默认为星期的“格里高利”日历定义。 As for what that means, I do not know as I could not find any documentation about their intent/definition. 至于那意味着什么,我不知道,因为我找不到任何关于他们的意图/定义的文件。 For ISO 8601 weeks, you must change a setting away from default . 对于ISO 8601周,您必须更改默认设置


About java.time 关于java.time

The java.time framework is built into Java 8 and later. java.time框架内置于Java 8及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat . 这些类取代了麻烦的旧遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes. 现在处于维护模式Joda-Time项目建议迁移到java.time类。

To learn more, see the Oracle Tutorial . 要了解更多信息,请参阅Oracle教程 And search Stack Overflow for many examples and explanations. 并搜索Stack Overflow以获取许多示例和解释。 Specification is JSR 310 . 规范是JSR 310

Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. 使用符合JDBC 4.2或更高版本的JDBC驱动程序 ,您可以直接与数据库交换java.time对象。 No need for strings nor java.sql.* classes. 不需要字符串也不需要java.sql。*类。

Where to obtain the java.time classes? 从哪里获取java.time类?

The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目使用其他类扩展了java.time。 This project is a proving ground for possible future additions to java.time. 该项目是未来可能添加到java.time的试验场。 You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more . 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

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

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