tl;博士
int iso8601WeekNumber =
ZonedDateTime.now( ZoneId.of ( "America/Montreal" ) )
.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR )
一周的多种定义
一周有很多定义。
对于某些人来说,一周的第一天是星期日,有些人是星期一,还有一些人是其他一天。
对于某些人来说,一年中的第一周包含 1 月 1 日,而另一些人则将第一周视为包含上述工作日开始的那一周,而其他人则将第一周视为包含特定日期-星期。
因此,您应该在没有研究文档的情况下,永远不要假设“周”或“周数”的含义。
避免使用旧的日期时间类
一般来说,您应该避免与 Java 的早期版本捆绑在一起的旧的遗留日期时间类,因为它们设计不佳、令人困惑且麻烦。
具体来说,java.util.Calendar 类的星期定义因地区而异。因此,如果您想要可靠的恒定结果,请不要使用它。
ISO 8601
ISO 8601 标准定义了日期时间值的格式和相关问题。它specifically defines一周和一年中的一周的含义:
- 每周从周一到周日,编号为 1-7,其中周一 = 1。
- 第 1 周包含一年中的第一个星期四,每年产生 52 或 53 周。
乔达时间
Joda-Time 库使用 ISO 8601 标准定义的一周和一年中的一周。
但是,请注意 Joda-Time 项目现在位于 maintenance mode,团队建议迁移到 java.time。
java.time
java.time 类使用 ISO 8601 定义的一周:第 1 周有第一个星期四,一周从星期一到星期日。
IsoFields 类定义了基于周的年份。我们可以要求:
首先我们得到当前的日期时间。
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
询问该日期时间对象,询问基于周的标准年份。
int week = now.get ( IsoFields.WEEK_OF_WEEK_BASED_YEAR );
int weekYear = now.get ( IsoFields.WEEK_BASED_YEAR );
转储到控制台。
System.out.println ( "now: " + now + " is week: " + week + " of weekYear: " + weekYear );
现在:2016-01-17T20:55:27.263-05:00[America/Montreal] is week: 2 of weekYear: 2016
有关详细信息,请参阅此类似问题:How to calculate Date from ISO8601 week number in Java。
WeekFields
在java.time中你也可以调用WeekFields类,比如WeekFields.ISO.weekBasedYear()。应该与 Java 8 或更高版本中的 IsoFields 具有相同的效果(Java 8 的早期版本中的一些 bugs were fixed)。
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、.Calendar 和 java.text.SimpleDateFormat。
Joda-Time 项目现在位于maintenance mode,建议迁移到 java.time。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。