Coverage Report

Created: 2025-12-05 06:46

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