IntStream.range(int from,int to)のようなものがDateでもほしいなあと思い、作ってみました。
実装
Between.java
@ValidTrue("from < to")
public class Between<T extends Temporal & Comparable<? super T>> {
private T from;
private T to;
public Between(T from, T to){
this.from = from;
this.to = to;
}
public Stream<T> each(ChronoUnit unit, UnaryOperator<T> adjuster, int skip){
T adjfrom = adjuster.apply(from);
while(from.compareTo(adjfrom)>0) adjfrom = unit.addTo(from, 1);
long size = adjfrom.until(to, unit)/skip;
return Stream.iterate(adjfrom, d -> unit.addTo(d, skip)).limit(size);
}
}
TemporalAdjusterというのが、Temporal -> Temporalの修正変換をしてくれるのですが、これ TemporalAdjuster<T extends Temporal>
じゃないんです・・・adjustすると型を失ってしまうので使えないという・・・・T型を復活する方法がありませんかね。
TemporalQueryを自分で作るのだろうか。
Test
BetweenTest.java
public class BetweenTest {
@Test
public void test(){
//毎日
Between<LocalDate> between = new Between<>(LocalDate.now(),LocalDate.now().plusDays(50));
between.each(ChronoUnit.DAYS , d -> d ,1).forEach(System.out::println);
System.out.println("***********");
//隔週日曜日
between.each(ChronoUnit.WEEKS , d -> d.with(DayOfWeek.SUNDAY) ,2).forEach(System.out::println);
System.out.println("***********");
//毎月最終日
Between<YearMonth> between2 = new Between<>(YearMonth.now(),YearMonth.now().plusMonths(12));
between2.each(ChronoUnit.MONTHS , m -> m , 1 ).map( YearMonth::atEndOfMonth ).forEach(System.out::println);
System.out.println("***********");
//毎月第3日曜日
between2.each(ChronoUnit.MONTHS , m -> m , 1 ).map( d -> d.atDay(1).with(TemporalAdjusters.dayOfWeekInMonth(3, DayOfWeek.SUNDAY ))).forEach(System.out::println);
System.out.println("***********");
//毎年4月1日
Between<Year> between3 = new Between<>(Year.now(),Year.now().plusYears(10));
between3.each(ChronoUnit.YEARS, y -> y, 1).map( y -> y.atMonthDay(MonthDay.of(4, 1))).forEach(System.out::println);
}
}
というわけで、いろんなTemporalのリストが作れそうです。
総括
考え中・・・
課題
- TemporalAdjuster・・・
- Day型がない
- T型を復活する方法
-
y -> y
これを書くクールなラムダ式を教えてください。
(追加)
//毎週土曜日と日曜日
between.each(ChronoUnit.WEEKS , d -> d.with(DayOfWeek.SATURDAY) ,1).flatMap( d -> Stream.of(d,d.plusDays(1))).forEach(System.out::println);
まあ、
between.stream().filter( d -> d.getDayOfWeek()==DayOfWeek.SUNDAY ||d.getDayOfWeek()==DayOfWeek.SATURDAY)
みたいに全部フィルタでいいよと言われるとまあそれでもいいんですが、全日走査するより早いじゃん、と言う気分です。