Java 8 LocalDate:确定每月的星期一(第 1、2、3 等)
Java 8 LocalDate: Determine What Monday of the Month its (1st, 2nd, 3rd, etc)
我正在尝试弄清楚如何确定特定星期一是给定月份的第一个、第二个、第三个或第四个星期一。我已经弄清楚如何使用 LocalDate class.
获取下周一和本月的星期几
LocalDate now = LocalDate.of(2018, 2, 1);
LocalDate nextMonday = now.with(next(DayOfWeek.MONDAY));
WeekFields weekFields = WeekFields.of(Locale.getDefault());
int week = nextMonday.get(weekFields.weekOfMonth());
如上例,代码获取的是下周一和所在周。周是二月的第二周,但那个周一不是第二个周一,是第一个。如有任何帮助,我们将不胜感激。
您可以尝试从日期中重复减去一周,直到月份发生变化。那么你这样做的次数就是原始日期的 'Xth day of the week in the month'.
编辑:一些代码。
LocalDate now = LocalDate.of(2018, 2, 1);
int i = 0;
Month originalMonth = now.getMonth();
while (now.getMonth() == originalMonth) { // its an enum, you can do this
now = now.plusWeeks(-1);
i++;
}
System.out.println(i); // prints 1
编辑:你应该采用 Ole V.V 的答案 (ChronoField.ALIGNED_WEEK_OF_MONTH
) 而不是这个答案。
你可以算出今天是几号,除以 7,再加 1:
LocalDate nextMonday = now.with(next(DayOfWeek.MONDAY));
int weekNo = ((nextMonday.getDayOfMonth()-1) / 7) +1;
例如,这段代码:
LocalDate now = LocalDate.of(2018, 2, 1);
for(int i = 0; i < 10; i++) {
now = now.with(next(DayOfWeek.MONDAY));
int weekNo = ((now.getDayOfMonth()-1) / 7) +1;
System.out.println("Date : " + now + " == " + weekNo);
}
打印出以下内容,我相信这就是你想要的...
Date : 2018-02-05 == 1
Date : 2018-02-12 == 2
Date : 2018-02-19 == 3
Date : 2018-02-26 == 4
Date : 2018-03-05 == 1
Date : 2018-03-12 == 2
Date : 2018-03-19 == 3
Date : 2018-03-26 == 4
Date : 2018-04-02 == 1
Date : 2018-04-09 == 2
String[] arr = { "2018-01-01", "2018-01-07", "2018-01-30", "2018-01-22",
"2018-01-25" };
for (String str : arr) {
LocalDate ld = LocalDate.parse(str);
ld = ld.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY));
int res = (ld.getDayOfMonth()/7) +
(Integer.min(1, ld.getDayOfMonth() % 7));
System.out.printf("%s => %d\n", str, res);
}
你不应该为此使用自己的算法。使用内置功能:
int week = nextMonday.get(ChronoField.ALIGNED_WEEK_OF_MONTH);
根据您代码中的日期,这会产生:
1
这意味着您得到的星期一(2 月 5 日)是该月的第一个星期一。此外,您不需要任何 WeekFields
,因为无论哪一天是一周的第一天,或者一年中的几周是如何编号的,每个月的第一个星期一就是该月的第一个星期一。
日期运算往往比较复杂,容易出错。这也意味着,即使您最终计算正确,reader 也很难说服 herself/himself 您的代码是正确的。因此,最好使用我们相信要测试的内置功能,它使用解释性名称而不是像 1 和 7 这样的数字。
您可能会惊讶于要使用的字段名为 ALIGNED_WEEK_OF_MONTH
。将对齐的周视为从每月 1 号开始的一周,无论星期几,以及接下来的几周。 2018 年 2 月,第一个对齐周从 2 月 1 日星期四到 2 月 7 日星期三。接下来的对齐周从 2 月 8 日、2 月 15 日和 2 月 22 日星期四开始。显然,该月的第一个星期一属于对齐周 1,第 2 周的第 2 个星期一,依此类推。因此可以使用 ALIGNED_WEEK_OF_MONTH
.
我正在尝试弄清楚如何确定特定星期一是给定月份的第一个、第二个、第三个或第四个星期一。我已经弄清楚如何使用 LocalDate class.
获取下周一和本月的星期几LocalDate now = LocalDate.of(2018, 2, 1);
LocalDate nextMonday = now.with(next(DayOfWeek.MONDAY));
WeekFields weekFields = WeekFields.of(Locale.getDefault());
int week = nextMonday.get(weekFields.weekOfMonth());
如上例,代码获取的是下周一和所在周。周是二月的第二周,但那个周一不是第二个周一,是第一个。如有任何帮助,我们将不胜感激。
您可以尝试从日期中重复减去一周,直到月份发生变化。那么你这样做的次数就是原始日期的 'Xth day of the week in the month'.
编辑:一些代码。
LocalDate now = LocalDate.of(2018, 2, 1);
int i = 0;
Month originalMonth = now.getMonth();
while (now.getMonth() == originalMonth) { // its an enum, you can do this
now = now.plusWeeks(-1);
i++;
}
System.out.println(i); // prints 1
编辑:你应该采用 Ole V.V 的答案 (ChronoField.ALIGNED_WEEK_OF_MONTH
) 而不是这个答案。
你可以算出今天是几号,除以 7,再加 1:
LocalDate nextMonday = now.with(next(DayOfWeek.MONDAY));
int weekNo = ((nextMonday.getDayOfMonth()-1) / 7) +1;
例如,这段代码:
LocalDate now = LocalDate.of(2018, 2, 1);
for(int i = 0; i < 10; i++) {
now = now.with(next(DayOfWeek.MONDAY));
int weekNo = ((now.getDayOfMonth()-1) / 7) +1;
System.out.println("Date : " + now + " == " + weekNo);
}
打印出以下内容,我相信这就是你想要的...
Date : 2018-02-05 == 1
Date : 2018-02-12 == 2
Date : 2018-02-19 == 3
Date : 2018-02-26 == 4
Date : 2018-03-05 == 1
Date : 2018-03-12 == 2
Date : 2018-03-19 == 3
Date : 2018-03-26 == 4
Date : 2018-04-02 == 1
Date : 2018-04-09 == 2
String[] arr = { "2018-01-01", "2018-01-07", "2018-01-30", "2018-01-22",
"2018-01-25" };
for (String str : arr) {
LocalDate ld = LocalDate.parse(str);
ld = ld.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY));
int res = (ld.getDayOfMonth()/7) +
(Integer.min(1, ld.getDayOfMonth() % 7));
System.out.printf("%s => %d\n", str, res);
}
你不应该为此使用自己的算法。使用内置功能:
int week = nextMonday.get(ChronoField.ALIGNED_WEEK_OF_MONTH);
根据您代码中的日期,这会产生:
1
这意味着您得到的星期一(2 月 5 日)是该月的第一个星期一。此外,您不需要任何 WeekFields
,因为无论哪一天是一周的第一天,或者一年中的几周是如何编号的,每个月的第一个星期一就是该月的第一个星期一。
日期运算往往比较复杂,容易出错。这也意味着,即使您最终计算正确,reader 也很难说服 herself/himself 您的代码是正确的。因此,最好使用我们相信要测试的内置功能,它使用解释性名称而不是像 1 和 7 这样的数字。
您可能会惊讶于要使用的字段名为 ALIGNED_WEEK_OF_MONTH
。将对齐的周视为从每月 1 号开始的一周,无论星期几,以及接下来的几周。 2018 年 2 月,第一个对齐周从 2 月 1 日星期四到 2 月 7 日星期三。接下来的对齐周从 2 月 8 日、2 月 15 日和 2 月 22 日星期四开始。显然,该月的第一个星期一属于对齐周 1,第 2 周的第 2 个星期一,依此类推。因此可以使用 ALIGNED_WEEK_OF_MONTH
.