Skip to main content

time/
date.rs

1//! The [`Date`] struct and its associated `impl`s.
2
3#[cfg(feature = "formatting")]
4use alloc::string::String;
5use core::fmt;
6use core::mem::MaybeUninit;
7use core::num::NonZero;
8use core::ops::{Add, AddAssign, Sub, SubAssign};
9use core::time::Duration as StdDuration;
10#[cfg(feature = "formatting")]
11use std::io;
12
13use deranged::{ri32, ru8, ru32};
14use num_conv::prelude::*;
15use powerfmt::smart_display::{FormatterOptions, Metadata, SmartDisplay};
16
17#[cfg(any(feature = "formatting", feature = "parsing"))]
18use crate::PrivateMethod;
19#[cfg(feature = "formatting")]
20use crate::formatting::Formattable;
21#[cfg(feature = "formatting")]
22use crate::internal_macros::try_likely_ok;
23use crate::internal_macros::{const_try, const_try_opt, div_floor, ensure_ranged};
24use crate::iter::DateIter;
25use crate::num_fmt::{four_to_six_digits, str_from_raw_parts, two_digits_zero_padded};
26#[cfg(feature = "parsing")]
27use crate::parsing::{Parsable, Parsed};
28use crate::unit::*;
29use crate::util::{days_in_month_leap, range_validated, weeks_in_year};
30use crate::{Month, PlainDateTime, SignedDuration, Time, Weekday, error, hint};
31
32type Year = ri32<MIN_YEAR, MAX_YEAR>;
33
34/// The minimum valid year.
35pub(crate) const MIN_YEAR: i32 = if cfg!(feature = "large-dates") {
36    -999_999
37} else {
38    -9999
39};
40/// The maximum valid year.
41pub(crate) const MAX_YEAR: i32 = if cfg!(feature = "large-dates") {
42    999_999
43} else {
44    9999
45};
46
47/// Date in the proleptic Gregorian calendar.
48///
49/// By default, years between ±9999 inclusive are representable. This can be expanded to ±999,999
50/// inclusive by enabling the `large-dates` crate feature. Doing so has performance implications
51/// and introduces some ambiguities when parsing.
52#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
53pub struct Date {
54    /// Bitpacked field containing the year, ordinal, and whether the year is a leap year.
55    // |     x      | xxxxxxxxxxxxxxxxxxxxx |       x       | xxxxxxxxx |
56    // |   1 bit    |        21 bits        |     1 bit     |  9 bits   |
57    // | unassigned |         year          | is leap year? |  ordinal  |
58    // The year is 15 bits when `large-dates` is not enabled.
59    value: NonZero<i32>,
60}
61
62impl Date {
63    /// Provide a representation of `Date` as a `i32`. This value can be used for equality, hashing,
64    /// and ordering.
65    ///
66    /// **Note**: This value is explicitly signed, so do not cast this to or treat this as an
67    /// unsigned integer. Doing so will lead to incorrect results for values with differing
68    /// signs.
69    #[inline]
70    pub(crate) const fn as_i32(self) -> i32 {
71        self.value.get()
72    }
73
74    /// The Unix epoch: 1970-01-01
75    // Safety: `ordinal` is not zero.
76    pub(crate) const UNIX_EPOCH: Self = unsafe { Self::__from_ordinal_date_unchecked(1970, 1) };
77
78    /// The minimum valid `Date`.
79    ///
80    /// The value of this may vary depending on the feature flags enabled.
81    // Safety: `ordinal` is not zero.
82    pub const MIN: Self = unsafe { Self::__from_ordinal_date_unchecked(MIN_YEAR, 1) };
83
84    /// The maximum valid `Date`.
85    ///
86    /// The value of this may vary depending on the feature flags enabled.
87    // Safety: `ordinal` is not zero.
88    pub const MAX: Self = unsafe {
89        Self::__from_ordinal_date_unchecked(MAX_YEAR, range_validated::days_in_year(MAX_YEAR))
90    };
91
92    /// Construct a `Date` from its internal representation, the validity of which must be
93    /// guaranteed by the caller.
94    ///
95    /// # Safety
96    ///
97    /// - `ordinal` must be non-zero and at most the number of days in `year`
98    /// - `is_leap_year` must be `true` if and only if `year` is a leap year
99    #[inline]
100    #[track_caller]
101    pub(crate) const unsafe fn from_parts(year: i32, is_leap_year: bool, ordinal: u16) -> Self {
102        debug_assert!(year >= MIN_YEAR);
103        debug_assert!(year <= MAX_YEAR);
104        debug_assert!(ordinal != 0);
105        debug_assert!(ordinal <= range_validated::days_in_year(year));
106        debug_assert!(range_validated::is_leap_year(year) == is_leap_year);
107
108        Self {
109            // Safety: `ordinal` is not zero.
110            value: unsafe {
111                NonZero::new_unchecked((year << 10) | ((is_leap_year as i32) << 9) | ordinal as i32)
112            },
113        }
114    }
115
116    /// Construct a `Date` from the year and ordinal values, the validity of which must be
117    /// guaranteed by the caller.
118    ///
119    /// # Safety
120    ///
121    /// - `year` must be in the range `MIN_YEAR..=MAX_YEAR`.
122    /// - `ordinal` must be non-zero and at most the number of days in `year`.
123    #[doc(hidden)]
124    #[inline]
125    #[track_caller]
126    pub const unsafe fn __from_ordinal_date_unchecked(year: i32, ordinal: u16) -> Self {
127        // Safety: The caller must guarantee that `ordinal` is not zero and that the year is in
128        // range.
129        unsafe { Self::from_parts(year, range_validated::is_leap_year(year), ordinal) }
130    }
131
132    /// Attempt to create a `Date` from the year, month, and day.
133    ///
134    /// ```rust
135    /// # use time::{Date, Month};
136    /// assert!(Date::from_calendar_date(2019, Month::January, 1).is_ok());
137    /// assert!(Date::from_calendar_date(2019, Month::December, 31).is_ok());
138    /// ```
139    ///
140    /// ```rust
141    /// # use time::{Date, Month};
142    /// assert!(Date::from_calendar_date(2019, Month::February, 29).is_err()); // 2019 isn't a leap year.
143    /// ```
144    #[inline]
145    pub const fn from_calendar_date(
146        year: i32,
147        month: Month,
148        day: u8,
149    ) -> Result<Self, error::ComponentRange> {
150        /// Cumulative days through the beginning of a month in both common and leap years.
151        const DAYS_CUMULATIVE_COMMON_LEAP: [[u16; 12]; 2] = [
152            [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
153            [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335],
154        ];
155
156        ensure_ranged!(Year: year);
157
158        let is_leap_year = range_validated::is_leap_year(year);
159        match day {
160            1..=28 => {}
161            29..=31 if day <= days_in_month_leap(month as u8, is_leap_year) => hint::cold_path(),
162            _ => {
163                hint::cold_path();
164                return Err(error::ComponentRange::conditional("day"));
165            }
166        }
167
168        // Safety: `ordinal` is not zero and `is_leap_year` is correct.
169        Ok(unsafe {
170            Self::from_parts(
171                year,
172                is_leap_year,
173                DAYS_CUMULATIVE_COMMON_LEAP[is_leap_year as usize][month as usize - 1] + day as u16,
174            )
175        })
176    }
177
178    /// Attempt to create a `Date` from the year and ordinal day number.
179    ///
180    /// ```rust
181    /// # use time::Date;
182    /// assert!(Date::from_ordinal_date(2019, 1).is_ok());
183    /// assert!(Date::from_ordinal_date(2019, 365).is_ok());
184    /// ```
185    ///
186    /// ```rust
187    /// # use time::Date;
188    /// assert!(Date::from_ordinal_date(2019, 366).is_err()); // 2019 isn't a leap year.
189    /// ```
190    #[inline]
191    pub const fn from_ordinal_date(year: i32, ordinal: u16) -> Result<Self, error::ComponentRange> {
192        ensure_ranged!(Year: year);
193
194        let is_leap_year = range_validated::is_leap_year(year);
195        match ordinal {
196            1..=365 => {}
197            366 if is_leap_year => hint::cold_path(),
198            _ => {
199                hint::cold_path();
200                return Err(error::ComponentRange::conditional("ordinal"));
201            }
202        }
203
204        // Safety: `ordinal` is not zero.
205        Ok(unsafe { Self::from_parts(year, is_leap_year, ordinal) })
206    }
207
208    /// Attempt to create a `Date` from the ISO year, week, and weekday.
209    ///
210    /// ```rust
211    /// # use time::{Date, Weekday::*};
212    /// assert!(Date::from_iso_week_date(2019, 1, Monday).is_ok());
213    /// assert!(Date::from_iso_week_date(2019, 1, Tuesday).is_ok());
214    /// assert!(Date::from_iso_week_date(2020, 53, Friday).is_ok());
215    /// ```
216    ///
217    /// ```rust
218    /// # use time::{Date, Weekday::*};
219    /// assert!(Date::from_iso_week_date(2019, 53, Monday).is_err()); // 2019 doesn't have 53 weeks.
220    /// ```
221    pub const fn from_iso_week_date(
222        year: i32,
223        week: u8,
224        weekday: Weekday,
225    ) -> Result<Self, error::ComponentRange> {
226        ensure_ranged!(Year: year);
227        match week {
228            1..=52 => {}
229            53 if week <= weeks_in_year(year) => hint::cold_path(),
230            _ => {
231                hint::cold_path();
232                return Err(error::ComponentRange::conditional("week"));
233            }
234        }
235
236        let adj_year = year - 1;
237        let raw = 365 * adj_year + div_floor!(adj_year, 4) - div_floor!(adj_year, 100)
238            + div_floor!(adj_year, 400);
239        let jan_4 = match (raw % 7) as i8 {
240            -6 | 1 => 8,
241            -5 | 2 => 9,
242            -4 | 3 => 10,
243            -3 | 4 => 4,
244            -2 | 5 => 5,
245            -1 | 6 => 6,
246            _ => 7,
247        };
248        let ordinal = week as i16 * 7 + weekday.number_from_monday() as i16 - jan_4;
249
250        if ordinal <= 0 {
251            // Safety: `ordinal` is not zero.
252            return Ok(unsafe {
253                Self::__from_ordinal_date_unchecked(
254                    year - 1,
255                    ordinal
256                        .cast_unsigned()
257                        .wrapping_add(range_validated::days_in_year(year - 1)),
258                )
259            });
260        }
261
262        let is_leap_year = range_validated::is_leap_year(year);
263        let days_in_year = if is_leap_year { 366 } else { 365 };
264        let ordinal = ordinal.cast_unsigned();
265        Ok(if ordinal > days_in_year {
266            // Issue #777
267            if hint::unlikely(year == MAX_YEAR) {
268                return Err(error::ComponentRange::conditional("weekday"));
269            }
270            // Safety: the year is in range and `ordinal` is not zero.
271            unsafe { Self::__from_ordinal_date_unchecked(year + 1, ordinal - days_in_year) }
272        } else {
273            // Safety: `ordinal` is not zero and `is_leap_year` is correct.
274            unsafe { Self::from_parts(year, is_leap_year, ordinal) }
275        })
276    }
277
278    /// Create a `Date` from the Julian day.
279    ///
280    /// ```rust
281    /// # use time::Date;
282    /// # use time_macros::date;
283    /// assert_eq!(Date::from_julian_day(0), Ok(date!(-4713-11-24)));
284    /// assert_eq!(Date::from_julian_day(2_451_545), Ok(date!(2000-01-01)));
285    /// assert_eq!(Date::from_julian_day(2_458_485), Ok(date!(2019-01-01)));
286    /// assert_eq!(Date::from_julian_day(2_458_849), Ok(date!(2019-12-31)));
287    /// ```
288    #[doc(alias = "from_julian_date")]
289    #[inline]
290    pub const fn from_julian_day(julian_day: i32) -> Result<Self, error::ComponentRange> {
291        type JulianDay = ri32<{ Date::MIN.to_julian_day() }, { Date::MAX.to_julian_day() }>;
292        ensure_ranged!(JulianDay: julian_day);
293        // Safety: The Julian day number is in range.
294        Ok(unsafe { Self::from_julian_day_unchecked(julian_day) })
295    }
296
297    /// Create a `Date` from the Julian day.
298    ///
299    /// # Safety
300    ///
301    /// The provided Julian day number must be between `Date::MIN.to_julian_day()` and
302    /// `Date::MAX.to_julian_day()` inclusive.
303    #[inline]
304    pub(crate) const unsafe fn from_julian_day_unchecked(julian_day: i32) -> Self {
305        debug_assert!(julian_day >= Self::MIN.to_julian_day());
306        debug_assert!(julian_day <= Self::MAX.to_julian_day());
307
308        const ERAS: u32 = 5_949;
309        // Rata Die shift:
310        const D_SHIFT: u32 = 146097 * ERAS - 1_721_060;
311        // Year shift:
312        const Y_SHIFT: u32 = 400 * ERAS;
313
314        const CEN_MUL: u32 = ((4u64 << 47) / 146_097) as u32;
315        const JUL_MUL: u32 = ((4u64 << 40) / 1_461 + 1) as u32;
316        const CEN_CUT: u32 = ((365u64 << 32) / 36_525) as u32;
317
318        let day = julian_day.cast_unsigned().wrapping_add(D_SHIFT);
319        let c_n = (day as u64 * CEN_MUL as u64) >> 15;
320        let cen = (c_n >> 32) as u32;
321        let cpt = c_n as u32;
322        let ijy = cpt > CEN_CUT || cen.is_multiple_of(4);
323        let jul = day - cen / 4 + cen;
324        let y_n = (jul as u64 * JUL_MUL as u64) >> 8;
325        let yrs = (y_n >> 32) as u32;
326        let ypt = y_n as u32;
327
328        let year = yrs.wrapping_sub(Y_SHIFT).cast_signed();
329        let ordinal = ((ypt as u64 * 1_461) >> 34) as u32 + ijy as u32;
330        let leap = yrs.is_multiple_of(4) & ijy;
331
332        // Safety: `ordinal` is not zero and `is_leap_year` is correct, so long as the Julian day
333        // number is in range, which is guaranteed by the caller.
334        unsafe { Self::from_parts(year, leap, ordinal as u16) }
335    }
336
337    /// Whether `is_leap_year(self.year())` is `true`.
338    ///
339    /// This method is optimized to take advantage of the fact that the value is pre-computed upon
340    /// construction and stored in the bitpacked struct.
341    #[inline]
342    pub(crate) const fn is_in_leap_year(self) -> bool {
343        (self.value.get() >> 9) & 1 == 1
344    }
345
346    /// Get the year of the date.
347    ///
348    /// ```rust
349    /// # use time_macros::date;
350    /// assert_eq!(date!(2019-01-01).year(), 2019);
351    /// assert_eq!(date!(2019-12-31).year(), 2019);
352    /// assert_eq!(date!(2020-01-01).year(), 2020);
353    /// ```
354    #[inline]
355    pub const fn year(self) -> i32 {
356        self.value.get() >> 10
357    }
358
359    /// Get the month.
360    ///
361    /// ```rust
362    /// # use time::Month;
363    /// # use time_macros::date;
364    /// assert_eq!(date!(2019-01-01).month(), Month::January);
365    /// assert_eq!(date!(2019-12-31).month(), Month::December);
366    /// ```
367    #[inline]
368    pub const fn month(self) -> Month {
369        let ordinal = self.ordinal() as u32;
370        let jan_feb_len = 59 + self.is_in_leap_year() as u32;
371
372        let (month_adj, ordinal_adj) = if ordinal <= jan_feb_len {
373            (0, 0)
374        } else {
375            (2, jan_feb_len)
376        };
377
378        let ordinal = ordinal - ordinal_adj;
379        let month = ((ordinal * 268 + 8031) >> 13) + month_adj;
380
381        // Safety: `month` is guaranteed to be between 1 and 12 inclusive.
382        unsafe {
383            match Month::from_number(NonZero::new_unchecked(month as u8)) {
384                Ok(month) => month,
385                Err(_) => core::hint::unreachable_unchecked(),
386            }
387        }
388    }
389
390    /// Get the day of the month.
391    ///
392    /// The returned value will always be in the range `1..=31`.
393    ///
394    /// ```rust
395    /// # use time_macros::date;
396    /// assert_eq!(date!(2019-01-01).day(), 1);
397    /// assert_eq!(date!(2019-12-31).day(), 31);
398    /// ```
399    #[inline]
400    pub const fn day(self) -> u8 {
401        let ordinal = self.ordinal() as u32;
402        let jan_feb_len = 59 + self.is_in_leap_year() as u32;
403
404        let ordinal_adj = if ordinal <= jan_feb_len {
405            0
406        } else {
407            jan_feb_len
408        };
409
410        let ordinal = ordinal - ordinal_adj;
411        let month = (ordinal * 268 + 8031) >> 13;
412        let days_in_preceding_months = (month * 3917 - 3866) >> 7;
413        (ordinal - days_in_preceding_months) as u8
414    }
415
416    /// Get the day of the year.
417    ///
418    /// The returned value will always be in the range `1..=366` (`1..=365` for common years).
419    ///
420    /// ```rust
421    /// # use time_macros::date;
422    /// assert_eq!(date!(2019-01-01).ordinal(), 1);
423    /// assert_eq!(date!(2019-12-31).ordinal(), 365);
424    /// ```
425    #[inline]
426    pub const fn ordinal(self) -> u16 {
427        (self.value.get() & 0x1FF) as u16
428    }
429
430    /// Get the ISO 8601 year and week number.
431    #[inline]
432    pub(crate) const fn iso_year_week(self) -> (i32, u8) {
433        let (year, ordinal) = self.to_ordinal_date();
434
435        match ((ordinal + 10 - self.weekday().number_from_monday() as u16) / 7) as u8 {
436            0 => (year - 1, weeks_in_year(year - 1)),
437            53 if weeks_in_year(year) == 52 => (year + 1, 1),
438            week => (year, week),
439        }
440    }
441
442    /// Get the ISO week number.
443    ///
444    /// The returned value will always be in the range `1..=53`.
445    ///
446    /// ```rust
447    /// # use time_macros::date;
448    /// assert_eq!(date!(2019-01-01).iso_week(), 1);
449    /// assert_eq!(date!(2019-10-04).iso_week(), 40);
450    /// assert_eq!(date!(2020-01-01).iso_week(), 1);
451    /// assert_eq!(date!(2020-12-31).iso_week(), 53);
452    /// assert_eq!(date!(2021-01-01).iso_week(), 53);
453    /// ```
454    #[inline]
455    pub const fn iso_week(self) -> u8 {
456        self.iso_year_week().1
457    }
458
459    /// Get the week number where week 1 begins on the first Sunday.
460    ///
461    /// The returned value will always be in the range `0..=53`.
462    ///
463    /// ```rust
464    /// # use time_macros::date;
465    /// assert_eq!(date!(2019-01-01).sunday_based_week(), 0);
466    /// assert_eq!(date!(2020-01-01).sunday_based_week(), 0);
467    /// assert_eq!(date!(2020-12-31).sunday_based_week(), 52);
468    /// assert_eq!(date!(2021-01-01).sunday_based_week(), 0);
469    /// ```
470    #[inline]
471    pub const fn sunday_based_week(self) -> u8 {
472        ((self.ordinal().cast_signed() - self.weekday().number_days_from_sunday() as i16 + 6) / 7)
473            as u8
474    }
475
476    /// Get the week number where week 1 begins on the first Monday.
477    ///
478    /// The returned value will always be in the range `0..=53`.
479    ///
480    /// ```rust
481    /// # use time_macros::date;
482    /// assert_eq!(date!(2019-01-01).monday_based_week(), 0);
483    /// assert_eq!(date!(2020-01-01).monday_based_week(), 0);
484    /// assert_eq!(date!(2020-12-31).monday_based_week(), 52);
485    /// assert_eq!(date!(2021-01-01).monday_based_week(), 0);
486    /// ```
487    #[inline]
488    pub const fn monday_based_week(self) -> u8 {
489        ((self.ordinal().cast_signed() - self.weekday().number_days_from_monday() as i16 + 6) / 7)
490            as u8
491    }
492
493    /// Get the year, month, and day.
494    ///
495    /// ```rust
496    /// # use time::Month;
497    /// # use time_macros::date;
498    /// assert_eq!(
499    ///     date!(2019-01-01).to_calendar_date(),
500    ///     (2019, Month::January, 1)
501    /// );
502    /// ```
503    #[inline]
504    pub const fn to_calendar_date(self) -> (i32, Month, u8) {
505        let (year, ordinal) = self.to_ordinal_date();
506        let ordinal = ordinal as u32;
507        let jan_feb_len = 59 + self.is_in_leap_year() as u32;
508
509        let (month_adj, ordinal_adj) = if ordinal <= jan_feb_len {
510            (0, 0)
511        } else {
512            (2, jan_feb_len)
513        };
514
515        let ordinal = ordinal - ordinal_adj;
516        let month = (ordinal * 268 + 8031) >> 13;
517        let days_in_preceding_months = (month * 3917 - 3866) >> 7;
518        let day = ordinal - days_in_preceding_months;
519        let month = month + month_adj;
520
521        (
522            year,
523            // Safety: `month` is guaranteed to be between 1 and 12 inclusive.
524            unsafe {
525                match Month::from_number(NonZero::new_unchecked(month as u8)) {
526                    Ok(month) => month,
527                    Err(_) => core::hint::unreachable_unchecked(),
528                }
529            },
530            day as u8,
531        )
532    }
533
534    /// Get the year and ordinal day number.
535    ///
536    /// ```rust
537    /// # use time_macros::date;
538    /// assert_eq!(date!(2019-01-01).to_ordinal_date(), (2019, 1));
539    /// ```
540    #[inline]
541    pub const fn to_ordinal_date(self) -> (i32, u16) {
542        (self.year(), self.ordinal())
543    }
544
545    /// Get the ISO 8601 year, week number, and weekday.
546    ///
547    /// ```rust
548    /// # use time::Weekday::*;
549    /// # use time_macros::date;
550    /// assert_eq!(date!(2019-01-01).to_iso_week_date(), (2019, 1, Tuesday));
551    /// assert_eq!(date!(2019-10-04).to_iso_week_date(), (2019, 40, Friday));
552    /// assert_eq!(date!(2020-01-01).to_iso_week_date(), (2020, 1, Wednesday));
553    /// assert_eq!(date!(2020-12-31).to_iso_week_date(), (2020, 53, Thursday));
554    /// assert_eq!(date!(2021-01-01).to_iso_week_date(), (2020, 53, Friday));
555    /// ```
556    #[inline]
557    pub const fn to_iso_week_date(self) -> (i32, u8, Weekday) {
558        let (year, ordinal) = self.to_ordinal_date();
559        let weekday = self.weekday();
560
561        match ((ordinal + 10 - weekday.number_from_monday() as u16) / 7) as u8 {
562            0 => (year - 1, weeks_in_year(year - 1), weekday),
563            53 if weeks_in_year(year) == 52 => (year + 1, 1, weekday),
564            week => (year, week, weekday),
565        }
566    }
567
568    /// Get the weekday.
569    ///
570    /// ```rust
571    /// # use time::Weekday::*;
572    /// # use time_macros::date;
573    /// assert_eq!(date!(2019-01-01).weekday(), Tuesday);
574    /// assert_eq!(date!(2019-02-01).weekday(), Friday);
575    /// assert_eq!(date!(2019-03-01).weekday(), Friday);
576    /// assert_eq!(date!(2019-04-01).weekday(), Monday);
577    /// assert_eq!(date!(2019-05-01).weekday(), Wednesday);
578    /// assert_eq!(date!(2019-06-01).weekday(), Saturday);
579    /// assert_eq!(date!(2019-07-01).weekday(), Monday);
580    /// assert_eq!(date!(2019-08-01).weekday(), Thursday);
581    /// assert_eq!(date!(2019-09-01).weekday(), Sunday);
582    /// assert_eq!(date!(2019-10-01).weekday(), Tuesday);
583    /// assert_eq!(date!(2019-11-01).weekday(), Friday);
584    /// assert_eq!(date!(2019-12-01).weekday(), Sunday);
585    /// ```
586    #[inline]
587    pub const fn weekday(self) -> Weekday {
588        match self.to_julian_day() % 7 {
589            -6 | 1 => Weekday::Tuesday,
590            -5 | 2 => Weekday::Wednesday,
591            -4 | 3 => Weekday::Thursday,
592            -3 | 4 => Weekday::Friday,
593            -2 | 5 => Weekday::Saturday,
594            -1 | 6 => Weekday::Sunday,
595            val => {
596                debug_assert!(val == 0);
597                Weekday::Monday
598            }
599        }
600    }
601
602    /// Get the next calendar date.
603    ///
604    /// ```rust
605    /// # use time::Date;
606    /// # use time_macros::date;
607    /// assert_eq!(date!(2019-01-01).next_day(), Some(date!(2019-01-02)));
608    /// assert_eq!(date!(2019-01-31).next_day(), Some(date!(2019-02-01)));
609    /// assert_eq!(date!(2019-12-31).next_day(), Some(date!(2020-01-01)));
610    /// assert_eq!(Date::MAX.next_day(), None);
611    /// ```
612    #[inline]
613    pub const fn next_day(self) -> Option<Self> {
614        let is_last_day_of_year = matches!(self.value.get() & 0x3FF, 365 | 878);
615        if hint::unlikely(is_last_day_of_year) {
616            if self.value.get() == Self::MAX.value.get() {
617                None
618            } else {
619                // Safety: `ordinal` is not zero.
620                unsafe { Some(Self::__from_ordinal_date_unchecked(self.year() + 1, 1)) }
621            }
622        } else {
623            // Safety: `self` is not the last day of the year.
624            Some(unsafe { self.add_days_unchecked(1) })
625        }
626    }
627
628    /// Get the previous calendar date.
629    ///
630    /// ```rust
631    /// # use time::Date;
632    /// # use time_macros::date;
633    /// assert_eq!(date!(2019-01-02).previous_day(), Some(date!(2019-01-01)));
634    /// assert_eq!(date!(2019-02-01).previous_day(), Some(date!(2019-01-31)));
635    /// assert_eq!(date!(2020-01-01).previous_day(), Some(date!(2019-12-31)));
636    /// assert_eq!(Date::MIN.previous_day(), None);
637    /// ```
638    #[inline]
639    pub const fn previous_day(self) -> Option<Self> {
640        if hint::likely(self.ordinal() != 1) {
641            // Safety: `self` is not the first day of the year.
642            Some(unsafe { self.add_days_unchecked(-1) })
643        } else if self.value.get() == Self::MIN.value.get() {
644            None
645        } else {
646            let year = self.year() - 1;
647            let is_leap_year = range_validated::is_leap_year(year);
648            let ordinal = if is_leap_year { 366 } else { 365 };
649            // Safety: `ordinal` is not zero, `is_leap_year` is correct.
650            Some(unsafe { Self::from_parts(year, is_leap_year, ordinal) })
651        }
652    }
653
654    /// Calculates the first occurrence of a weekday that is strictly later than a given `Date`.
655    ///
656    /// # Panics
657    /// Panics if an overflow occurred.
658    ///
659    /// # Examples
660    /// ```
661    /// # use time::Weekday;
662    /// # use time_macros::date;
663    /// assert_eq!(
664    ///     date!(2023-06-28).next_occurrence(Weekday::Monday),
665    ///     date!(2023-07-03)
666    /// );
667    /// assert_eq!(
668    ///     date!(2023-06-19).next_occurrence(Weekday::Monday),
669    ///     date!(2023-06-26)
670    /// );
671    /// ```
672    #[inline]
673    #[track_caller]
674    pub const fn next_occurrence(self, weekday: Weekday) -> Self {
675        self.checked_next_occurrence(weekday)
676            .expect("overflow calculating the next occurrence of a weekday")
677    }
678
679    /// Calculates the first occurrence of a weekday that is strictly earlier than a given `Date`.
680    ///
681    /// # Panics
682    /// Panics if an overflow occurred.
683    ///
684    /// # Examples
685    /// ```
686    /// # use time::Weekday;
687    /// # use time_macros::date;
688    /// assert_eq!(
689    ///     date!(2023-06-28).prev_occurrence(Weekday::Monday),
690    ///     date!(2023-06-26)
691    /// );
692    /// assert_eq!(
693    ///     date!(2023-06-19).prev_occurrence(Weekday::Monday),
694    ///     date!(2023-06-12)
695    /// );
696    /// ```
697    #[inline]
698    #[track_caller]
699    pub const fn prev_occurrence(self, weekday: Weekday) -> Self {
700        self.checked_prev_occurrence(weekday)
701            .expect("overflow calculating the previous occurrence of a weekday")
702    }
703
704    /// Calculates the `n`th occurrence of a weekday that is strictly later than a given `Date`.
705    ///
706    /// # Panics
707    /// Panics if an overflow occurred or if `n == 0`.
708    ///
709    /// # Examples
710    /// ```
711    /// # use time::Weekday;
712    /// # use time_macros::date;
713    /// assert_eq!(
714    ///     date!(2023-06-25).nth_next_occurrence(Weekday::Monday, 5),
715    ///     date!(2023-07-24)
716    /// );
717    /// assert_eq!(
718    ///     date!(2023-06-26).nth_next_occurrence(Weekday::Monday, 5),
719    ///     date!(2023-07-31)
720    /// );
721    /// ```
722    #[inline]
723    #[track_caller]
724    pub const fn nth_next_occurrence(self, weekday: Weekday, n: u8) -> Self {
725        self.checked_nth_next_occurrence(weekday, n)
726            .expect("overflow calculating the next occurrence of a weekday")
727    }
728
729    /// Calculates the `n`th occurrence of a weekday that is strictly earlier than a given `Date`.
730    ///
731    /// # Panics
732    /// Panics if an overflow occurred or if `n == 0`.
733    ///
734    /// # Examples
735    /// ```
736    /// # use time::Weekday;
737    /// # use time_macros::date;
738    /// assert_eq!(
739    ///     date!(2023-06-27).nth_prev_occurrence(Weekday::Monday, 3),
740    ///     date!(2023-06-12)
741    /// );
742    /// assert_eq!(
743    ///     date!(2023-06-26).nth_prev_occurrence(Weekday::Monday, 3),
744    ///     date!(2023-06-05)
745    /// );
746    /// ```
747    #[inline]
748    #[track_caller]
749    pub const fn nth_prev_occurrence(self, weekday: Weekday, n: u8) -> Self {
750        self.checked_nth_prev_occurrence(weekday, n)
751            .expect("overflow calculating the previous occurrence of a weekday")
752    }
753
754    /// Create an iterator of dates from `self` to `end` inclusive.
755    ///
756    /// ```rust
757    /// # use time_macros::date;
758    /// let mut iter = date!(2019-01-01).iter_to(date!(2019-01-03));
759    /// assert_eq!(iter.next(), Some(date!(2019-01-01)));
760    /// assert_eq!(iter.next(), Some(date!(2019-01-02)));
761    /// assert_eq!(iter.next(), Some(date!(2019-01-03)));
762    /// assert_eq!(iter.next(), None);
763    /// ```
764    #[inline]
765    pub const fn iter_to(self, end: Self) -> DateIter {
766        DateIter::new(self, end)
767    }
768
769    /// Get the Julian day for the date.
770    ///
771    /// ```rust
772    /// # use time_macros::date;
773    /// assert_eq!(date!(-4713-11-24).to_julian_day(), 0);
774    /// assert_eq!(date!(2000-01-01).to_julian_day(), 2_451_545);
775    /// assert_eq!(date!(2019-01-01).to_julian_day(), 2_458_485);
776    /// assert_eq!(date!(2019-12-31).to_julian_day(), 2_458_849);
777    /// ```
778    #[inline]
779    pub const fn to_julian_day(self) -> i32 {
780        let (year, ordinal) = self.to_ordinal_date();
781
782        // The algorithm requires a non-negative year. Add the lowest value to make it so. This is
783        // adjusted for at the end with the final subtraction.
784        let adj_year = year + 999_999;
785        let century = adj_year / 100;
786
787        let days_before_year = (1461 * adj_year as i64 / 4) as i32 - century + century / 4;
788        days_before_year + ordinal as i32 - 363_521_075
789    }
790
791    /// Add a number of days to the date without checking for overflow.
792    ///
793    /// # Safety
794    ///
795    /// `self.ordinal() + days` must be in the range `1..=366` for leap years and `1..=365` for
796    /// common years.
797    #[inline]
798    pub(crate) const unsafe fn add_days_unchecked(mut self, days: i32) -> Self {
799        // Safety: asserted by caller
800        self.value = unsafe { NonZero::new_unchecked(self.value.get() + days) };
801        self
802    }
803
804    /// Computes `self + duration`, returning `None` if an overflow occurred.
805    ///
806    /// ```rust
807    /// # use time::{Date, ext::NumericalDuration};
808    /// # use time_macros::date;
809    /// assert_eq!(Date::MAX.checked_add(1.days()), None);
810    /// assert_eq!(Date::MIN.checked_add((-2).days()), None);
811    /// assert_eq!(
812    ///     date!(2020-12-31).checked_add(2.days()),
813    ///     Some(date!(2021-01-02))
814    /// );
815    /// ```
816    ///
817    /// # Note
818    ///
819    /// This function only takes whole days into account.
820    ///
821    /// ```rust
822    /// # use time::{Date, ext::NumericalDuration};
823    /// # use time_macros::date;
824    /// assert_eq!(Date::MAX.checked_add(23.hours()), Some(Date::MAX));
825    /// assert_eq!(Date::MIN.checked_add((-23).hours()), Some(Date::MIN));
826    /// assert_eq!(
827    ///     date!(2020-12-31).checked_add(23.hours()),
828    ///     Some(date!(2020-12-31))
829    /// );
830    /// assert_eq!(
831    ///     date!(2020-12-31).checked_add(47.hours()),
832    ///     Some(date!(2021-01-01))
833    /// );
834    /// ```
835    #[inline]
836    pub const fn checked_add(self, duration: SignedDuration) -> Option<Self> {
837        let whole_days = duration.whole_days();
838        if whole_days < i32::MIN as i64 || whole_days > i32::MAX as i64 {
839            return None;
840        }
841
842        let year = self.year();
843        let is_leap_year = self.is_in_leap_year();
844        let ordinal = self.ordinal() as i32;
845
846        let days_in_year = if is_leap_year { 366 } else { 365 };
847        let whole_days = whole_days as i32;
848
849        // Fast path for when the result is in the same year.
850        if let Some(new_ordinal) = ordinal.checked_add(whole_days)
851            && new_ordinal >= 1
852            && new_ordinal <= days_in_year
853        {
854            // Safety: `new_ordinal` is in range and `is_leap_year` is correct
855            return Some(unsafe { Self::from_parts(year, is_leap_year, new_ordinal as u16) });
856        }
857
858        let julian_day = const_try_opt!(self.to_julian_day().checked_add(whole_days));
859        if let Ok(date) = Self::from_julian_day(julian_day) {
860            Some(date)
861        } else {
862            None
863        }
864    }
865
866    /// Computes `self + duration`, returning `None` if an overflow occurred.
867    ///
868    /// ```rust
869    /// # use time::{Date, ext::NumericalStdDuration};
870    /// # use time_macros::date;
871    /// assert_eq!(Date::MAX.checked_add_std(1.std_days()), None);
872    /// assert_eq!(
873    ///     date!(2020-12-31).checked_add_std(2.std_days()),
874    ///     Some(date!(2021-01-02))
875    /// );
876    /// ```
877    ///
878    /// # Note
879    ///
880    /// This function only takes whole days into account.
881    ///
882    /// ```rust
883    /// # use time::{Date, ext::NumericalStdDuration};
884    /// # use time_macros::date;
885    /// assert_eq!(Date::MAX.checked_add_std(23.std_hours()), Some(Date::MAX));
886    /// assert_eq!(
887    ///     date!(2020-12-31).checked_add_std(23.std_hours()),
888    ///     Some(date!(2020-12-31))
889    /// );
890    /// assert_eq!(
891    ///     date!(2020-12-31).checked_add_std(47.std_hours()),
892    ///     Some(date!(2021-01-01))
893    /// );
894    /// ```
895    #[inline]
896    pub const fn checked_add_std(self, duration: StdDuration) -> Option<Self> {
897        let whole_days = duration.as_secs() / Second::per_t::<u64>(Day);
898        if whole_days > i32::MAX as u64 {
899            return None;
900        }
901
902        let year = self.year();
903        let is_leap_year = self.is_in_leap_year();
904        let ordinal = self.ordinal() as i32;
905
906        let days_in_year = if is_leap_year { 366 } else { 365 };
907        let whole_days = whole_days as i32;
908
909        // Fast path for when the result is in the same year.
910        if let Some(new_ordinal) = ordinal.checked_add(whole_days)
911            && new_ordinal >= 1
912            && new_ordinal <= days_in_year
913        {
914            // Safety: `new_ordinal` is in range and `is_leap_year` is correct
915            return Some(unsafe { Self::from_parts(year, is_leap_year, new_ordinal as u16) });
916        }
917
918        let julian_day = const_try_opt!(self.to_julian_day().checked_add(whole_days));
919        if let Ok(date) = Self::from_julian_day(julian_day) {
920            Some(date)
921        } else {
922            None
923        }
924    }
925
926    /// Computes `self - duration`, returning `None` if an overflow occurred.
927    ///
928    /// ```
929    /// # use time::{Date, ext::NumericalDuration};
930    /// # use time_macros::date;
931    /// assert_eq!(Date::MAX.checked_sub((-2).days()), None);
932    /// assert_eq!(Date::MIN.checked_sub(1.days()), None);
933    /// assert_eq!(
934    ///     date!(2020-12-31).checked_sub(2.days()),
935    ///     Some(date!(2020-12-29))
936    /// );
937    /// ```
938    ///
939    /// # Note
940    ///
941    /// This function only takes whole days into account.
942    ///
943    /// ```
944    /// # use time::{Date, ext::NumericalDuration};
945    /// # use time_macros::date;
946    /// assert_eq!(Date::MAX.checked_sub((-23).hours()), Some(Date::MAX));
947    /// assert_eq!(Date::MIN.checked_sub(23.hours()), Some(Date::MIN));
948    /// assert_eq!(
949    ///     date!(2020-12-31).checked_sub(23.hours()),
950    ///     Some(date!(2020-12-31))
951    /// );
952    /// assert_eq!(
953    ///     date!(2020-12-31).checked_sub(47.hours()),
954    ///     Some(date!(2020-12-30))
955    /// );
956    /// ```
957    #[inline]
958    pub const fn checked_sub(self, duration: SignedDuration) -> Option<Self> {
959        let whole_days = duration.whole_days();
960        if whole_days < i32::MIN as i64 || whole_days > i32::MAX as i64 {
961            return None;
962        }
963
964        let year = self.year();
965        let is_leap_year = self.is_in_leap_year();
966        let ordinal = self.ordinal() as i32;
967
968        let days_in_year = if is_leap_year { 366 } else { 365 };
969        let whole_days = whole_days as i32;
970
971        // Fast path for when the result is in the same year.
972        if let Some(new_ordinal) = ordinal.checked_sub(whole_days)
973            && new_ordinal >= 1
974            && new_ordinal <= days_in_year
975        {
976            // Safety: `new_ordinal` is in range and `is_leap_year` is correct
977            return Some(unsafe { Self::from_parts(year, is_leap_year, new_ordinal as u16) });
978        }
979
980        let julian_day = const_try_opt!(self.to_julian_day().checked_sub(whole_days));
981        if let Ok(date) = Self::from_julian_day(julian_day) {
982            Some(date)
983        } else {
984            None
985        }
986    }
987
988    /// Computes `self - duration`, returning `None` if an overflow occurred.
989    ///
990    /// ```
991    /// # use time::{Date, ext::NumericalStdDuration};
992    /// # use time_macros::date;
993    /// assert_eq!(Date::MIN.checked_sub_std(1.std_days()), None);
994    /// assert_eq!(
995    ///     date!(2020-12-31).checked_sub_std(2.std_days()),
996    ///     Some(date!(2020-12-29))
997    /// );
998    /// ```
999    ///
1000    /// # Note
1001    ///
1002    /// This function only takes whole days into account.
1003    ///
1004    /// ```
1005    /// # use time::{Date, ext::NumericalStdDuration};
1006    /// # use time_macros::date;
1007    /// assert_eq!(Date::MIN.checked_sub_std(23.std_hours()), Some(Date::MIN));
1008    /// assert_eq!(
1009    ///     date!(2020-12-31).checked_sub_std(23.std_hours()),
1010    ///     Some(date!(2020-12-31))
1011    /// );
1012    /// assert_eq!(
1013    ///     date!(2020-12-31).checked_sub_std(47.std_hours()),
1014    ///     Some(date!(2020-12-30))
1015    /// );
1016    /// ```
1017    #[inline]
1018    pub const fn checked_sub_std(self, duration: StdDuration) -> Option<Self> {
1019        let whole_days = duration.as_secs() / Second::per_t::<u64>(Day);
1020        if whole_days > i32::MAX as u64 {
1021            return None;
1022        }
1023
1024        let year = self.year();
1025        let is_leap_year = self.is_in_leap_year();
1026        let ordinal = self.ordinal() as i32;
1027
1028        let days_in_year = if is_leap_year { 366 } else { 365 };
1029        let whole_days = whole_days as i32;
1030
1031        // Fast path for when the result is in the same year.
1032        if let Some(new_ordinal) = ordinal.checked_sub(whole_days)
1033            && new_ordinal >= 1
1034            && new_ordinal <= days_in_year
1035        {
1036            // Safety: `new_ordinal` is in range and `is_leap_year` is correct
1037            return Some(unsafe { Self::from_parts(year, is_leap_year, new_ordinal as u16) });
1038        }
1039
1040        let julian_day = const_try_opt!(self.to_julian_day().checked_sub(whole_days));
1041        if let Ok(date) = Self::from_julian_day(julian_day) {
1042            Some(date)
1043        } else {
1044            None
1045        }
1046    }
1047
1048    /// Calculates the first occurrence of a weekday that is strictly later than a given `Date`.
1049    /// Returns `None` if an overflow occurred.
1050    #[inline]
1051    pub(crate) const fn checked_next_occurrence(self, weekday: Weekday) -> Option<Self> {
1052        let day_diff = match weekday as i8 - self.weekday() as i8 {
1053            1 | -6 => 1,
1054            2 | -5 => 2,
1055            3 | -4 => 3,
1056            4 | -3 => 4,
1057            5 | -2 => 5,
1058            6 | -1 => 6,
1059            val => {
1060                debug_assert!(val == 0);
1061                7
1062            }
1063        };
1064
1065        self.checked_add(SignedDuration::days(day_diff))
1066    }
1067
1068    /// Calculates the first occurrence of a weekday that is strictly earlier than a given `Date`.
1069    /// Returns `None` if an overflow occurred.
1070    #[inline]
1071    pub(crate) const fn checked_prev_occurrence(self, weekday: Weekday) -> Option<Self> {
1072        let day_diff = match weekday as i8 - self.weekday() as i8 {
1073            1 | -6 => 6,
1074            2 | -5 => 5,
1075            3 | -4 => 4,
1076            4 | -3 => 3,
1077            5 | -2 => 2,
1078            6 | -1 => 1,
1079            val => {
1080                debug_assert!(val == 0);
1081                7
1082            }
1083        };
1084
1085        self.checked_sub(SignedDuration::days(day_diff))
1086    }
1087
1088    /// Calculates the `n`th occurrence of a weekday that is strictly later than a given `Date`.
1089    /// Returns `None` if an overflow occurred or if `n == 0`.
1090    #[inline]
1091    pub(crate) const fn checked_nth_next_occurrence(self, weekday: Weekday, n: u8) -> Option<Self> {
1092        if n == 0 {
1093            return None;
1094        }
1095
1096        const_try_opt!(self.checked_next_occurrence(weekday))
1097            .checked_add(SignedDuration::weeks(n as i64 - 1))
1098    }
1099
1100    /// Calculates the `n`th occurrence of a weekday that is strictly earlier than a given `Date`.
1101    /// Returns `None` if an overflow occurred or if `n == 0`.
1102    #[inline]
1103    pub(crate) const fn checked_nth_prev_occurrence(self, weekday: Weekday, n: u8) -> Option<Self> {
1104        if n == 0 {
1105            return None;
1106        }
1107
1108        const_try_opt!(self.checked_prev_occurrence(weekday))
1109            .checked_sub(SignedDuration::weeks(n as i64 - 1))
1110    }
1111
1112    /// Computes `self + duration`, saturating value on overflow.
1113    ///
1114    /// ```rust
1115    /// # use time::{Date, ext::NumericalDuration};
1116    /// # use time_macros::date;
1117    /// assert_eq!(Date::MAX.saturating_add(1.days()), Date::MAX);
1118    /// assert_eq!(Date::MIN.saturating_add((-2).days()), Date::MIN);
1119    /// assert_eq!(
1120    ///     date!(2020-12-31).saturating_add(2.days()),
1121    ///     date!(2021-01-02)
1122    /// );
1123    /// ```
1124    ///
1125    /// # Note
1126    ///
1127    /// This function only takes whole days into account.
1128    ///
1129    /// ```rust
1130    /// # use time::ext::NumericalDuration;
1131    /// # use time_macros::date;
1132    /// assert_eq!(
1133    ///     date!(2020-12-31).saturating_add(23.hours()),
1134    ///     date!(2020-12-31)
1135    /// );
1136    /// assert_eq!(
1137    ///     date!(2020-12-31).saturating_add(47.hours()),
1138    ///     date!(2021-01-01)
1139    /// );
1140    /// ```
1141    #[inline]
1142    pub const fn saturating_add(self, duration: SignedDuration) -> Self {
1143        if let Some(datetime) = self.checked_add(duration) {
1144            datetime
1145        } else if duration.is_negative() {
1146            Self::MIN
1147        } else {
1148            debug_assert!(duration.is_positive());
1149            Self::MAX
1150        }
1151    }
1152
1153    /// Computes `self - duration`, saturating value on overflow.
1154    ///
1155    /// ```
1156    /// # use time::{Date, ext::NumericalDuration};
1157    /// # use time_macros::date;
1158    /// assert_eq!(Date::MAX.saturating_sub((-2).days()), Date::MAX);
1159    /// assert_eq!(Date::MIN.saturating_sub(1.days()), Date::MIN);
1160    /// assert_eq!(
1161    ///     date!(2020-12-31).saturating_sub(2.days()),
1162    ///     date!(2020-12-29)
1163    /// );
1164    /// ```
1165    ///
1166    /// # Note
1167    ///
1168    /// This function only takes whole days into account.
1169    ///
1170    /// ```
1171    /// # use time::ext::NumericalDuration;
1172    /// # use time_macros::date;
1173    /// assert_eq!(
1174    ///     date!(2020-12-31).saturating_sub(23.hours()),
1175    ///     date!(2020-12-31)
1176    /// );
1177    /// assert_eq!(
1178    ///     date!(2020-12-31).saturating_sub(47.hours()),
1179    ///     date!(2020-12-30)
1180    /// );
1181    /// ```
1182    #[inline]
1183    pub const fn saturating_sub(self, duration: SignedDuration) -> Self {
1184        if let Some(datetime) = self.checked_sub(duration) {
1185            datetime
1186        } else if duration.is_negative() {
1187            Self::MAX
1188        } else {
1189            debug_assert!(duration.is_positive());
1190            Self::MIN
1191        }
1192    }
1193
1194    /// Replace the year. The month and day will be unchanged.
1195    ///
1196    /// ```rust
1197    /// # use time_macros::date;
1198    /// assert_eq!(
1199    ///     date!(2022-02-18).replace_year(2019),
1200    ///     Ok(date!(2019-02-18))
1201    /// );
1202    /// assert!(date!(2022-02-18).replace_year(-1_000_000_000).is_err()); // -1_000_000_000 isn't a valid year
1203    /// assert!(date!(2022-02-18).replace_year(1_000_000_000).is_err()); // 1_000_000_000 isn't a valid year
1204    /// ```
1205    #[inline]
1206    #[must_use = "This method does not mutate the original `Date`."]
1207    pub const fn replace_year(self, year: i32) -> Result<Self, error::ComponentRange> {
1208        ensure_ranged!(Year: year);
1209
1210        let new_is_leap_year = range_validated::is_leap_year(year);
1211        let ordinal = self.ordinal();
1212
1213        // Dates in January and February are unaffected by leap years.
1214        if ordinal <= 59 {
1215            // Safety: `ordinal` is not zero and `is_leap_year` is correct.
1216            return Ok(unsafe { Self::from_parts(year, new_is_leap_year, ordinal) });
1217        }
1218
1219        match (self.is_in_leap_year(), new_is_leap_year) {
1220            (false, false) | (true, true) => {
1221                Ok(Self {
1222                    // Safety: Whether the year is leap or common, the ordinal are unchanged, with
1223                    // only the year being replaced.
1224                    value: unsafe {
1225                        NonZero::new_unchecked((year << 10) | (self.value.get() & 0x3FF))
1226                    },
1227                })
1228            }
1229            // February 29 does not exist in common years.
1230            (true, false) if ordinal == 60 => Err(error::ComponentRange::conditional("day")),
1231            // We're going from a common year to a leap year. Shift dates in March and later by
1232            // one day.
1233            // Safety: `ordinal` is not zero and `is_leap_year` is correct.
1234            (false, true) => Ok(unsafe { Self::from_parts(year, true, ordinal + 1) }),
1235            // We're going from a leap year to a common year. Shift dates in January and
1236            // February by one day.
1237            // Safety: `ordinal` is not zero and `is_leap_year` is correct.
1238            (true, false) => Ok(unsafe { Self::from_parts(year, false, ordinal - 1) }),
1239        }
1240    }
1241
1242    /// Replace the month of the year.
1243    ///
1244    /// ```rust
1245    /// # use time_macros::date;
1246    /// # use time::Month;
1247    /// assert_eq!(
1248    ///     date!(2022-02-18).replace_month(Month::January),
1249    ///     Ok(date!(2022-01-18))
1250    /// );
1251    /// assert!(date!(2022-01-30)
1252    ///     .replace_month(Month::February)
1253    ///     .is_err()); // 30 isn't a valid day in February
1254    /// ```
1255    #[inline]
1256    #[must_use = "This method does not mutate the original `Date`."]
1257    pub const fn replace_month(self, month: Month) -> Result<Self, error::ComponentRange> {
1258        /// Cumulative days through the beginning of a month in both common and leap years.
1259        const DAYS_CUMULATIVE_COMMON_LEAP: [[u16; 12]; 2] = [
1260            [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
1261            [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335],
1262        ];
1263
1264        let (year, ordinal) = self.to_ordinal_date();
1265        let mut ordinal = ordinal as u32;
1266        let is_leap_year = self.is_in_leap_year();
1267        let jan_feb_len = 59 + is_leap_year as u32;
1268
1269        if ordinal > jan_feb_len {
1270            ordinal -= jan_feb_len;
1271        }
1272        let current_month = (ordinal * 268 + 8031) >> 13;
1273        let days_in_preceding_months = (current_month * 3917 - 3866) >> 7;
1274        let day = (ordinal - days_in_preceding_months) as u8;
1275
1276        match day {
1277            1..=28 => {}
1278            29..=31 if day <= days_in_month_leap(month as u8, is_leap_year) => hint::cold_path(),
1279            _ => {
1280                hint::cold_path();
1281                return Err(error::ComponentRange::conditional("day"));
1282            }
1283        }
1284
1285        // Safety: `ordinal` is not zero and `is_leap_year` is correct.
1286        Ok(unsafe {
1287            Self::from_parts(
1288                year,
1289                is_leap_year,
1290                DAYS_CUMULATIVE_COMMON_LEAP[is_leap_year as usize][month as usize - 1] + day as u16,
1291            )
1292        })
1293    }
1294
1295    /// Replace the day of the month.
1296    ///
1297    /// ```rust
1298    /// # use time_macros::date;
1299    /// assert_eq!(date!(2022-02-18).replace_day(1), Ok(date!(2022-02-01)));
1300    /// assert!(date!(2022-02-18).replace_day(0).is_err()); // 0 isn't a valid day
1301    /// assert!(date!(2022-02-18).replace_day(30).is_err()); // 30 isn't a valid day in February
1302    /// ```
1303    #[inline]
1304    #[must_use = "This method does not mutate the original `Date`."]
1305    pub const fn replace_day(self, day: u8) -> Result<Self, error::ComponentRange> {
1306        let is_leap_year = self.is_in_leap_year();
1307        match day {
1308            1..=28 => {}
1309            29..=31 if day <= days_in_month_leap(self.month() as u8, is_leap_year) => {
1310                hint::cold_path()
1311            }
1312            _ => {
1313                hint::cold_path();
1314                return Err(error::ComponentRange::conditional("day"));
1315            }
1316        }
1317
1318        // Safety: `ordinal` is not zero and `is_leap_year` is correct.
1319        Ok(unsafe {
1320            Self::from_parts(
1321                self.year(),
1322                is_leap_year,
1323                (self.ordinal().cast_signed() - self.day() as i16 + day as i16).cast_unsigned(),
1324            )
1325        })
1326    }
1327
1328    /// Replace the day of the year.
1329    ///
1330    /// ```rust
1331    /// # use time_macros::date;
1332    /// assert_eq!(date!(2022-049).replace_ordinal(1), Ok(date!(2022-001)));
1333    /// assert!(date!(2022-049).replace_ordinal(0).is_err()); // 0 isn't a valid ordinal
1334    /// assert!(date!(2022-049).replace_ordinal(366).is_err()); // 2022 isn't a leap year
1335    /// ```
1336    #[inline]
1337    #[must_use = "This method does not mutate the original `Date`."]
1338    pub const fn replace_ordinal(self, ordinal: u16) -> Result<Self, error::ComponentRange> {
1339        let is_leap_year = self.is_in_leap_year();
1340        match ordinal {
1341            1..=365 => {}
1342            366 if is_leap_year => hint::cold_path(),
1343            _ => {
1344                hint::cold_path();
1345                return Err(error::ComponentRange::conditional("ordinal"));
1346            }
1347        }
1348
1349        // Safety: `ordinal` is in range and `is_leap_year` is correct.
1350        Ok(unsafe { Self::from_parts(self.year(), is_leap_year, ordinal) })
1351    }
1352}
1353
1354/// Methods to add a [`Time`] component, resulting in a [`PlainDateTime`].
1355impl Date {
1356    /// Create a [`PlainDateTime`] using the existing date. The [`Time`] component will be set to
1357    /// midnight.
1358    ///
1359    /// ```rust
1360    /// # use time_macros::{date, datetime};
1361    /// assert_eq!(date!(1970-01-01).midnight(), datetime!(1970-01-01 0:00));
1362    /// ```
1363    #[inline]
1364    pub const fn midnight(self) -> PlainDateTime {
1365        PlainDateTime::new(self, Time::MIDNIGHT)
1366    }
1367
1368    /// Create a [`PlainDateTime`] using the existing date and the provided [`Time`].
1369    ///
1370    /// ```rust
1371    /// # use time_macros::{date, datetime, time};
1372    /// assert_eq!(
1373    ///     date!(1970-01-01).with_time(time!(0:00)),
1374    ///     datetime!(1970-01-01 0:00),
1375    /// );
1376    /// ```
1377    #[inline]
1378    pub const fn with_time(self, time: Time) -> PlainDateTime {
1379        PlainDateTime::new(self, time)
1380    }
1381
1382    /// Attempt to create a [`PlainDateTime`] using the existing date and the provided time.
1383    ///
1384    /// ```rust
1385    /// # use time_macros::date;
1386    /// assert!(date!(1970-01-01).with_hms(0, 0, 0).is_ok());
1387    /// assert!(date!(1970-01-01).with_hms(24, 0, 0).is_err());
1388    /// ```
1389    #[inline]
1390    pub const fn with_hms(
1391        self,
1392        hour: u8,
1393        minute: u8,
1394        second: u8,
1395    ) -> Result<PlainDateTime, error::ComponentRange> {
1396        Ok(PlainDateTime::new(
1397            self,
1398            const_try!(Time::from_hms(hour, minute, second)),
1399        ))
1400    }
1401
1402    /// Attempt to create a [`PlainDateTime`] using the existing date and the provided time.
1403    ///
1404    /// ```rust
1405    /// # use time_macros::date;
1406    /// assert!(date!(1970-01-01).with_hms_milli(0, 0, 0, 0).is_ok());
1407    /// assert!(date!(1970-01-01).with_hms_milli(24, 0, 0, 0).is_err());
1408    /// ```
1409    #[inline]
1410    pub const fn with_hms_milli(
1411        self,
1412        hour: u8,
1413        minute: u8,
1414        second: u8,
1415        millisecond: u16,
1416    ) -> Result<PlainDateTime, error::ComponentRange> {
1417        Ok(PlainDateTime::new(
1418            self,
1419            const_try!(Time::from_hms_milli(hour, minute, second, millisecond)),
1420        ))
1421    }
1422
1423    /// Attempt to create a [`PlainDateTime`] using the existing date and the provided time.
1424    ///
1425    /// ```rust
1426    /// # use time_macros::date;
1427    /// assert!(date!(1970-01-01).with_hms_micro(0, 0, 0, 0).is_ok());
1428    /// assert!(date!(1970-01-01).with_hms_micro(24, 0, 0, 0).is_err());
1429    /// ```
1430    #[inline]
1431    pub const fn with_hms_micro(
1432        self,
1433        hour: u8,
1434        minute: u8,
1435        second: u8,
1436        microsecond: u32,
1437    ) -> Result<PlainDateTime, error::ComponentRange> {
1438        Ok(PlainDateTime::new(
1439            self,
1440            const_try!(Time::from_hms_micro(hour, minute, second, microsecond)),
1441        ))
1442    }
1443
1444    /// Attempt to create a [`PlainDateTime`] using the existing date and the provided time.
1445    ///
1446    /// ```rust
1447    /// # use time_macros::date;
1448    /// assert!(date!(1970-01-01).with_hms_nano(0, 0, 0, 0).is_ok());
1449    /// assert!(date!(1970-01-01).with_hms_nano(24, 0, 0, 0).is_err());
1450    /// ```
1451    #[inline]
1452    pub const fn with_hms_nano(
1453        self,
1454        hour: u8,
1455        minute: u8,
1456        second: u8,
1457        nanosecond: u32,
1458    ) -> Result<PlainDateTime, error::ComponentRange> {
1459        Ok(PlainDateTime::new(
1460            self,
1461            const_try!(Time::from_hms_nano(hour, minute, second, nanosecond)),
1462        ))
1463    }
1464}
1465
1466#[cfg(feature = "formatting")]
1467impl Date {
1468    /// Format the `Date` using the provided [format description](crate::format_description).
1469    #[inline]
1470    pub fn format_into(
1471        self,
1472        output: &mut (impl io::Write + ?Sized),
1473        format: &(impl Formattable + ?Sized),
1474    ) -> Result<usize, error::Format> {
1475        let mut output = crate::formatting::Output {
1476            bytes_written: 0,
1477            output,
1478        };
1479        try_likely_ok!(format.format_into(
1480            &mut output,
1481            &self,
1482            &mut Default::default(),
1483            PrivateMethod,
1484        ));
1485        Ok(output.bytes_written)
1486    }
1487
1488    /// Format the `Date` using the provided [format description](crate::format_description).
1489    ///
1490    /// ```rust
1491    /// # use time::format_description;
1492    /// # use time_macros::date;
1493    /// let format = format_description::parse_borrowed::<3>("[year]-[month]-[day]")?;
1494    /// assert_eq!(date!(2020-01-02).format(&format)?, "2020-01-02");
1495    /// # Ok::<_, time::Error>(())
1496    /// ```
1497    #[inline]
1498    pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result<String, error::Format> {
1499        format.format(&self, &mut Default::default(), PrivateMethod)
1500    }
1501}
1502
1503#[cfg(feature = "parsing")]
1504impl Date {
1505    /// Parse a `Date` from the input using the provided [format
1506    /// description](crate::format_description).
1507    ///
1508    /// ```rust
1509    /// # use time::Date;
1510    /// # use time_macros::{date, format_description};
1511    /// let format = format_description!("[year]-[month]-[day]");
1512    /// assert_eq!(Date::parse("2020-01-02", &format)?, date!(2020-01-02));
1513    /// # Ok::<_, time::Error>(())
1514    /// ```
1515    #[inline]
1516    pub fn parse(
1517        input: &str,
1518        description: &(impl Parsable + ?Sized),
1519    ) -> Result<Self, error::Parse> {
1520        description.parse_date(input.as_bytes(), None, PrivateMethod)
1521    }
1522
1523    /// Parse a `Date` from the input using the provided [format
1524    /// description](crate::format_description) and default values.
1525    ///
1526    /// ```rust
1527    /// # use time::Date;
1528    /// # use time::parsing::Parsed;
1529    /// # use time_macros::{date, format_description};
1530    /// let format = format_description!("[month]-[day]");
1531    /// let defaults = Parsed::new().with_year(2020).expect("2020 is a valid year");
1532    /// assert_eq!(
1533    ///     Date::parse_with_defaults(b"01-15", &format, defaults)?,
1534    ///     date!(2020-01-15)
1535    /// );
1536    /// # Ok::<_, time::Error>(())
1537    /// ```
1538    #[inline]
1539    pub fn parse_with_defaults(
1540        input: &[u8],
1541        description: &(impl Parsable + ?Sized),
1542        defaults: Parsed,
1543    ) -> Result<Self, error::Parse> {
1544        description.parse_date(input, Some(defaults), PrivateMethod)
1545    }
1546}
1547
1548// This no longer needs special handling, as the format is fixed and doesn't require anything
1549// advanced. Trait impls can't be deprecated and the info is still useful for other types
1550// implementing `SmartDisplay`, so leave it as-is for now.
1551impl SmartDisplay for Date {
1552    type Metadata = ();
1553
1554    #[inline]
1555    fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> {
1556        use crate::ext::DigitCount as _;
1557
1558        let year_sign_width =
1559            if self.year() < 0 || (cfg!(feature = "large-dates") && self.year() >= 10_000) {
1560                1
1561            } else {
1562                0
1563            };
1564        let year_width = self.year().unsigned_abs().num_digits().clamp(4, 6);
1565        let formatted_width = year_sign_width + year_width + 6; // include two dashes and two digits each for month and day
1566
1567        Metadata::new(formatted_width as usize, self, ())
1568    }
1569
1570    #[inline]
1571    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1572        fmt::Display::fmt(self, f)
1573    }
1574}
1575
1576impl Date {
1577    /// The maximum number of bytes that the `fmt_into_buffer` method will write, which is also used
1578    /// for the `Display` implementation.
1579    pub(crate) const DISPLAY_BUFFER_SIZE: usize = 13;
1580
1581    /// Format the `Date` into the provided buffer, returning the number of bytes written.
1582    #[inline]
1583    pub(crate) fn fmt_into_buffer(
1584        self,
1585        buf: &mut [MaybeUninit<u8>; Self::DISPLAY_BUFFER_SIZE],
1586    ) -> usize {
1587        let mut idx = 0;
1588        let (year, month, day) = self.to_calendar_date();
1589
1590        // Compute the sign of the integer, if any. Doing this in a branchless manner gives a
1591        // significant performance improvement.
1592        let neg = year.is_negative() as u8;
1593        let pos = (cfg!(feature = "large-dates") && year - 10_000 >= 0) as u8;
1594        let sign = b'+' + 2 * neg; // b'-' if `neg` is true, b'+' otherwise
1595        // Always write the computed byte, even if it's later overwritten by the first digit of the
1596        // year.
1597        buf[idx] = MaybeUninit::new(sign);
1598        idx += (neg | pos) as usize;
1599
1600        // Safety: `year.unsigned_abs()` is less than 1,000,000.
1601        let [first_two, second_two, third_two] =
1602            four_to_six_digits(unsafe { ru32::new_unchecked(year.unsigned_abs()) });
1603        // Safety:
1604        // - both `first_two` and `buf` are valid for reads and writes of up to 2 bytes.
1605        // - `u8` is 1-aligned, so that is not a concern.
1606        // - `first_two` points to static memory, while `buf` is a local variable, so they do not
1607        //   overlap.
1608        unsafe {
1609            first_two
1610                .as_ptr()
1611                .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), first_two.len());
1612        }
1613        idx += first_two.len();
1614        // Safety: See above.
1615        unsafe {
1616            second_two
1617                .as_ptr()
1618                .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), 2);
1619        }
1620        idx += 2;
1621        // Safety: See above.
1622        unsafe {
1623            third_two
1624                .as_ptr()
1625                .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), 2);
1626        }
1627        idx += 2;
1628
1629        buf[idx] = MaybeUninit::new(b'-');
1630        idx += 1;
1631
1632        // Safety: See above for `copy_to_nonoverlapping`. `month` is in the range 1..=12.
1633        unsafe {
1634            two_digits_zero_padded(ru8::new_unchecked(u8::from(month)))
1635                .as_ptr()
1636                .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), 2);
1637        }
1638        idx += 2;
1639
1640        buf[idx] = MaybeUninit::new(b'-');
1641        idx += 1;
1642
1643        // Safety: See above for `copy_to_nonoverlapping`. `day` is in the range 1..=31.
1644        unsafe {
1645            two_digits_zero_padded(ru8::new_unchecked(day))
1646                .as_ptr()
1647                .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), 2);
1648        }
1649        idx += 2;
1650
1651        idx
1652    }
1653}
1654
1655impl fmt::Display for Date {
1656    #[inline]
1657    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1658        let mut buf = [MaybeUninit::uninit(); 13];
1659        let len = self.fmt_into_buffer(&mut buf);
1660        // Safety: All bytes up to `len` have been initialized with ASCII characters.
1661        let s = unsafe { str_from_raw_parts((&raw const buf).cast(), len) };
1662        f.pad(s)
1663    }
1664}
1665
1666impl fmt::Debug for Date {
1667    #[inline]
1668    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
1669        fmt::Display::fmt(self, f)
1670    }
1671}
1672
1673impl Add<SignedDuration> for Date {
1674    type Output = Self;
1675
1676    /// # Panics
1677    ///
1678    /// This may panic if an overflow occurs.
1679    #[inline]
1680    #[track_caller]
1681    fn add(self, duration: SignedDuration) -> Self::Output {
1682        self.checked_add(duration)
1683            .expect("overflow adding duration to date")
1684    }
1685}
1686
1687impl Add<StdDuration> for Date {
1688    type Output = Self;
1689
1690    /// # Panics
1691    ///
1692    /// This may panic if an overflow occurs.
1693    #[inline]
1694    #[track_caller]
1695    fn add(self, duration: StdDuration) -> Self::Output {
1696        self.checked_add_std(duration)
1697            .expect("overflow adding duration to date")
1698    }
1699}
1700
1701impl AddAssign<SignedDuration> for Date {
1702    /// # Panics
1703    ///
1704    /// This may panic if an overflow occurs.
1705    #[inline]
1706    #[track_caller]
1707    fn add_assign(&mut self, rhs: SignedDuration) {
1708        *self = *self + rhs;
1709    }
1710}
1711
1712impl AddAssign<StdDuration> for Date {
1713    /// # Panics
1714    ///
1715    /// This may panic if an overflow occurs.
1716    #[inline]
1717    #[track_caller]
1718    fn add_assign(&mut self, rhs: StdDuration) {
1719        *self = *self + rhs;
1720    }
1721}
1722
1723impl Sub<SignedDuration> for Date {
1724    type Output = Self;
1725
1726    /// # Panics
1727    ///
1728    /// This may panic if an overflow occurs.
1729    #[inline]
1730    #[track_caller]
1731    fn sub(self, duration: SignedDuration) -> Self::Output {
1732        self.checked_sub(duration)
1733            .expect("overflow subtracting duration from date")
1734    }
1735}
1736
1737impl Sub<StdDuration> for Date {
1738    type Output = Self;
1739
1740    /// # Panics
1741    ///
1742    /// This may panic if an overflow occurs.
1743    #[inline]
1744    #[track_caller]
1745    fn sub(self, duration: StdDuration) -> Self::Output {
1746        self.checked_sub_std(duration)
1747            .expect("overflow subtracting duration from date")
1748    }
1749}
1750
1751impl SubAssign<SignedDuration> for Date {
1752    /// # Panics
1753    ///
1754    /// This may panic if an overflow occurs.
1755    #[inline]
1756    #[track_caller]
1757    fn sub_assign(&mut self, rhs: SignedDuration) {
1758        *self = *self - rhs;
1759    }
1760}
1761
1762impl SubAssign<StdDuration> for Date {
1763    /// # Panics
1764    ///
1765    /// This may panic if an overflow occurs.
1766    #[inline]
1767    #[track_caller]
1768    fn sub_assign(&mut self, rhs: StdDuration) {
1769        *self = *self - rhs;
1770    }
1771}
1772
1773impl Sub for Date {
1774    type Output = SignedDuration;
1775
1776    #[inline]
1777    fn sub(self, other: Self) -> Self::Output {
1778        SignedDuration::days((self.to_julian_day() - other.to_julian_day()).widen())
1779    }
1780}