83 import java.time.chrono.ChronoLocalDate; 84 import java.time.chrono.IsoEra; 85 import java.time.chrono.IsoChronology; 86 import java.time.format.DateTimeFormatter; 87 import java.time.format.DateTimeParseException; 88 import java.time.temporal.ChronoField; 89 import java.time.temporal.ChronoUnit; 90 import java.time.temporal.Temporal; 91 import java.time.temporal.TemporalAccessor; 92 import java.time.temporal.TemporalAdjuster; 93 import java.time.temporal.TemporalAmount; 94 import java.time.temporal.TemporalField; 95 import java.time.temporal.TemporalQueries; 96 import java.time.temporal.TemporalQuery; 97 import java.time.temporal.TemporalUnit; 98 import java.time.temporal.UnsupportedTemporalTypeException; 99 import java.time.temporal.ValueRange; 100 import java.time.zone.ZoneOffsetTransition; 101 import java.time.zone.ZoneRules; 102 import java.util.Objects; 103 104 /** 105 * A date without a time-zone in the ISO-8601 calendar system, 106 * such as {@code 2007-12-03}. 107 * <p> 108 * {@code LocalDate} is an immutable date-time object that represents a date, 109 * often viewed as year-month-day. Other date fields, such as day-of-year, 110 * day-of-week and week-of-year, can also be accessed. 111 * For example, the value "2nd October 2007" can be stored in a {@code LocalDate}. 112 * <p> 113 * This class does not store or represent a time or time-zone. 114 * Instead, it is a description of the date, as used for birthdays. 115 * It cannot represent an instant on the time-line without additional information 116 * such as an offset or time-zone. 117 * <p> 118 * The ISO-8601 calendar system is the modern civil calendar system used today 119 * in most of the world. It is equivalent to the proleptic Gregorian calendar 120 * system, in which today's rules for leap years are applied for all time. 121 * For most applications written today, the ISO-8601 rules are entirely suitable. 122 * However, any application that makes use of historical dates, and requires them 1696 * 1697 * @param endDateExclusive the end date, exclusive, which may be in any chronology, not null 1698 * @return the period between this date and the end date, not null 1699 */ 1700 @Override 1701 public Period until(ChronoLocalDate endDateExclusive) { 1702 LocalDate end = LocalDate.from(endDateExclusive); 1703 long totalMonths = end.getProlepticMonth() - this.getProlepticMonth(); // safe 1704 int days = end.day - this.day; 1705 if (totalMonths > 0 && days < 0) { 1706 totalMonths--; 1707 LocalDate calcDate = this.plusMonths(totalMonths); 1708 days = (int) (end.toEpochDay() - calcDate.toEpochDay()); // safe 1709 } else if (totalMonths < 0 && days > 0) { 1710 totalMonths++; 1711 days -= end.lengthOfMonth(); 1712 } 1713 long years = totalMonths / 12; // safe 1714 int months = (int) (totalMonths % 12); // safe 1715 return Period.of(Math.toIntExact(years), months, days); 1716 } 1717 1718 /** 1719 * Formats this date using the specified formatter. 1720 * <p> 1721 * This date will be passed to the formatter to produce a string. 1722 * 1723 * @param formatter the formatter to use, not null 1724 * @return the formatted date string, not null 1725 * @throws DateTimeException if an error occurs during printing 1726 */ 1727 @Override // override for Javadoc and performance 1728 public String format(DateTimeFormatter formatter) { 1729 Objects.requireNonNull(formatter, "formatter"); 1730 return formatter.format(this); 1731 } 1732 1733 //----------------------------------------------------------------------- 1734 /** 1735 * Combines this date with a time to create a {@code LocalDateTime}. | 83 import java.time.chrono.ChronoLocalDate; 84 import java.time.chrono.IsoEra; 85 import java.time.chrono.IsoChronology; 86 import java.time.format.DateTimeFormatter; 87 import java.time.format.DateTimeParseException; 88 import java.time.temporal.ChronoField; 89 import java.time.temporal.ChronoUnit; 90 import java.time.temporal.Temporal; 91 import java.time.temporal.TemporalAccessor; 92 import java.time.temporal.TemporalAdjuster; 93 import java.time.temporal.TemporalAmount; 94 import java.time.temporal.TemporalField; 95 import java.time.temporal.TemporalQueries; 96 import java.time.temporal.TemporalQuery; 97 import java.time.temporal.TemporalUnit; 98 import java.time.temporal.UnsupportedTemporalTypeException; 99 import java.time.temporal.ValueRange; 100 import java.time.zone.ZoneOffsetTransition; 101 import java.time.zone.ZoneRules; 102 import java.util.Objects; 103 import java.util.stream.LongStream; 104 import java.util.stream.Stream; 105 106 /** 107 * A date without a time-zone in the ISO-8601 calendar system, 108 * such as {@code 2007-12-03}. 109 * <p> 110 * {@code LocalDate} is an immutable date-time object that represents a date, 111 * often viewed as year-month-day. Other date fields, such as day-of-year, 112 * day-of-week and week-of-year, can also be accessed. 113 * For example, the value "2nd October 2007" can be stored in a {@code LocalDate}. 114 * <p> 115 * This class does not store or represent a time or time-zone. 116 * Instead, it is a description of the date, as used for birthdays. 117 * It cannot represent an instant on the time-line without additional information 118 * such as an offset or time-zone. 119 * <p> 120 * The ISO-8601 calendar system is the modern civil calendar system used today 121 * in most of the world. It is equivalent to the proleptic Gregorian calendar 122 * system, in which today's rules for leap years are applied for all time. 123 * For most applications written today, the ISO-8601 rules are entirely suitable. 124 * However, any application that makes use of historical dates, and requires them 1698 * 1699 * @param endDateExclusive the end date, exclusive, which may be in any chronology, not null 1700 * @return the period between this date and the end date, not null 1701 */ 1702 @Override 1703 public Period until(ChronoLocalDate endDateExclusive) { 1704 LocalDate end = LocalDate.from(endDateExclusive); 1705 long totalMonths = end.getProlepticMonth() - this.getProlepticMonth(); // safe 1706 int days = end.day - this.day; 1707 if (totalMonths > 0 && days < 0) { 1708 totalMonths--; 1709 LocalDate calcDate = this.plusMonths(totalMonths); 1710 days = (int) (end.toEpochDay() - calcDate.toEpochDay()); // safe 1711 } else if (totalMonths < 0 && days > 0) { 1712 totalMonths++; 1713 days -= end.lengthOfMonth(); 1714 } 1715 long years = totalMonths / 12; // safe 1716 int months = (int) (totalMonths % 12); // safe 1717 return Period.of(Math.toIntExact(years), months, days); 1718 } 1719 1720 /** 1721 * Returns a sequential ordered stream of dates. The returned stream starts from this date 1722 * (inclusive) and goes to {@code endExclusive} (exclusive) by an incremental step of 1 day. 1723 * <p> 1724 * This method is equivalent to {@code datesUntil(endExclusive, Period.ofDays(1))}. 1725 * 1726 * @param endExclusive the end date, exclusive, not null 1727 * @return a sequential {@code Stream} for the range of {@code LocalDate} values 1728 * @throws IllegalArgumentException if end date is before this date 1729 * @since 9 1730 */ 1731 public Stream<LocalDate> datesUntil(LocalDate endExclusive) { 1732 long end = endExclusive.toEpochDay(); 1733 long start = toEpochDay(); 1734 if (end < start) { 1735 throw new IllegalArgumentException(endExclusive + " < " + this); 1736 } 1737 return LongStream.range(start, end).mapToObj(LocalDate::ofEpochDay); 1738 } 1739 1740 /** 1741 * Returns a sequential ordered stream of dates by given incremental step. The returned stream 1742 * starts from this date (inclusive) and goes to {@code endExclusive} (exclusive). 1743 * <p> 1744 * The n-th date which appears in the stream is equal to {@code this.plus(step.multipliedBy(n))} 1745 * (but the result of step multiplication never overflows). For example, if this date is 1746 * {@code 2015-01-31}, the end date is {@code 2015-05-01} and the step is 1 month, then the 1747 * stream contains {@code 2015-01-31}, {@code 2015-02-28}, {@code 2015-03-31}, and 1748 * {@code 2015-04-30}. 1749 * 1750 * @param endExclusive the end date, exclusive, not null 1751 * @param step the non-zero, non-negative {@code Period} which represents the step. 1752 * @return a sequential {@code Stream} for the range of {@code LocalDate} values 1753 * @throws IllegalArgumentException if step is zero, or {@code step.getDays()} and 1754 * {@code step.toTotalMonths()} have opposite sign, or end date is before this date 1755 * and step is positive, or end date is after this date and step is negative 1756 * @since 9 1757 */ 1758 public Stream<LocalDate> datesUntil(LocalDate endExclusive, Period step) { 1759 if (step.isZero()) { 1760 throw new IllegalArgumentException("step is zero"); 1761 } 1762 long end = endExclusive.toEpochDay(); 1763 long start = toEpochDay(); 1764 long until = end - start; 1765 long months = step.toTotalMonths(); 1766 long days = step.getDays(); 1767 if ((months < 0 && days > 0) || (months > 0 && days < 0)) { 1768 throw new IllegalArgumentException("period months and days are of opposite sign"); 1769 } 1770 if (until == 0) { 1771 return Stream.empty(); 1772 } 1773 int sign = months > 0 || days > 0 ? 1 : -1; 1774 if (sign < 0 ^ until < 0) { 1775 throw new IllegalArgumentException(endExclusive + (sign < 0 ? " > " : " < ") + this); 1776 } 1777 if (months == 0) { 1778 long steps = (until - sign) / days; // non-negative 1779 return LongStream.rangeClosed(0, steps).mapToObj( 1780 n -> LocalDate.ofEpochDay(start + n * days)); 1781 } 1782 // 48699/1600 = 365.2425/12, no overflow, non-negative result 1783 long steps = until * 1600 / (months * 48699 + days * 1600) + 1; 1784 long addMonths = months * steps; 1785 long addDays = days * steps; 1786 long maxAddMonths = months > 0 ? MAX.getProlepticMonth() - getProlepticMonth() 1787 : getProlepticMonth() - MIN.getProlepticMonth(); 1788 // adjust steps estimation 1789 if (addMonths * sign > maxAddMonths 1790 || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) { 1791 steps--; 1792 addMonths -= months; 1793 addDays -= days; 1794 if (addMonths * sign > maxAddMonths 1795 || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) { 1796 steps--; 1797 } 1798 } 1799 return LongStream.rangeClosed(0, steps).mapToObj( 1800 n -> this.plusMonths(months * n).plusDays(days * n)); 1801 } 1802 1803 /** 1804 * Formats this date using the specified formatter. 1805 * <p> 1806 * This date will be passed to the formatter to produce a string. 1807 * 1808 * @param formatter the formatter to use, not null 1809 * @return the formatted date string, not null 1810 * @throws DateTimeException if an error occurs during printing 1811 */ 1812 @Override // override for Javadoc and performance 1813 public String format(DateTimeFormatter formatter) { 1814 Objects.requireNonNull(formatter, "formatter"); 1815 return formatter.format(this); 1816 } 1817 1818 //----------------------------------------------------------------------- 1819 /** 1820 * Combines this date with a time to create a {@code LocalDateTime}. |