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 1679 * 1680 * @param endDateExclusive the end date, exclusive, which may be in any chronology, not null 1681 * @return the period between this date and the end date, not null 1682 */ 1683 @Override 1684 public Period until(ChronoLocalDate endDateExclusive) { 1685 LocalDate end = LocalDate.from(endDateExclusive); 1686 long totalMonths = end.getProlepticMonth() - this.getProlepticMonth(); // safe 1687 int days = end.day - this.day; 1688 if (totalMonths > 0 && days < 0) { 1689 totalMonths--; 1690 LocalDate calcDate = this.plusMonths(totalMonths); 1691 days = (int) (end.toEpochDay() - calcDate.toEpochDay()); // safe 1692 } else if (totalMonths < 0 && days > 0) { 1693 totalMonths++; 1694 days -= end.lengthOfMonth(); 1695 } 1696 long years = totalMonths / 12; // safe 1697 int months = (int) (totalMonths % 12); // safe 1698 return Period.of(Math.toIntExact(years), months, days); 1699 } 1700 1701 /** 1702 * Formats this date using the specified formatter. 1703 * <p> 1704 * This date will be passed to the formatter to produce a string. 1705 * 1706 * @param formatter the formatter to use, not null 1707 * @return the formatted date string, not null 1708 * @throws DateTimeException if an error occurs during printing 1709 */ 1710 @Override // override for Javadoc and performance 1711 public String format(DateTimeFormatter formatter) { 1712 Objects.requireNonNull(formatter, "formatter"); 1713 return formatter.format(this); 1714 } 1715 1716 //----------------------------------------------------------------------- 1717 /** 1718 * 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 1681 * 1682 * @param endDateExclusive the end date, exclusive, which may be in any chronology, not null 1683 * @return the period between this date and the end date, not null 1684 */ 1685 @Override 1686 public Period until(ChronoLocalDate endDateExclusive) { 1687 LocalDate end = LocalDate.from(endDateExclusive); 1688 long totalMonths = end.getProlepticMonth() - this.getProlepticMonth(); // safe 1689 int days = end.day - this.day; 1690 if (totalMonths > 0 && days < 0) { 1691 totalMonths--; 1692 LocalDate calcDate = this.plusMonths(totalMonths); 1693 days = (int) (end.toEpochDay() - calcDate.toEpochDay()); // safe 1694 } else if (totalMonths < 0 && days > 0) { 1695 totalMonths++; 1696 days -= end.lengthOfMonth(); 1697 } 1698 long years = totalMonths / 12; // safe 1699 int months = (int) (totalMonths % 12); // safe 1700 return Period.of(Math.toIntExact(years), months, days); 1701 } 1702 1703 /** 1704 * Returns a sequential ordered {@link Stream} containing all the 1705 * {@code LocalDate} values starting from this (inclusive) to 1706 * {@code endExclusive} (exclusive) by an incremental step of 1 day. 1707 * <p> 1708 * This method is equivalent to {@code datesUntil(endExclusive, Period.ofDays(1))}. 1709 * <p> 1710 * The resulting stream will be empty if the end date is equal to or before the start. 1711 * 1712 * @param endExclusive the end date, exclusive, not null 1713 * @return a sequential {@code Stream} for the range of {@code LocalDate} 1714 * values 1715 * @since 9 1716 */ 1717 public Stream<LocalDate> datesUntil(LocalDate endExclusive) { 1718 return LongStream.range(0, daysUntil(endExclusive)).mapToObj(this::plusDays); 1719 } 1720 1721 /** 1722 * Returns a sequential ordered {@link Stream} containing the 1723 * {@code LocalDate} values starting from this (inclusive) to 1724 * {@code endExclusive} (exclusive) by the supplied incremental {@code step}. 1725 * <p> 1726 * The resulting stream will be empty if the end date is equal to or before the start. 1727 * 1728 * @param endExclusive the end date, exclusive, not null 1729 * @param step the non-zero, non-negative {@code Period} which represents 1730 * the step. 1731 * @return a sequential {@code Stream} for the range of {@code LocalDate} 1732 * values 1733 * @throws IllegalArgumentException if step is zero or is negative 1734 * @since 9 1735 */ 1736 public Stream<LocalDate> datesUntil(LocalDate endExclusive, Period step) { 1737 if (step.isZero() || step.isNegative()) 1738 throw new IllegalArgumentException("step must be positive"); 1739 long until = daysUntil(endExclusive); 1740 if (until <= 0) 1741 return Stream.empty(); 1742 long months = step.toTotalMonths(); 1743 long days = step.getDays(); 1744 long steps; 1745 if (months != 0) { 1746 // 48699/1600 = 365.2425/12, no overflow 1747 steps = until * 1600 / (months * 48699 + days * 1600) + 1; 1748 long endDays = endExclusive.toEpochDay(); 1749 long maxAddMonths = MAX.getProlepticMonth() - getProlepticMonth(); 1750 long addMonths = months * steps; 1751 long addDays = days * steps; 1752 // adjust steps estimation 1753 if (addMonths > maxAddMonths 1754 || plusMonths(addMonths).toEpochDay() + addDays >= endDays) { 1755 steps--; 1756 addMonths -= months; 1757 addDays -= days; 1758 if (addMonths > maxAddMonths 1759 || plusMonths(addMonths).toEpochDay() + addDays >= endDays) { 1760 steps--; 1761 } 1762 } 1763 } else { 1764 steps = (until - 1) / days; 1765 } 1766 return LongStream.rangeClosed(0, steps).mapToObj( 1767 n -> this.plusMonths(months * n).plusDays(days * n)); 1768 } 1769 1770 /** 1771 * Formats this date using the specified formatter. 1772 * <p> 1773 * This date will be passed to the formatter to produce a string. 1774 * 1775 * @param formatter the formatter to use, not null 1776 * @return the formatted date string, not null 1777 * @throws DateTimeException if an error occurs during printing 1778 */ 1779 @Override // override for Javadoc and performance 1780 public String format(DateTimeFormatter formatter) { 1781 Objects.requireNonNull(formatter, "formatter"); 1782 return formatter.format(this); 1783 } 1784 1785 //----------------------------------------------------------------------- 1786 /** 1787 * Combines this date with a time to create a {@code LocalDateTime}. |