< prev index next >

src/java.base/share/classes/java/time/LocalDate.java

Print this page

        

@@ -98,10 +98,12 @@
 import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.time.zone.ZoneOffsetTransition;
 import java.time.zone.ZoneRules;
 import java.util.Objects;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
 
 /**
  * A date without a time-zone in the ISO-8601 calendar system,
  * such as {@code 2007-12-03}.
  * <p>

@@ -1697,10 +1699,77 @@
         int months = (int) (totalMonths % 12);  // safe
         return Period.of(Math.toIntExact(years), months, days);
     }
 
     /**
+     * Returns a sequential ordered {@link Stream} containing all the
+     * {@code LocalDate} values starting from this (inclusive) to
+     * {@code endExclusive} (exclusive) by an incremental step of 1 day.
+     * <p>
+     * This method is equivalent to {@code datesUntil(endExclusive, Period.ofDays(1))}.
+     * <p>
+     * The resulting stream will be empty if the end date is equal to or before the start.
+     *
+     * @param endExclusive  the end date, exclusive, not null
+     * @return a sequential {@code Stream} for the range of {@code LocalDate}
+     *         values
+     * @since 9
+     */
+    public Stream<LocalDate> datesUntil(LocalDate endExclusive) {
+        return LongStream.range(0, daysUntil(endExclusive)).mapToObj(this::plusDays);
+    }
+
+    /**
+     * Returns a sequential ordered {@link Stream} containing the
+     * {@code LocalDate} values starting from this (inclusive) to
+     * {@code endExclusive} (exclusive) by the supplied incremental {@code step}.
+     * <p>
+     * The resulting stream will be empty if the end date is equal to or before the start.
+     * 
+     * @param endExclusive  the end date, exclusive, not null
+     * @param step  the non-zero, non-negative {@code Period} which represents 
+     *              the step.
+     * @return a sequential {@code Stream} for the range of {@code LocalDate}
+     *         values
+     * @throws IllegalArgumentException if step is zero or is negative
+     * @since 9
+     */
+    public Stream<LocalDate> datesUntil(LocalDate endExclusive, Period step) {
+        if (step.isZero() || step.isNegative())
+            throw new IllegalArgumentException("step must be positive");
+        long until = daysUntil(endExclusive);
+        if (until <= 0)
+            return Stream.empty();
+        long months = step.toTotalMonths();
+        long days = step.getDays();
+        long steps;
+        if (months != 0) {
+            // 48699/1600 = 365.2425/12, no overflow
+            steps = until * 1600 / (months * 48699 + days * 1600) + 1;
+            long endDays = endExclusive.toEpochDay();
+            long maxAddMonths = MAX.getProlepticMonth() - getProlepticMonth();
+            long addMonths = months * steps;
+            long addDays = days * steps;
+            // adjust steps estimation
+            if (addMonths > maxAddMonths
+                    || plusMonths(addMonths).toEpochDay() + addDays >= endDays) {
+                steps--;
+                addMonths -= months;
+                addDays -= days;
+                if (addMonths > maxAddMonths
+                        || plusMonths(addMonths).toEpochDay() + addDays >= endDays) {
+                    steps--;
+                }
+            }
+        } else {
+            steps = (until - 1) / days;
+        }
+        return LongStream.rangeClosed(0, steps).mapToObj(
+                n -> this.plusMonths(months * n).plusDays(days * n));
+    }
+
+    /**
      * Formats this date using the specified formatter.
      * <p>
      * This date will be passed to the formatter to produce a string.
      *
      * @param formatter  the formatter to use, not null
< prev index next >