如何使用 Java 找到一年中每月 # 周的所有周数?



我希望建立一个函数,该函数返回一个数组,其中包含一年中前几个月的所有周数,这些周数与某个特定月份的周数相同。

我使用星期一作为一周的第一天,我将本月的第一个星期一作为每月的第一周。

输入:一年中的一周和一年。例如,27 和 2019。七月的第一周 (7(.

输出:月份的一周数组。例如,[2, 6, 10, 14, 19, 23, 27]。

我尝试什么

private void getResult(int weekYear)
{
LocalDate date = LocalDate.now();
final int weekNumber = 27;
LocalDate newDate = date.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber);
int month = newDate.getMonthValue();;

int weekMonth = LocalDate.from(newDate).get(WeekFields.ISO.weekOfMonth());

System.out.println(newDate);
System.out.println(month);
System.out.println(weekMonth);

ArrayList<Integer> list = new ArrayList<Integer>();

for (int i = 1; i <= month; i++)
{
LocalDate tempDate = date.withYear(2019).withMonth(i).with(WeekFields.ISO.weekOfMonth(), weekMonth);
int tempYear = LocalDate.from(tempDate).get(WeekFields.ISO.weekOfWeekBasedYear());
list.add(tempYear);
}

list.forEach((e) -> System.out.print(e + " "));
}
int weekYear = 27;
getResult(weekYear);

我得到的:[1 6 10 14 18 23 27]。

在寻找什么:我有两个问题:

  1. 第一:获得的结果与预期不同。我认为问题是由于我没有指定如何计算该月的第一周(每月的第一个星期一(。对吗?我该如何解决这个问题?
  2. 第二个:什么是更好的解决方案?

这里的关键是理解几点:

  1. 您以两种不同的方式对周进行编号。对于一年中的一周,您使用 ISO 编号:一年的第一周是包含至少 4 天的新年。对于每月的一周,您正在计算星期一(您可能会说该月的第一周是包括该月七天的一周,而不是四天(。
  2. 周数可能并不总是存在。如果您的起点在当月的第 0 周或第 5 周,则前一个月可能没有该周。

获得的结果与预期的结果不同。我认为 问题是由于我没有指定如何计算 每月的第一周(每月的第一个星期一(。对吗?如何 我能解决吗?

你是对的。要计算每月的星期一,您可以使用:

LocalDate tempDate = date.withYear(2019)
.withMonth(i)
.with(ChronoField.DAY_OF_WEEK, DayOfWeek.MONDAY.getValue())
.with(ChronoField.ALIGNED_WEEK_OF_MONTH, weekMonth);

(当然,DayOfWeek.MONDAY.getValue()只是啰嗦的1表达方式,但更好地传达了意图,所以我更喜欢它。

通过对代码的此更改,输出是预期的:

2 6 10 14 19 23 27

关键是ChronoField.ALIGNED_WEEK_OF_MONTH.一个月的对齐周从每月的 1 号开始,无论一周中的哪几天,始终为 7 天。第一个对齐周是从每月的 1 日到 7 日,如果从 8 日到 14 日,则为第二个对齐周,依此类推。由于我们已将星期几设置为星期一,因此将对齐的周设置为 1 会给我们每月的第一个星期一,依此类推。

我们还没有完成。如果我将weekNumber设置为 40,我会得到:

2 6 10 14 14 23 27 27 36 41

我原以为 40 是列表中的最后一个数字,但它不存在。2019年第40周是从9月30日星期一到10月6日,所以如果我理解正确的话,你想要的是那些有第5周的月份的第5周。这让我们回到了并非每个月都有第 5 周的问题(因为他们没有 5 个星期一(。发生的事情是,由于我在星期二运行您的代码,因此以第 40 周的星期二(即 10 月 1 日(为起点,因此给了我每月的第 1 周而不是第 5 周。

有更好的解决方案吗?你能推荐一个吗?

我真的不能。你得到的很好。

只是您没有使用int weekYear参数。您可能希望使用它来代替weekNumber局部变量。在任何情况下,您都应该删除其中一个并使用另一个。

这个不相关的提示:你对LocalDate.from(someLocalDate)的使用是多余的,因为它只是再次给你相同的LocalDate(要么是相同的对象,要么是相等的对象,我不知道也不在乎(。只需在这些情况下使用someLocalDate即可。

最新更新