如何获得下一个 n 个星期五,即一个月中的第一个、第二个或第三个星期五?
How to get the next n fridays which are the first, second or third friday in a month?
我需要找到接下来的 n 个星期五,但想排除第 4 个和可能的第 5 个星期五,即我想要获得接下来的 n 个星期五,即每个月的第 1、2 或 3 号。我找到了一种在接下来的 n 个星期五进行流式传输的方法(例如接下来的 10 个星期五):
LocalDate now = LocalDate.now();
Stream.iterate(now , localDate -> localDate.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)))
.skip(1) // skip today
.limit(10)
.forEach(System.out::println);
输出:
2021-10-22
2021-10-29
2021-11-05
2021-11-12
2021-11-19
2021-11-26
2021-12-03
2021-12-10
2021-12-17
2021-12-24
但我需要排除例如 2021-10-22
和 2021-10-29
,因为它们是 10 月的第 4 个和第 5 个星期五。同样 2021-11-26
& 2021-12-24
因为它们不是第一个、第二个或第三个星期五。
我搜索了 SO 并找到了一些方法来计算一个月的第 n 个星期五,例如这个
public static LocalDate nthFridayOfMonth(LocalDate localDate, int week) {
return localDate.with(TemporalAdjusters.dayOfWeekInMonth(week, DayOfWeek.FRIDAY));
}
第 n 个星期五的给定日期 returns。
如果给定的 LocalDate 是一个月的第一个、第二个或第三个星期五,如何修改此方法使其 returns 为布尔值?或者使用这个方法来实现另一个方法来满足我的需要?
理想情况下,我想使用上面的流并使用一种方法,returns 一个布尔值作为过滤器:
LocalDate now = LocalDate.now();
Stream.iterate(now , localDate -> localDate.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)))
.skip(1) // skip today
.filter(d -> is1st2ndOr3rdFriday(d))
.limit(10)
.forEach(System.out::println);
得到
2021-11-05
2021-11-12
2021-11-19
2021-12-03
2021-12-10
2021-12-17
2022-01-07
2022-01-14
2022-01-21
2022-02-04
感谢任何关于如何实现过滤方法的帮助boolean is1st2ndOr3rdFriday(LocalDate d) {}
获取本地日期的ALIGNED_WEEK_OF_MONTH
时间字段,判断是否≤3
Stream.iterate(now , localDate -> localDate.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)))
.skip(1) // skip today
.filter(x -> x.get(ChronoField.ALIGNED_WEEK_OF_MONTH) <= 3)
.limit(10)
.forEach(System.out::println);
另一个解决方案:你可以按月分组你的日期(到 Map >),然后如果有超过 3 个日期,则每个月键,删除它,return 结果:
public static void main(String[] args) {
// initialize your date here:
LocalDate now = LocalDate.now();
// Grouping Dates By Month
Map<Month, List<LocalDate>> map = Stream
.iterate(LocalDate.of(now.getYear(), now.getMonth(), 1),
localDate -> localDate.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)))
.limit(20).collect(Collectors.groupingBy(element -> element.getMonth()));
// delete the 4 or 5 fridays
map.forEach((k, v) -> {
if (v.size() > 3)
v.removeIf(e -> e.isBefore(now) || v.indexOf(e) > 2);
});
// print results sorted
Stream.of(map.values()).flatMap(e -> e.stream()).flatMap(List::stream).sorted().limit(10)
.forEach(System.out::println);
}
Output
2021-11-05
2021-11-12
2021-11-19
2021-12-03
2021-12-10
2021-12-17
2022-01-07
2022-01-14
2022-01-21
2022-02-04
另一种选择:迭代月
为了变化,这里有一个不同的想法。我正在创建一个月份流,并明确地从每个月的前 3 个星期五开始。
LocalDate today = LocalDate.now(ZoneId.systemDefault());
YearMonth thisMonth = YearMonth.from(today);
List<LocalDate> fridays = Stream.iterate(thisMonth, ym -> ym.plusMonths(1))
.flatMap(ym -> Stream.of(fridayOfMonth(ym, 1), fridayOfMonth(ym, 2), fridayOfMonth(ym, 3)))
.filter(date -> date.isAfter(today))
.limit(10)
.collect(Collectors.toList());
System.out.println(fridays);
今天运行时的输出:
[2021-11-05, 2021-11-12, 2021-11-19, 2021-12-03, 2021-12-10,
2021-12-17, 2022-01-07, 2022-01-14, 2022-01-21, 2022-02-04]
我使用了以下辅助方法来查找一个月的第 n 个星期五:
private static LocalDate fridayOfMonth(YearMonth ym, int no) {
return ym.atDay(15).with(DayOfWeek.FRIDAY).with(ChronoField.ALIGNED_WEEK_OF_MONTH, no);
}
变体: 还是为了变体,这里是创建每月前三个星期五流的不同方式:
List<LocalDate> fridays = Stream.iterate(thisMonth, ym -> ym.plusMonths(1))
.flatMap(MyClass::firstThreeFridays)
.filter(date -> date.isAfter(today))
.limit(10)
.collect(Collectors.toList());
这次我的辅助方法是这样的:
private static Stream<LocalDate> firstThreeFridays(YearMonth ym) {
LocalDate firstFriday = ym.atDay(1).with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY));
return Stream.of(firstFriday, firstFriday.plusWeeks(1), firstFriday.plusWeeks(2));
}
结果和之前一样
(迭代月份的想法也在 Basil Bourque 现已删除的答案中。)
我需要找到接下来的 n 个星期五,但想排除第 4 个和可能的第 5 个星期五,即我想要获得接下来的 n 个星期五,即每个月的第 1、2 或 3 号。我找到了一种在接下来的 n 个星期五进行流式传输的方法(例如接下来的 10 个星期五):
LocalDate now = LocalDate.now();
Stream.iterate(now , localDate -> localDate.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)))
.skip(1) // skip today
.limit(10)
.forEach(System.out::println);
输出:
2021-10-22
2021-10-29
2021-11-05
2021-11-12
2021-11-19
2021-11-26
2021-12-03
2021-12-10
2021-12-17
2021-12-24
但我需要排除例如 2021-10-22
和 2021-10-29
,因为它们是 10 月的第 4 个和第 5 个星期五。同样 2021-11-26
& 2021-12-24
因为它们不是第一个、第二个或第三个星期五。
我搜索了 SO 并找到了一些方法来计算一个月的第 n 个星期五,例如这个
public static LocalDate nthFridayOfMonth(LocalDate localDate, int week) {
return localDate.with(TemporalAdjusters.dayOfWeekInMonth(week, DayOfWeek.FRIDAY));
}
第 n 个星期五的给定日期 returns。
如果给定的 LocalDate 是一个月的第一个、第二个或第三个星期五,如何修改此方法使其 returns 为布尔值?或者使用这个方法来实现另一个方法来满足我的需要?
理想情况下,我想使用上面的流并使用一种方法,returns 一个布尔值作为过滤器:
LocalDate now = LocalDate.now();
Stream.iterate(now , localDate -> localDate.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)))
.skip(1) // skip today
.filter(d -> is1st2ndOr3rdFriday(d))
.limit(10)
.forEach(System.out::println);
得到
2021-11-05
2021-11-12
2021-11-19
2021-12-03
2021-12-10
2021-12-17
2022-01-07
2022-01-14
2022-01-21
2022-02-04
感谢任何关于如何实现过滤方法的帮助boolean is1st2ndOr3rdFriday(LocalDate d) {}
获取本地日期的ALIGNED_WEEK_OF_MONTH
时间字段,判断是否≤3
Stream.iterate(now , localDate -> localDate.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)))
.skip(1) // skip today
.filter(x -> x.get(ChronoField.ALIGNED_WEEK_OF_MONTH) <= 3)
.limit(10)
.forEach(System.out::println);
另一个解决方案:你可以按月分组你的日期(到 Map
public static void main(String[] args) {
// initialize your date here:
LocalDate now = LocalDate.now();
// Grouping Dates By Month
Map<Month, List<LocalDate>> map = Stream
.iterate(LocalDate.of(now.getYear(), now.getMonth(), 1),
localDate -> localDate.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)))
.limit(20).collect(Collectors.groupingBy(element -> element.getMonth()));
// delete the 4 or 5 fridays
map.forEach((k, v) -> {
if (v.size() > 3)
v.removeIf(e -> e.isBefore(now) || v.indexOf(e) > 2);
});
// print results sorted
Stream.of(map.values()).flatMap(e -> e.stream()).flatMap(List::stream).sorted().limit(10)
.forEach(System.out::println);
}
Output
2021-11-05
2021-11-12
2021-11-19
2021-12-03
2021-12-10
2021-12-17
2022-01-07
2022-01-14
2022-01-21
2022-02-04
另一种选择:迭代月
为了变化,这里有一个不同的想法。我正在创建一个月份流,并明确地从每个月的前 3 个星期五开始。
LocalDate today = LocalDate.now(ZoneId.systemDefault());
YearMonth thisMonth = YearMonth.from(today);
List<LocalDate> fridays = Stream.iterate(thisMonth, ym -> ym.plusMonths(1))
.flatMap(ym -> Stream.of(fridayOfMonth(ym, 1), fridayOfMonth(ym, 2), fridayOfMonth(ym, 3)))
.filter(date -> date.isAfter(today))
.limit(10)
.collect(Collectors.toList());
System.out.println(fridays);
今天运行时的输出:
[2021-11-05, 2021-11-12, 2021-11-19, 2021-12-03, 2021-12-10, 2021-12-17, 2022-01-07, 2022-01-14, 2022-01-21, 2022-02-04]
我使用了以下辅助方法来查找一个月的第 n 个星期五:
private static LocalDate fridayOfMonth(YearMonth ym, int no) {
return ym.atDay(15).with(DayOfWeek.FRIDAY).with(ChronoField.ALIGNED_WEEK_OF_MONTH, no);
}
变体: 还是为了变体,这里是创建每月前三个星期五流的不同方式:
List<LocalDate> fridays = Stream.iterate(thisMonth, ym -> ym.plusMonths(1))
.flatMap(MyClass::firstThreeFridays)
.filter(date -> date.isAfter(today))
.limit(10)
.collect(Collectors.toList());
这次我的辅助方法是这样的:
private static Stream<LocalDate> firstThreeFridays(YearMonth ym) {
LocalDate firstFriday = ym.atDay(1).with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY));
return Stream.of(firstFriday, firstFriday.plusWeeks(1), firstFriday.plusWeeks(2));
}
结果和之前一样
(迭代月份的想法也在 Basil Bourque 现已删除的答案中。)