Java时间:获取特定年份的最大周数

3
我只找到了Joda Time的解决方案。
我的解决方案仅适用于最后一天不在第一周的情况:
LocalDate.now() // or any other LocalDate
  .withDayOfMonth(31)
  .withMonth(12)
  .get(weekFields.weekOfWeekBasedYear())

那么在Java Time中(例如在Joda Time中),什么是正确的方式?


所以您正在尝试确定当前年份是否有52或53个(编号)周,我理解得对吗?是针对美国或国际周编号,还是两者都适用? - Ole V.V.
根据国际标准化组织的规定,一周所属的年份至少有四天在该周内。因此,你可以查询12月28日所属的周数。由于这一天之后只有三天,它肯定是当年最后一个编号的周。有点棘手,我承认。同样地,1月4日总是在第一周。 - Ole V.V.
请注意,您的代码仅在拥有31天的月份运行时才能正常工作!您需要交换两行代码:.withDayOfMonth(31).withMonth(12) - steffen
4个回答

12

这个信息可以直接使用java.time.* API获取。

其中关键方法是TemporalField上的rangeRefinedBy(Temporal)方法。它允许您获取一个ValueRange对象,该对象提供了由传入的时间对象细化后的字段最小和最大值。

要找出一年中有多少个ISO周,请按照以下步骤进行:

LocalDate date = LocalDate.of(2015, 6, 1);
long weeksInYear = IsoFields.WEEK_OF_WEEK_BASED_YEAR.rangeRefinedBy(date).getMaximum();
System.out.println(weeksInYear);

请注意,您传递的日期用于确定答案。因此,在传递1月初或12月末的日期时,确保您了解ISO基于周的日历的工作原理以及日历年和基于周的年份之间的区别。


1
令我惊奇的是,现在Java 8时间库拥有如此丰富的功能。 - YoYo

1
如果想要基于7天获取周数,不管一周从何时开始以及一年中的第一个部分周有多少天,ChronoField.ALIGNED_WEEK_OF_YEAR可能会有所帮助。
例如,根据ISO-8601定义(其中一周从星期一开始,第一周最少有4天),2016年1月1日属于第0周,但在对齐后它是第1周。
    LocalDate date = LocalDate.of(2016, 1, 1);

    int iso8601 = date.get(WeekFields.ISO.weekOfYear()); // result is 0

    int aligned = date.get(ChronoField.ALIGNED_WEEK_OF_YEAR); // result is 1

0

看起来当最后一天在第一周时,你不想得到1作为答案,而是52/3/4,这种情况下你可能正在寻找:

LocalDate.of(2017, 12, 31).get(WeekFields.ISO.weekOfYear());

定义周数有几种方法-如果这不能满足您的需求,您需要澄清要使用哪种方法。


1
尝试使用2012年、2013年、2014年和2015年:您应该得到53。 - assylias
抱歉,我的测试有问题。这些年来我确实得到了53。 - Ole V.V.

0

正确且最佳的解决方案由@JodaStephen提供。无论如何,这里还有一些替代方案。

12月28日总是在一年的最后一周,因为之后的三天无法组成另一个完整的星期:

int weeks = LocalDate.of(2017, 12, 28).get(WeekFields.ISO.weekOfYear());

一年有53个星期,如果它以星期四开始或结束:
Year year = Year.of(2017);
DayOfWeek firstDay = year.atDay(1).getDayOfWeek();
DayOfWeek lastDay = year.atDay(year.length()).getDayOfWeek();
int weeks = firstDay == DayOfWeek.THURSDAY || lastDay == DayOfWeek.THURSDAY ? 53 : 52;

最后,这将为您提供一年中最后一天的“周数”。在最后一周的数字为52的情况下,如果最后一天所在周的主要部分位于下一年(该周由下一年声明),则它也是53。
// This will not give the correct number of weeks for a given year
Year year = Year.of(2018);
year.atDay(year.length()).get(WeekFields.ISO.weekOfYear()); // 53

那就是你实际上所做的。


没有完全理解问题的情况下,我尝试了2010年至2020年间的所有年份。在2015年和2020年,我得到了53周。在2010年、2011年、2016年和2017年,我得到了52周。我相信这些都是正确的。但令我困惑的是,对于2012年、2013年、2014年、2018年和2019年,第一段代码段得到了53周,而第二段代码却只有52周。 - Ole V.V.
谢谢满足我的好奇心,我现在认为我理解了它们的区别。 - Ole V.V.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接