我希望建立一个函数,返回一个数组,其中包含一年中前几个月的所有周数,这些周数与某个特定月份的周数相同。
我将星期一用作一周的第一天,并将当月的第一个星期一用作该月的第一周。
输入:一年中的周和年。例如,27 和 2019 年。7 月的第一周 (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]。
我在寻找什么:我有两个问题:
我认为这里的关键是理解几点(希望I从你的问题中正确理解了它们)。
得到的结果与预期不同。我觉得 问题是由于我没有指定如何计算 该月的第一周(该月的第一个星期一)。这样对吗?如何 我可以解决这个问题吗?
我相信你是对的。要计算该月的星期一,您可以使用:
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 个星期一)。发生的情况是,由于我在星期二运行您的代码,因此以第 40 周(即 10 月 1 日)的星期二作为起点,因此给了我每个月的第一周而不是第五周。
有更好的解决方案吗?你能推荐一个吗?
我真的不能。我认为你所拥有的很好。
只是您没有使用
int weekYear
参数。您可能想使用它来代替您的 weekNumber
局部变量。无论如何,您应该删除其中一个并使用另一个。
还有这个不相关的提示:您对
LocalDate.from(someLocalDate)
的使用是多余的,因为它只会再次给您相同的 LocalDate
(无论是相同的对象还是相等的对象,我不知道或关心)。在这些情况下只需使用 someLocalDate
。