Skip to main content

jiff/civil/
datetime.rs

1use core::time::Duration as UnsignedDuration;
2
3use jcore::{bounds::Sign, civil::DateTime as JDateTime, constants as c};
4
5use crate::{
6    civil::{
7        datetime, Date, DateWith, Era, ISOWeekDate, Time, TimeWith, Weekday,
8    },
9    duration::{Duration, SDuration},
10    error::{civil::Error as E, Error, ErrorContext},
11    fmt::{
12        self,
13        temporal::{self, DEFAULT_DATETIME_PARSER},
14    },
15    tz::TimeZone,
16    util::round::Increment,
17    zoned::Zoned,
18    RoundMode, SignedDuration, Span, SpanRound, Unit,
19};
20
21/// A representation of a civil datetime in the Gregorian calendar.
22///
23/// A `DateTime` value corresponds to a pair of a [`Date`] and a [`Time`].
24/// That is, a datetime contains a year, month, day, hour, minute, second and
25/// the fractional number of nanoseconds.
26///
27/// A `DateTime` value is guaranteed to contain a valid date and time. For
28/// example, neither `2023-02-29T00:00:00` nor `2015-06-30T23:59:60` are
29/// valid `DateTime` values.
30///
31/// # Civil datetimes
32///
33/// A `DateTime` value behaves without regard to daylight saving time or time
34/// zones in general. When doing arithmetic on datetimes with spans defined in
35/// units of time (such as with [`DateTime::checked_add`]), days are considered
36/// to always be precisely `86,400` seconds long.
37///
38/// # Parsing and printing
39///
40/// The `DateTime` type provides convenient trait implementations of
41/// [`std::str::FromStr`] and [`std::fmt::Display`]:
42///
43/// ```
44/// use jiff::civil::DateTime;
45///
46/// let dt: DateTime = "2024-06-19 15:22:45".parse()?;
47/// assert_eq!(dt.to_string(), "2024-06-19T15:22:45");
48///
49/// # Ok::<(), Box<dyn std::error::Error>>(())
50/// ```
51///
52/// A civil `DateTime` can also be parsed from something that _contains_ a
53/// datetime, but with perhaps other data (such as an offset or time zone):
54///
55/// ```
56/// use jiff::civil::DateTime;
57///
58/// let dt: DateTime = "2024-06-19T15:22:45-04[America/New_York]".parse()?;
59/// assert_eq!(dt.to_string(), "2024-06-19T15:22:45");
60///
61/// # Ok::<(), Box<dyn std::error::Error>>(())
62/// ```
63///
64/// For more information on the specific format supported, see the
65/// [`fmt::temporal`](crate::fmt::temporal) module documentation.
66///
67/// # Default value
68///
69/// For convenience, this type implements the `Default` trait. Its default
70/// value corresponds to `0000-01-01T00:00:00.000000000`. That is, it is
71/// the datetime corresponding to `DateTime::from_parts(Date::default(),
72/// Time::default())`. One can also access this value via the `DateTime::ZERO`
73/// constant.
74///
75/// # Leap seconds
76///
77/// Jiff does not support leap seconds. Jiff behaves as if they don't exist.
78/// The only exception is that if one parses a datetime with a second component
79/// of `60`, then it is automatically constrained to `59`:
80///
81/// ```
82/// use jiff::civil::{DateTime, date};
83///
84/// let dt: DateTime = "2016-12-31 23:59:60".parse()?;
85/// assert_eq!(dt, date(2016, 12, 31).at(23, 59, 59, 0));
86///
87/// # Ok::<(), Box<dyn std::error::Error>>(())
88/// ```
89///
90/// # Comparisons
91///
92/// The `DateTime` type provides both `Eq` and `Ord` trait implementations to
93/// facilitate easy comparisons. When a datetime `dt1` occurs before a datetime
94/// `dt2`, then `dt1 < dt2`. For example:
95///
96/// ```
97/// use jiff::civil::date;
98///
99/// let dt1 = date(2024, 3, 11).at(1, 25, 15, 0);
100/// let dt2 = date(2025, 1, 31).at(0, 30, 0, 0);
101/// assert!(dt1 < dt2);
102/// ```
103///
104/// # Arithmetic
105///
106/// This type provides routines for adding and subtracting spans of time, as
107/// well as computing the span of time between two `DateTime` values.
108///
109/// For adding or subtracting spans of time, one can use any of the following
110/// routines:
111///
112/// * [`DateTime::checked_add`] or [`DateTime::checked_sub`] for checked
113/// arithmetic.
114/// * [`DateTime::saturating_add`] or [`DateTime::saturating_sub`] for
115/// saturating arithmetic.
116///
117/// Additionally, checked arithmetic is available via the `Add` and `Sub`
118/// trait implementations. When the result overflows, a panic occurs.
119///
120/// ```
121/// use jiff::{civil::date, ToSpan};
122///
123/// let start = date(2024, 2, 25).at(15, 45, 0, 0);
124/// let one_week_later = start + 1.weeks();
125/// assert_eq!(one_week_later, date(2024, 3, 3).at(15, 45, 0, 0));
126/// ```
127///
128/// One can compute the span of time between two datetimes using either
129/// [`DateTime::until`] or [`DateTime::since`]. It's also possible to subtract
130/// two `DateTime` values directly via a `Sub` trait implementation:
131///
132/// ```
133/// use jiff::{civil::date, ToSpan};
134///
135/// let datetime1 = date(2024, 5, 3).at(23, 30, 0, 0);
136/// let datetime2 = date(2024, 2, 25).at(7, 0, 0, 0);
137/// assert_eq!(
138///     datetime1 - datetime2,
139///     68.days().hours(16).minutes(30).fieldwise(),
140/// );
141/// ```
142///
143/// The `until` and `since` APIs are polymorphic and allow re-balancing and
144/// rounding the span returned. For example, the default largest unit is days
145/// (as exemplified above), but we can ask for bigger units:
146///
147/// ```
148/// use jiff::{civil::date, ToSpan, Unit};
149///
150/// let datetime1 = date(2024, 5, 3).at(23, 30, 0, 0);
151/// let datetime2 = date(2024, 2, 25).at(7, 0, 0, 0);
152/// assert_eq!(
153///     datetime1.since((Unit::Year, datetime2))?,
154///     2.months().days(7).hours(16).minutes(30).fieldwise(),
155/// );
156///
157/// # Ok::<(), Box<dyn std::error::Error>>(())
158/// ```
159///
160/// Or even round the span returned:
161///
162/// ```
163/// use jiff::{civil::{DateTimeDifference, date}, RoundMode, ToSpan, Unit};
164///
165/// let datetime1 = date(2024, 5, 3).at(23, 30, 0, 0);
166/// let datetime2 = date(2024, 2, 25).at(7, 0, 0, 0);
167/// assert_eq!(
168///     datetime1.since(
169///         DateTimeDifference::new(datetime2)
170///             .smallest(Unit::Day)
171///             .largest(Unit::Year),
172///     )?,
173///     2.months().days(7).fieldwise(),
174/// );
175/// // `DateTimeDifference` uses truncation as a rounding mode by default,
176/// // but you can set the rounding mode to break ties away from zero:
177/// assert_eq!(
178///     datetime1.since(
179///         DateTimeDifference::new(datetime2)
180///             .smallest(Unit::Day)
181///             .largest(Unit::Year)
182///             .mode(RoundMode::HalfExpand),
183///     )?,
184///     // Rounds up to 8 days.
185///     2.months().days(8).fieldwise(),
186/// );
187///
188/// # Ok::<(), Box<dyn std::error::Error>>(())
189/// ```
190///
191/// # Rounding
192///
193/// A `DateTime` can be rounded based on a [`DateTimeRound`] configuration of
194/// smallest units, rounding increment and rounding mode. Here's an example
195/// showing how to round to the nearest third hour:
196///
197/// ```
198/// use jiff::{civil::{DateTimeRound, date}, Unit};
199///
200/// let dt = date(2024, 6, 19).at(16, 27, 29, 999_999_999);
201/// assert_eq!(
202///     dt.round(DateTimeRound::new().smallest(Unit::Hour).increment(3))?,
203///     date(2024, 6, 19).at(15, 0, 0, 0),
204/// );
205/// // Or alternatively, make use of the `From<(Unit, i64)> for DateTimeRound`
206/// // trait implementation:
207/// assert_eq!(
208///     dt.round((Unit::Hour, 3))?,
209///     date(2024, 6, 19).at(15, 0, 0, 0),
210/// );
211///
212/// # Ok::<(), Box<dyn std::error::Error>>(())
213/// ```
214///
215/// See [`DateTime::round`] for more details.
216#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
217#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
218pub struct DateTime {
219    date: Date,
220    time: Time,
221}
222
223impl DateTime {
224    /// The minimum representable Gregorian datetime.
225    ///
226    /// The minimum is chosen such that any [`Timestamp`](crate::Timestamp)
227    /// combined with any valid time zone offset can be infallibly converted to
228    /// this type.
229    pub const MIN: DateTime = datetime(-9999, 1, 1, 0, 0, 0, 0);
230
231    /// The maximum representable Gregorian datetime.
232    ///
233    /// The maximum is chosen such that any [`Timestamp`](crate::Timestamp)
234    /// combined with any valid time zone offset can be infallibly converted to
235    /// this type.
236    pub const MAX: DateTime = datetime(9999, 12, 31, 23, 59, 59, 999_999_999);
237
238    /// The first day of the zeroth year.
239    ///
240    /// This is guaranteed to be equivalent to `DateTime::default()`.
241    ///
242    /// # Example
243    ///
244    /// ```
245    /// use jiff::civil::DateTime;
246    ///
247    /// assert_eq!(DateTime::ZERO, DateTime::default());
248    /// ```
249    pub const ZERO: DateTime = DateTime::from_parts(Date::ZERO, Time::MIN);
250
251    /// Creates a new `DateTime` value from its component year, month, day,
252    /// hour, minute, second and fractional subsecond (up to nanosecond
253    /// precision) values.
254    ///
255    /// To create a new datetime from another with a particular component, use
256    /// the methods on [`DateTimeWith`] via [`DateTime::with`].
257    ///
258    /// # Errors
259    ///
260    /// This returns an error when the given components do not correspond to a
261    /// valid datetime. Namely, all of the following must be true:
262    ///
263    /// * The year must be in the range `-9999..=9999`.
264    /// * The month must be in the range `1..=12`.
265    /// * The day must be at least `1` and must be at most the number of days
266    /// in the corresponding month. So for example, `2024-02-29` is valid but
267    /// `2023-02-29` is not.
268    /// * `0 <= hour <= 23`
269    /// * `0 <= minute <= 59`
270    /// * `0 <= second <= 59`
271    /// * `0 <= subsec_nanosecond <= 999,999,999`
272    ///
273    /// # Example
274    ///
275    /// This shows an example of a valid datetime:
276    ///
277    /// ```
278    /// use jiff::civil::DateTime;
279    ///
280    /// let d = DateTime::new(2024, 2, 29, 21, 30, 5, 123_456_789).unwrap();
281    /// assert_eq!(d.year(), 2024);
282    /// assert_eq!(d.month(), 2);
283    /// assert_eq!(d.day(), 29);
284    /// assert_eq!(d.hour(), 21);
285    /// assert_eq!(d.minute(), 30);
286    /// assert_eq!(d.second(), 5);
287    /// assert_eq!(d.millisecond(), 123);
288    /// assert_eq!(d.microsecond(), 456);
289    /// assert_eq!(d.nanosecond(), 789);
290    /// ```
291    ///
292    /// This shows some examples of invalid datetimes:
293    ///
294    /// ```
295    /// use jiff::civil::DateTime;
296    ///
297    /// assert!(DateTime::new(2023, 2, 29, 21, 30, 5, 0).is_err());
298    /// assert!(DateTime::new(2015, 6, 30, 23, 59, 60, 0).is_err());
299    /// assert!(DateTime::new(2024, 6, 20, 19, 58, 0, 1_000_000_000).is_err());
300    /// ```
301    #[inline]
302    pub fn new(
303        year: i16,
304        month: i8,
305        day: i8,
306        hour: i8,
307        minute: i8,
308        second: i8,
309        subsec_nanosecond: i32,
310    ) -> Result<DateTime, Error> {
311        let date = Date::new(year, month, day)?;
312        let time = Time::new(hour, minute, second, subsec_nanosecond)?;
313        Ok(DateTime { date, time })
314    }
315
316    /// Creates a new `DateTime` value in a `const` context.
317    ///
318    /// Note that an alternative syntax that is terser and perhaps easier to
319    /// read for the same operation is to combine
320    /// [`civil::date`](crate::civil::date()) with [`Date::at`].
321    ///
322    /// # Panics
323    ///
324    /// This routine panics when [`DateTime::new`] would return an error. That
325    /// is, when the given components do not correspond to a valid datetime.
326    /// Namely, all of the following must be true:
327    ///
328    /// * The year must be in the range `-9999..=9999`.
329    /// * The month must be in the range `1..=12`.
330    /// * The day must be at least `1` and must be at most the number of days
331    /// in the corresponding month. So for example, `2024-02-29` is valid but
332    /// `2023-02-29` is not.
333    /// * `0 <= hour <= 23`
334    /// * `0 <= minute <= 59`
335    /// * `0 <= second <= 59`
336    /// * `0 <= subsec_nanosecond <= 999,999,999`
337    ///
338    /// Similarly, when used in a const context, invalid parameters will
339    /// prevent your Rust program from compiling.
340    ///
341    /// # Example
342    ///
343    /// ```
344    /// use jiff::civil::DateTime;
345    ///
346    /// let dt = DateTime::constant(2024, 2, 29, 21, 30, 5, 123_456_789);
347    /// assert_eq!(dt.year(), 2024);
348    /// assert_eq!(dt.month(), 2);
349    /// assert_eq!(dt.day(), 29);
350    /// assert_eq!(dt.hour(), 21);
351    /// assert_eq!(dt.minute(), 30);
352    /// assert_eq!(dt.second(), 5);
353    /// assert_eq!(dt.millisecond(), 123);
354    /// assert_eq!(dt.microsecond(), 456);
355    /// assert_eq!(dt.nanosecond(), 789);
356    /// ```
357    ///
358    /// Or alternatively:
359    ///
360    /// ```
361    /// use jiff::civil::date;
362    ///
363    /// let dt = date(2024, 2, 29).at(21, 30, 5, 123_456_789);
364    /// assert_eq!(dt.year(), 2024);
365    /// assert_eq!(dt.month(), 2);
366    /// assert_eq!(dt.day(), 29);
367    /// assert_eq!(dt.hour(), 21);
368    /// assert_eq!(dt.minute(), 30);
369    /// assert_eq!(dt.second(), 5);
370    /// assert_eq!(dt.millisecond(), 123);
371    /// assert_eq!(dt.microsecond(), 456);
372    /// assert_eq!(dt.nanosecond(), 789);
373    /// ```
374    #[inline]
375    pub const fn constant(
376        year: i16,
377        month: i8,
378        day: i8,
379        hour: i8,
380        minute: i8,
381        second: i8,
382        subsec_nanosecond: i32,
383    ) -> DateTime {
384        let date = Date::constant(year, month, day);
385        let time = Time::constant(hour, minute, second, subsec_nanosecond);
386        DateTime { date, time }
387    }
388
389    /// Creates a `DateTime` from its constituent parts.
390    ///
391    /// Any combination of a valid `Date` and a valid `Time` results in a valid
392    /// `DateTime`.
393    ///
394    /// # Example
395    ///
396    /// This example shows how to build a datetime from its parts:
397    ///
398    /// ```
399    /// use jiff::civil::{DateTime, date, time};
400    ///
401    /// let dt = DateTime::from_parts(date(2024, 6, 6), time(6, 0, 0, 0));
402    /// assert_eq!(dt, date(2024, 6, 6).at(6, 0, 0, 0));
403    /// ```
404    #[inline]
405    pub const fn from_parts(date: Date, time: Time) -> DateTime {
406        DateTime { date, time }
407    }
408
409    /// Create a builder for constructing a new `DateTime` from the fields of
410    /// this datetime.
411    ///
412    /// See the methods on [`DateTimeWith`] for the different ways one can set
413    /// the fields of a new `DateTime`.
414    ///
415    /// # Example
416    ///
417    /// The builder ensures one can chain together the individual components of
418    /// a datetime without it failing at an intermediate step. For example, if
419    /// you had a date of `2024-10-31T00:00:00` and wanted to change both the
420    /// day and the month, and each setting was validated independent of the
421    /// other, you would need to be careful to set the day first and then the
422    /// month. In some cases, you would need to set the month first and then
423    /// the day!
424    ///
425    /// But with the builder, you can set values in any order:
426    ///
427    /// ```
428    /// use jiff::civil::date;
429    ///
430    /// let dt1 = date(2024, 10, 31).at(0, 0, 0, 0);
431    /// let dt2 = dt1.with().month(11).day(30).build()?;
432    /// assert_eq!(dt2, date(2024, 11, 30).at(0, 0, 0, 0));
433    ///
434    /// let dt1 = date(2024, 4, 30).at(0, 0, 0, 0);
435    /// let dt2 = dt1.with().day(31).month(7).build()?;
436    /// assert_eq!(dt2, date(2024, 7, 31).at(0, 0, 0, 0));
437    ///
438    /// # Ok::<(), Box<dyn std::error::Error>>(())
439    /// ```
440    #[inline]
441    pub fn with(self) -> DateTimeWith {
442        DateTimeWith::new(self)
443    }
444
445    /// Returns the year for this datetime.
446    ///
447    /// The value returned is guaranteed to be in the range `-9999..=9999`.
448    ///
449    /// # Example
450    ///
451    /// ```
452    /// use jiff::civil::date;
453    ///
454    /// let dt1 = date(2024, 3, 9).at(7, 30, 0, 0);
455    /// assert_eq!(dt1.year(), 2024);
456    ///
457    /// let dt2 = date(-2024, 3, 9).at(7, 30, 0, 0);
458    /// assert_eq!(dt2.year(), -2024);
459    ///
460    /// let dt3 = date(0, 3, 9).at(7, 30, 0, 0);
461    /// assert_eq!(dt3.year(), 0);
462    /// ```
463    #[inline]
464    pub fn year(self) -> i16 {
465        self.date().year()
466    }
467
468    /// Returns the year and its era.
469    ///
470    /// This crate specifically allows years to be negative or `0`, where as
471    /// years written for the Gregorian calendar are always positive and
472    /// greater than `0`. In the Gregorian calendar, the era labels `BCE` and
473    /// `CE` are used to disambiguate between years less than or equal to `0`
474    /// and years greater than `0`, respectively.
475    ///
476    /// The crate is designed this way so that years in the latest era (that
477    /// is, `CE`) are aligned with years in this crate.
478    ///
479    /// The year returned is guaranteed to be in the range `1..=10000`.
480    ///
481    /// # Example
482    ///
483    /// ```
484    /// use jiff::civil::{Era, date};
485    ///
486    /// let dt = date(2024, 10, 3).at(7, 30, 0, 0);
487    /// assert_eq!(dt.era_year(), (2024, Era::CE));
488    ///
489    /// let dt = date(1, 10, 3).at(7, 30, 0, 0);
490    /// assert_eq!(dt.era_year(), (1, Era::CE));
491    ///
492    /// let dt = date(0, 10, 3).at(7, 30, 0, 0);
493    /// assert_eq!(dt.era_year(), (1, Era::BCE));
494    ///
495    /// let dt = date(-1, 10, 3).at(7, 30, 0, 0);
496    /// assert_eq!(dt.era_year(), (2, Era::BCE));
497    ///
498    /// let dt = date(-10, 10, 3).at(7, 30, 0, 0);
499    /// assert_eq!(dt.era_year(), (11, Era::BCE));
500    ///
501    /// let dt = date(-9_999, 10, 3).at(7, 30, 0, 0);
502    /// assert_eq!(dt.era_year(), (10_000, Era::BCE));
503    /// ```
504    #[inline]
505    pub fn era_year(self) -> (i16, Era) {
506        self.date().era_year()
507    }
508
509    /// Returns the month for this datetime.
510    ///
511    /// The value returned is guaranteed to be in the range `1..=12`.
512    ///
513    /// # Example
514    ///
515    /// ```
516    /// use jiff::civil::date;
517    ///
518    /// let dt1 = date(2024, 3, 9).at(7, 30, 0, 0);
519    /// assert_eq!(dt1.month(), 3);
520    /// ```
521    #[inline]
522    pub fn month(self) -> i8 {
523        self.date().month()
524    }
525
526    /// Returns the day for this datetime.
527    ///
528    /// The value returned is guaranteed to be in the range `1..=31`.
529    ///
530    /// # Example
531    ///
532    /// ```
533    /// use jiff::civil::date;
534    ///
535    /// let dt1 = date(2024, 2, 29).at(7, 30, 0, 0);
536    /// assert_eq!(dt1.day(), 29);
537    /// ```
538    #[inline]
539    pub fn day(self) -> i8 {
540        self.date().day()
541    }
542
543    /// Returns the "hour" component of this datetime.
544    ///
545    /// The value returned is guaranteed to be in the range `0..=23`.
546    ///
547    /// # Example
548    ///
549    /// ```
550    /// use jiff::civil::date;
551    ///
552    /// let dt = date(2000, 1, 2).at(3, 4, 5, 123_456_789);
553    /// assert_eq!(dt.hour(), 3);
554    /// ```
555    #[inline]
556    pub fn hour(self) -> i8 {
557        self.time().hour()
558    }
559
560    /// Returns the "minute" component of this datetime.
561    ///
562    /// The value returned is guaranteed to be in the range `0..=59`.
563    ///
564    /// # Example
565    ///
566    /// ```
567    /// use jiff::civil::date;
568    ///
569    /// let dt = date(2000, 1, 2).at(3, 4, 5, 123_456_789);
570    /// assert_eq!(dt.minute(), 4);
571    /// ```
572    #[inline]
573    pub fn minute(self) -> i8 {
574        self.time().minute()
575    }
576
577    /// Returns the "second" component of this datetime.
578    ///
579    /// The value returned is guaranteed to be in the range `0..=59`.
580    ///
581    /// # Example
582    ///
583    /// ```
584    /// use jiff::civil::date;
585    ///
586    /// let dt = date(2000, 1, 2).at(3, 4, 5, 123_456_789);
587    /// assert_eq!(dt.second(), 5);
588    /// ```
589    #[inline]
590    pub fn second(self) -> i8 {
591        self.time().second()
592    }
593
594    /// Returns the "millisecond" component of this datetime.
595    ///
596    /// The value returned is guaranteed to be in the range `0..=999`.
597    ///
598    /// # Example
599    ///
600    /// ```
601    /// use jiff::civil::date;
602    ///
603    /// let dt = date(2000, 1, 2).at(3, 4, 5, 123_456_789);
604    /// assert_eq!(dt.millisecond(), 123);
605    /// ```
606    #[inline]
607    pub fn millisecond(self) -> i16 {
608        self.time().millisecond()
609    }
610
611    /// Returns the "microsecond" component of this datetime.
612    ///
613    /// The value returned is guaranteed to be in the range `0..=999`.
614    ///
615    /// # Example
616    ///
617    /// ```
618    /// use jiff::civil::date;
619    ///
620    /// let dt = date(2000, 1, 2).at(3, 4, 5, 123_456_789);
621    /// assert_eq!(dt.microsecond(), 456);
622    /// ```
623    #[inline]
624    pub fn microsecond(self) -> i16 {
625        self.time().microsecond()
626    }
627
628    /// Returns the "nanosecond" component of this datetime.
629    ///
630    /// The value returned is guaranteed to be in the range `0..=999`.
631    ///
632    /// # Example
633    ///
634    /// ```
635    /// use jiff::civil::date;
636    ///
637    /// let dt = date(2000, 1, 2).at(3, 4, 5, 123_456_789);
638    /// assert_eq!(dt.nanosecond(), 789);
639    /// ```
640    #[inline]
641    pub fn nanosecond(self) -> i16 {
642        self.time().nanosecond()
643    }
644
645    /// Returns the fractional nanosecond for this `DateTime` value.
646    ///
647    /// If you want to set this value on `DateTime`, then use
648    /// [`DateTimeWith::subsec_nanosecond`] via [`DateTime::with`].
649    ///
650    /// The value returned is guaranteed to be in the range `0..=999_999_999`.
651    ///
652    /// # Example
653    ///
654    /// This shows the relationship between constructing a `DateTime` value
655    /// with routines like `with().millisecond()` and accessing the entire
656    /// fractional part as a nanosecond:
657    ///
658    /// ```
659    /// use jiff::civil::date;
660    ///
661    /// let dt1 = date(2000, 1, 2).at(3, 4, 5, 123_456_789);
662    /// assert_eq!(dt1.subsec_nanosecond(), 123_456_789);
663    /// let dt2 = dt1.with().millisecond(333).build()?;
664    /// assert_eq!(dt2.subsec_nanosecond(), 333_456_789);
665    ///
666    /// # Ok::<(), Box<dyn std::error::Error>>(())
667    /// ```
668    ///
669    /// # Example: nanoseconds from a timestamp
670    ///
671    /// This shows how the fractional nanosecond part of a `DateTime` value
672    /// manifests from a specific timestamp.
673    ///
674    /// ```
675    /// use jiff::Timestamp;
676    ///
677    /// // 1,234 nanoseconds after the Unix epoch.
678    /// let zdt = Timestamp::new(0, 1_234)?.in_tz("UTC")?;
679    /// let dt = zdt.datetime();
680    /// assert_eq!(dt.subsec_nanosecond(), 1_234);
681    ///
682    /// // 1,234 nanoseconds before the Unix epoch.
683    /// let zdt = Timestamp::new(0, -1_234)?.in_tz("UTC")?;
684    /// let dt = zdt.datetime();
685    /// // The nanosecond is equal to `1_000_000_000 - 1_234`.
686    /// assert_eq!(dt.subsec_nanosecond(), 999998766);
687    /// // Looking at the other components of the time value might help.
688    /// assert_eq!(dt.hour(), 23);
689    /// assert_eq!(dt.minute(), 59);
690    /// assert_eq!(dt.second(), 59);
691    ///
692    /// # Ok::<(), Box<dyn std::error::Error>>(())
693    /// ```
694    #[inline]
695    pub fn subsec_nanosecond(self) -> i32 {
696        self.time().subsec_nanosecond()
697    }
698
699    /// Returns the weekday corresponding to this datetime.
700    ///
701    /// # Example
702    ///
703    /// ```
704    /// use jiff::civil::{Weekday, date};
705    ///
706    /// // The Unix epoch was on a Thursday.
707    /// let dt = date(1970, 1, 1).at(7, 30, 0, 0);
708    /// assert_eq!(dt.weekday(), Weekday::Thursday);
709    /// // One can also get the weekday as an offset in a variety of schemes.
710    /// assert_eq!(dt.weekday().to_monday_zero_offset(), 3);
711    /// assert_eq!(dt.weekday().to_monday_one_offset(), 4);
712    /// assert_eq!(dt.weekday().to_sunday_zero_offset(), 4);
713    /// assert_eq!(dt.weekday().to_sunday_one_offset(), 5);
714    /// ```
715    #[inline]
716    pub fn weekday(self) -> Weekday {
717        self.date().weekday()
718    }
719
720    /// Returns the ordinal day of the year that this datetime resides in.
721    ///
722    /// For leap years, this always returns a value in the range `1..=366`.
723    /// Otherwise, the value is in the range `1..=365`.
724    ///
725    /// # Example
726    ///
727    /// ```
728    /// use jiff::civil::date;
729    ///
730    /// let dt = date(2006, 8, 24).at(7, 30, 0, 0);
731    /// assert_eq!(dt.day_of_year(), 236);
732    ///
733    /// let dt = date(2023, 12, 31).at(7, 30, 0, 0);
734    /// assert_eq!(dt.day_of_year(), 365);
735    ///
736    /// let dt = date(2024, 12, 31).at(7, 30, 0, 0);
737    /// assert_eq!(dt.day_of_year(), 366);
738    /// ```
739    #[inline]
740    pub fn day_of_year(self) -> i16 {
741        self.date().day_of_year()
742    }
743
744    /// Returns the ordinal day of the year that this datetime resides in, but
745    /// ignores leap years.
746    ///
747    /// That is, the range of possible values returned by this routine is
748    /// `1..=365`, even if this date resides in a leap year. If this date is
749    /// February 29, then this routine returns `None`.
750    ///
751    /// The value `365` always corresponds to the last day in the year,
752    /// December 31, even for leap years.
753    ///
754    /// # Example
755    ///
756    /// ```
757    /// use jiff::civil::date;
758    ///
759    /// let dt = date(2006, 8, 24).at(7, 30, 0, 0);
760    /// assert_eq!(dt.day_of_year_no_leap(), Some(236));
761    ///
762    /// let dt = date(2023, 12, 31).at(7, 30, 0, 0);
763    /// assert_eq!(dt.day_of_year_no_leap(), Some(365));
764    ///
765    /// let dt = date(2024, 12, 31).at(7, 30, 0, 0);
766    /// assert_eq!(dt.day_of_year_no_leap(), Some(365));
767    ///
768    /// let dt = date(2024, 2, 29).at(7, 30, 0, 0);
769    /// assert_eq!(dt.day_of_year_no_leap(), None);
770    /// ```
771    #[inline]
772    pub fn day_of_year_no_leap(self) -> Option<i16> {
773        self.date().day_of_year_no_leap()
774    }
775
776    /// Returns the beginning of the day that this datetime resides in.
777    ///
778    /// That is, the datetime returned always keeps the same date, but its
779    /// time is always `00:00:00` (midnight).
780    ///
781    /// # Example
782    ///
783    /// ```
784    /// use jiff::civil::date;
785    ///
786    /// let dt = date(2024, 7, 3).at(7, 30, 10, 123_456_789);
787    /// assert_eq!(dt.start_of_day(), date(2024, 7, 3).at(0, 0, 0, 0));
788    /// ```
789    #[inline]
790    pub fn start_of_day(&self) -> DateTime {
791        DateTime::from_parts(self.date(), Time::MIN)
792    }
793
794    /// Returns the end of the day that this datetime resides in.
795    ///
796    /// That is, the datetime returned always keeps the same date, but its
797    /// time is always `23:59:59.999999999`.
798    ///
799    /// # Example
800    ///
801    /// ```
802    /// use jiff::civil::date;
803    ///
804    /// let dt = date(2024, 7, 3).at(7, 30, 10, 123_456_789);
805    /// assert_eq!(
806    ///     dt.end_of_day(),
807    ///     date(2024, 7, 3).at(23, 59, 59, 999_999_999),
808    /// );
809    /// ```
810    #[inline]
811    pub fn end_of_day(&self) -> DateTime {
812        DateTime::from_parts(self.date(), Time::MAX)
813    }
814
815    /// Returns the first date of the month that this datetime resides in.
816    ///
817    /// The time in the datetime returned remains unchanged.
818    ///
819    /// # Example
820    ///
821    /// ```
822    /// use jiff::civil::date;
823    ///
824    /// let dt = date(2024, 2, 29).at(7, 30, 0, 0);
825    /// assert_eq!(dt.first_of_month(), date(2024, 2, 1).at(7, 30, 0, 0));
826    /// ```
827    #[inline]
828    pub fn first_of_month(self) -> DateTime {
829        DateTime::from_parts(self.date().first_of_month(), self.time())
830    }
831
832    /// Returns the last date of the month that this datetime resides in.
833    ///
834    /// The time in the datetime returned remains unchanged.
835    ///
836    /// # Example
837    ///
838    /// ```
839    /// use jiff::civil::date;
840    ///
841    /// let dt = date(2024, 2, 5).at(7, 30, 0, 0);
842    /// assert_eq!(dt.last_of_month(), date(2024, 2, 29).at(7, 30, 0, 0));
843    /// ```
844    #[inline]
845    pub fn last_of_month(self) -> DateTime {
846        DateTime::from_parts(self.date().last_of_month(), self.time())
847    }
848
849    /// Returns the total number of days in the the month in which this
850    /// datetime resides.
851    ///
852    /// This is guaranteed to always return one of the following values,
853    /// depending on the year and the month: 28, 29, 30 or 31.
854    ///
855    /// # Example
856    ///
857    /// ```
858    /// use jiff::civil::date;
859    ///
860    /// let dt = date(2024, 2, 10).at(7, 30, 0, 0);
861    /// assert_eq!(dt.days_in_month(), 29);
862    ///
863    /// let dt = date(2023, 2, 10).at(7, 30, 0, 0);
864    /// assert_eq!(dt.days_in_month(), 28);
865    ///
866    /// let dt = date(2024, 8, 15).at(7, 30, 0, 0);
867    /// assert_eq!(dt.days_in_month(), 31);
868    /// ```
869    #[inline]
870    pub fn days_in_month(self) -> i8 {
871        self.date().days_in_month()
872    }
873
874    /// Returns the first date of the year that this datetime resides in.
875    ///
876    /// The time in the datetime returned remains unchanged.
877    ///
878    /// # Example
879    ///
880    /// ```
881    /// use jiff::civil::date;
882    ///
883    /// let dt = date(2024, 2, 29).at(7, 30, 0, 0);
884    /// assert_eq!(dt.first_of_year(), date(2024, 1, 1).at(7, 30, 0, 0));
885    /// ```
886    #[inline]
887    pub fn first_of_year(self) -> DateTime {
888        DateTime::from_parts(self.date().first_of_year(), self.time())
889    }
890
891    /// Returns the last date of the year that this datetime resides in.
892    ///
893    /// The time in the datetime returned remains unchanged.
894    ///
895    /// # Example
896    ///
897    /// ```
898    /// use jiff::civil::date;
899    ///
900    /// let dt = date(2024, 2, 5).at(7, 30, 0, 0);
901    /// assert_eq!(dt.last_of_year(), date(2024, 12, 31).at(7, 30, 0, 0));
902    /// ```
903    #[inline]
904    pub fn last_of_year(self) -> DateTime {
905        DateTime::from_parts(self.date().last_of_year(), self.time())
906    }
907
908    /// Returns the total number of days in the the year in which this datetime
909    /// resides.
910    ///
911    /// This is guaranteed to always return either `365` or `366`.
912    ///
913    /// # Example
914    ///
915    /// ```
916    /// use jiff::civil::date;
917    ///
918    /// let dt = date(2024, 7, 10).at(7, 30, 0, 0);
919    /// assert_eq!(dt.days_in_year(), 366);
920    ///
921    /// let dt = date(2023, 7, 10).at(7, 30, 0, 0);
922    /// assert_eq!(dt.days_in_year(), 365);
923    /// ```
924    #[inline]
925    pub fn days_in_year(self) -> i16 {
926        self.date().days_in_year()
927    }
928
929    /// Returns true if and only if the year in which this datetime resides is
930    /// a leap year.
931    ///
932    /// # Example
933    ///
934    /// ```
935    /// use jiff::civil::date;
936    ///
937    /// assert!(date(2024, 1, 1).at(7, 30, 0, 0).in_leap_year());
938    /// assert!(!date(2023, 12, 31).at(7, 30, 0, 0).in_leap_year());
939    /// ```
940    #[inline]
941    pub fn in_leap_year(self) -> bool {
942        self.date().in_leap_year()
943    }
944
945    /// Returns the datetime with a date immediately following this one.
946    ///
947    /// The time in the datetime returned remains unchanged.
948    ///
949    /// # Errors
950    ///
951    /// This returns an error when this datetime's date is the maximum value.
952    ///
953    /// # Example
954    ///
955    /// ```
956    /// use jiff::civil::{DateTime, date};
957    ///
958    /// let dt = date(2024, 2, 28).at(7, 30, 0, 0);
959    /// assert_eq!(dt.tomorrow()?, date(2024, 2, 29).at(7, 30, 0, 0));
960    ///
961    /// // The max doesn't have a tomorrow.
962    /// assert!(DateTime::MAX.tomorrow().is_err());
963    ///
964    /// # Ok::<(), Box<dyn std::error::Error>>(())
965    /// ```
966    #[inline]
967    pub fn tomorrow(self) -> Result<DateTime, Error> {
968        Ok(DateTime::from_parts(self.date().tomorrow()?, self.time()))
969    }
970
971    /// Returns the datetime with a date immediately preceding this one.
972    ///
973    /// The time in the datetime returned remains unchanged.
974    ///
975    /// # Errors
976    ///
977    /// This returns an error when this datetime's date is the minimum value.
978    ///
979    /// # Example
980    ///
981    /// ```
982    /// use jiff::civil::{DateTime, date};
983    ///
984    /// let dt = date(2024, 3, 1).at(7, 30, 0, 0);
985    /// assert_eq!(dt.yesterday()?, date(2024, 2, 29).at(7, 30, 0, 0));
986    ///
987    /// // The min doesn't have a yesterday.
988    /// assert!(DateTime::MIN.yesterday().is_err());
989    ///
990    /// # Ok::<(), Box<dyn std::error::Error>>(())
991    /// ```
992    #[inline]
993    pub fn yesterday(self) -> Result<DateTime, Error> {
994        Ok(DateTime::from_parts(self.date().yesterday()?, self.time()))
995    }
996
997    /// Returns the "nth" weekday from the beginning or end of the month in
998    /// which this datetime resides.
999    ///
1000    /// The `nth` parameter can be positive or negative. A positive value
1001    /// computes the "nth" weekday from the beginning of the month. A negative
1002    /// value computes the "nth" weekday from the end of the month. So for
1003    /// example, use `-1` to "find the last weekday" in this date's month.
1004    ///
1005    /// The time in the datetime returned remains unchanged.
1006    ///
1007    /// # Errors
1008    ///
1009    /// This returns an error when `nth` is `0`, or if it is `5` or `-5` and
1010    /// there is no 5th weekday from the beginning or end of the month.
1011    ///
1012    /// # Example
1013    ///
1014    /// This shows how to get the nth weekday in a month, starting from the
1015    /// beginning of the month:
1016    ///
1017    /// ```
1018    /// use jiff::civil::{Weekday, date};
1019    ///
1020    /// let dt = date(2017, 3, 1).at(7, 30, 0, 0);
1021    /// let second_friday = dt.nth_weekday_of_month(2, Weekday::Friday)?;
1022    /// assert_eq!(second_friday, date(2017, 3, 10).at(7, 30, 0, 0));
1023    ///
1024    /// # Ok::<(), Box<dyn std::error::Error>>(())
1025    /// ```
1026    ///
1027    /// This shows how to do the reverse of the above. That is, the nth _last_
1028    /// weekday in a month:
1029    ///
1030    /// ```
1031    /// use jiff::civil::{Weekday, date};
1032    ///
1033    /// let dt = date(2024, 3, 1).at(7, 30, 0, 0);
1034    /// let last_thursday = dt.nth_weekday_of_month(-1, Weekday::Thursday)?;
1035    /// assert_eq!(last_thursday, date(2024, 3, 28).at(7, 30, 0, 0));
1036    /// let second_last_thursday = dt.nth_weekday_of_month(
1037    ///     -2,
1038    ///     Weekday::Thursday,
1039    /// )?;
1040    /// assert_eq!(second_last_thursday, date(2024, 3, 21).at(7, 30, 0, 0));
1041    ///
1042    /// # Ok::<(), Box<dyn std::error::Error>>(())
1043    /// ```
1044    ///
1045    /// This routine can return an error if there isn't an `nth` weekday
1046    /// for this month. For example, March 2024 only has 4 Mondays:
1047    ///
1048    /// ```
1049    /// use jiff::civil::{Weekday, date};
1050    ///
1051    /// let dt = date(2024, 3, 25).at(7, 30, 0, 0);
1052    /// let fourth_monday = dt.nth_weekday_of_month(4, Weekday::Monday)?;
1053    /// assert_eq!(fourth_monday, date(2024, 3, 25).at(7, 30, 0, 0));
1054    /// // There is no 5th Monday.
1055    /// assert!(dt.nth_weekday_of_month(5, Weekday::Monday).is_err());
1056    /// // Same goes for counting backwards.
1057    /// assert!(dt.nth_weekday_of_month(-5, Weekday::Monday).is_err());
1058    ///
1059    /// # Ok::<(), Box<dyn std::error::Error>>(())
1060    /// ```
1061    #[inline]
1062    pub fn nth_weekday_of_month(
1063        self,
1064        nth: i8,
1065        weekday: Weekday,
1066    ) -> Result<DateTime, Error> {
1067        let date = self.date().nth_weekday_of_month(nth, weekday)?;
1068        Ok(DateTime::from_parts(date, self.time()))
1069    }
1070
1071    /// Returns the "nth" weekday from this datetime, not including itself.
1072    ///
1073    /// The `nth` parameter can be positive or negative. A positive value
1074    /// computes the "nth" weekday starting at the day after this date and
1075    /// going forwards in time. A negative value computes the "nth" weekday
1076    /// starting at the day before this date and going backwards in time.
1077    ///
1078    /// For example, if this datetime's weekday is a Sunday and the first
1079    /// Sunday is asked for (that is, `dt.nth_weekday(1, Weekday::Sunday)`),
1080    /// then the result is a week from this datetime corresponding to the
1081    /// following Sunday.
1082    ///
1083    /// The time in the datetime returned remains unchanged.
1084    ///
1085    /// # Errors
1086    ///
1087    /// This returns an error when `nth` is `0`, or if it would otherwise
1088    /// result in a date that overflows the minimum/maximum values of
1089    /// `DateTime`.
1090    ///
1091    /// # Example
1092    ///
1093    /// This example shows how to find the "nth" weekday going forwards in
1094    /// time:
1095    ///
1096    /// ```
1097    /// use jiff::civil::{Weekday, date};
1098    ///
1099    /// // Use a Sunday in March as our start date.
1100    /// let dt = date(2024, 3, 10).at(7, 30, 0, 0);
1101    /// assert_eq!(dt.weekday(), Weekday::Sunday);
1102    ///
1103    /// // The first next Monday is tomorrow!
1104    /// let next_monday = dt.nth_weekday(1, Weekday::Monday)?;
1105    /// assert_eq!(next_monday, date(2024, 3, 11).at(7, 30, 0, 0));
1106    ///
1107    /// // But the next Sunday is a week away, because this doesn't
1108    /// // include the current weekday.
1109    /// let next_sunday = dt.nth_weekday(1, Weekday::Sunday)?;
1110    /// assert_eq!(next_sunday, date(2024, 3, 17).at(7, 30, 0, 0));
1111    ///
1112    /// // "not this Thursday, but next Thursday"
1113    /// let next_next_thursday = dt.nth_weekday(2, Weekday::Thursday)?;
1114    /// assert_eq!(next_next_thursday, date(2024, 3, 21).at(7, 30, 0, 0));
1115    ///
1116    /// # Ok::<(), Box<dyn std::error::Error>>(())
1117    /// ```
1118    ///
1119    /// This example shows how to find the "nth" weekday going backwards in
1120    /// time:
1121    ///
1122    /// ```
1123    /// use jiff::civil::{Weekday, date};
1124    ///
1125    /// // Use a Sunday in March as our start date.
1126    /// let dt = date(2024, 3, 10).at(7, 30, 0, 0);
1127    /// assert_eq!(dt.weekday(), Weekday::Sunday);
1128    ///
1129    /// // "last Saturday" was yesterday!
1130    /// let last_saturday = dt.nth_weekday(-1, Weekday::Saturday)?;
1131    /// assert_eq!(last_saturday, date(2024, 3, 9).at(7, 30, 0, 0));
1132    ///
1133    /// // "last Sunday" was a week ago.
1134    /// let last_sunday = dt.nth_weekday(-1, Weekday::Sunday)?;
1135    /// assert_eq!(last_sunday, date(2024, 3, 3).at(7, 30, 0, 0));
1136    ///
1137    /// // "not last Thursday, but the one before"
1138    /// let prev_prev_thursday = dt.nth_weekday(-2, Weekday::Thursday)?;
1139    /// assert_eq!(prev_prev_thursday, date(2024, 2, 29).at(7, 30, 0, 0));
1140    ///
1141    /// # Ok::<(), Box<dyn std::error::Error>>(())
1142    /// ```
1143    ///
1144    /// This example shows that overflow results in an error in either
1145    /// direction:
1146    ///
1147    /// ```
1148    /// use jiff::civil::{DateTime, Weekday};
1149    ///
1150    /// let dt = DateTime::MAX;
1151    /// assert_eq!(dt.weekday(), Weekday::Friday);
1152    /// assert!(dt.nth_weekday(1, Weekday::Saturday).is_err());
1153    ///
1154    /// let dt = DateTime::MIN;
1155    /// assert_eq!(dt.weekday(), Weekday::Monday);
1156    /// assert!(dt.nth_weekday(-1, Weekday::Sunday).is_err());
1157    /// ```
1158    ///
1159    /// # Example: the start of Israeli summer time
1160    ///
1161    /// Israeli law says (at present, as of 2024-03-11) that DST or
1162    /// "summer time" starts on the Friday before the last Sunday in
1163    /// March. We can find that date using both `nth_weekday` and
1164    /// [`DateTime::nth_weekday_of_month`]:
1165    ///
1166    /// ```
1167    /// use jiff::civil::{Weekday, date};
1168    ///
1169    /// let march = date(2024, 3, 1).at(0, 0, 0, 0);
1170    /// let last_sunday = march.nth_weekday_of_month(-1, Weekday::Sunday)?;
1171    /// let dst_starts_on = last_sunday.nth_weekday(-1, Weekday::Friday)?;
1172    /// assert_eq!(dst_starts_on, date(2024, 3, 29).at(0, 0, 0, 0));
1173    ///
1174    /// # Ok::<(), Box<dyn std::error::Error>>(())
1175    /// ```
1176    ///
1177    /// # Example: getting the start of the week
1178    ///
1179    /// Given a date, one can use `nth_weekday` to determine the start of the
1180    /// week in which the date resides in. This might vary based on whether
1181    /// the weeks start on Sunday or Monday. This example shows how to handle
1182    /// both.
1183    ///
1184    /// ```
1185    /// use jiff::civil::{Weekday, date};
1186    ///
1187    /// let dt = date(2024, 3, 15).at(7, 30, 0, 0);
1188    /// // For weeks starting with Sunday.
1189    /// let start_of_week = dt.tomorrow()?.nth_weekday(-1, Weekday::Sunday)?;
1190    /// assert_eq!(start_of_week, date(2024, 3, 10).at(7, 30, 0, 0));
1191    /// // For weeks starting with Monday.
1192    /// let start_of_week = dt.tomorrow()?.nth_weekday(-1, Weekday::Monday)?;
1193    /// assert_eq!(start_of_week, date(2024, 3, 11).at(7, 30, 0, 0));
1194    ///
1195    /// # Ok::<(), Box<dyn std::error::Error>>(())
1196    /// ```
1197    ///
1198    /// In the above example, we first get the date after the current one
1199    /// because `nth_weekday` does not consider itself when counting. This
1200    /// works as expected even at the boundaries of a week:
1201    ///
1202    /// ```
1203    /// use jiff::civil::{Time, Weekday, date};
1204    ///
1205    /// // The start of the week.
1206    /// let dt = date(2024, 3, 10).at(0, 0, 0, 0);
1207    /// let start_of_week = dt.tomorrow()?.nth_weekday(-1, Weekday::Sunday)?;
1208    /// assert_eq!(start_of_week, date(2024, 3, 10).at(0, 0, 0, 0));
1209    /// // The end of the week.
1210    /// let dt = date(2024, 3, 16).at(23, 59, 59, 999_999_999);
1211    /// let start_of_week = dt
1212    ///     .tomorrow()?
1213    ///     .nth_weekday(-1, Weekday::Sunday)?
1214    ///     .with().time(Time::midnight()).build()?;
1215    /// assert_eq!(start_of_week, date(2024, 3, 10).at(0, 0, 0, 0));
1216    ///
1217    /// # Ok::<(), Box<dyn std::error::Error>>(())
1218    /// ```
1219    #[inline]
1220    pub fn nth_weekday(
1221        self,
1222        nth: i32,
1223        weekday: Weekday,
1224    ) -> Result<DateTime, Error> {
1225        let date = self.date().nth_weekday(nth, weekday)?;
1226        Ok(DateTime::from_parts(date, self.time()))
1227    }
1228
1229    /// Returns the date component of this datetime.
1230    ///
1231    /// # Example
1232    ///
1233    /// ```
1234    /// use jiff::civil::date;
1235    ///
1236    /// let dt = date(2024, 3, 14).at(18, 45, 0, 0);
1237    /// assert_eq!(dt.date(), date(2024, 3, 14));
1238    /// ```
1239    #[inline]
1240    pub fn date(self) -> Date {
1241        self.date
1242    }
1243
1244    /// Returns the time component of this datetime.
1245    ///
1246    /// # Example
1247    ///
1248    /// ```
1249    /// use jiff::civil::{date, time};
1250    ///
1251    /// let dt = date(2024, 3, 14).at(18, 45, 0, 0);
1252    /// assert_eq!(dt.time(), time(18, 45, 0, 0));
1253    /// ```
1254    #[inline]
1255    pub fn time(self) -> Time {
1256        self.time
1257    }
1258
1259    /// Construct an [ISO 8601 week date] from this datetime.
1260    ///
1261    /// The [`ISOWeekDate`] type describes itself in more detail, but in
1262    /// brief, the ISO week date calendar system eschews months in favor of
1263    /// weeks.
1264    ///
1265    /// This routine is equivalent to
1266    /// [`ISOWeekDate::from_date(dt.date())`](ISOWeekDate::from_date).
1267    ///
1268    /// [ISO 8601 week date]: https://en.wikipedia.org/wiki/ISO_week_date
1269    ///
1270    /// # Example
1271    ///
1272    /// This shows a number of examples demonstrating the conversion from a
1273    /// Gregorian date to an ISO 8601 week date:
1274    ///
1275    /// ```
1276    /// use jiff::civil::{Date, Time, Weekday, date};
1277    ///
1278    /// let dt = date(1995, 1, 1).at(18, 45, 0, 0);
1279    /// let weekdate = dt.iso_week_date();
1280    /// assert_eq!(weekdate.year(), 1994);
1281    /// assert_eq!(weekdate.week(), 52);
1282    /// assert_eq!(weekdate.weekday(), Weekday::Sunday);
1283    ///
1284    /// let dt = date(1996, 12, 31).at(18, 45, 0, 0);
1285    /// let weekdate = dt.iso_week_date();
1286    /// assert_eq!(weekdate.year(), 1997);
1287    /// assert_eq!(weekdate.week(), 1);
1288    /// assert_eq!(weekdate.weekday(), Weekday::Tuesday);
1289    ///
1290    /// let dt = date(2019, 12, 30).at(18, 45, 0, 0);
1291    /// let weekdate = dt.iso_week_date();
1292    /// assert_eq!(weekdate.year(), 2020);
1293    /// assert_eq!(weekdate.week(), 1);
1294    /// assert_eq!(weekdate.weekday(), Weekday::Monday);
1295    ///
1296    /// let dt = date(2024, 3, 9).at(18, 45, 0, 0);
1297    /// let weekdate = dt.iso_week_date();
1298    /// assert_eq!(weekdate.year(), 2024);
1299    /// assert_eq!(weekdate.week(), 10);
1300    /// assert_eq!(weekdate.weekday(), Weekday::Saturday);
1301    ///
1302    /// let dt = Date::MIN.to_datetime(Time::MIN);
1303    /// let weekdate = dt.iso_week_date();
1304    /// assert_eq!(weekdate.year(), -9999);
1305    /// assert_eq!(weekdate.week(), 1);
1306    /// assert_eq!(weekdate.weekday(), Weekday::Monday);
1307    ///
1308    /// let dt = Date::MAX.to_datetime(Time::MAX);
1309    /// let weekdate = dt.iso_week_date();
1310    /// assert_eq!(weekdate.year(), 9999);
1311    /// assert_eq!(weekdate.week(), 52);
1312    /// assert_eq!(weekdate.weekday(), Weekday::Friday);
1313    /// ```
1314    #[inline]
1315    pub fn iso_week_date(self) -> ISOWeekDate {
1316        self.date().iso_week_date()
1317    }
1318
1319    /// Converts a civil datetime to a [`Zoned`] datetime by adding the given
1320    /// time zone.
1321    ///
1322    /// The name given is resolved to a [`TimeZone`] by using the default
1323    /// [`TimeZoneDatabase`](crate::tz::TimeZoneDatabase) created by
1324    /// [`tz::db`](crate::tz::db). Indeed, this is a convenience function for
1325    /// [`DateTime::to_zoned`] where the time zone database lookup is done
1326    /// automatically.
1327    ///
1328    /// In some cases, a civil datetime may be ambiguous in a
1329    /// particular time zone. This routine automatically utilizes the
1330    /// [`Disambiguation::Compatible`](crate::tz::Disambiguation) strategy
1331    /// for resolving ambiguities. That is, if a civil datetime occurs in a
1332    /// backward transition (called a fold), then the earlier time is selected.
1333    /// Or if a civil datetime occurs in a forward transition (called a gap),
1334    /// then the later time is selected.
1335    ///
1336    /// To convert a datetime to a `Zoned` using a different disambiguation
1337    /// strategy, use [`TimeZone::to_ambiguous_zoned`].
1338    ///
1339    /// # Errors
1340    ///
1341    /// This returns an error when the given time zone name could not be found
1342    /// in the default time zone database.
1343    ///
1344    /// This also returns an error if this datetime could not be represented as
1345    /// an instant. This can occur in some cases near the minimum and maximum
1346    /// boundaries of a `DateTime`.
1347    ///
1348    /// # Example
1349    ///
1350    /// This is a simple example of converting a civil datetime (a "wall" or
1351    /// "local" or "naive" datetime) to a datetime that is aware of its time
1352    /// zone:
1353    ///
1354    /// ```
1355    /// use jiff::civil::DateTime;
1356    ///
1357    /// let dt: DateTime = "2024-06-20 15:06".parse()?;
1358    /// let zdt = dt.in_tz("America/New_York")?;
1359    /// assert_eq!(zdt.to_string(), "2024-06-20T15:06:00-04:00[America/New_York]");
1360    ///
1361    /// # Ok::<(), Box<dyn std::error::Error>>(())
1362    /// ```
1363    ///
1364    /// # Example: dealing with ambiguity
1365    ///
1366    /// In the `America/New_York` time zone, there was a forward transition
1367    /// at `2024-03-10 02:00:00` civil time, and a backward transition at
1368    /// `2024-11-03 01:00:00` civil time. In the former case, a gap was
1369    /// created such that the 2 o'clock hour never appeared on clocks for folks
1370    /// in the `America/New_York` time zone. In the latter case, a fold was
1371    /// created such that the 1 o'clock hour was repeated. Thus, March 10, 2024
1372    /// in New York was 23 hours long, while November 3, 2024 in New York was
1373    /// 25 hours long.
1374    ///
1375    /// This example shows how datetimes in these gaps and folds are resolved
1376    /// by default:
1377    ///
1378    /// ```
1379    /// use jiff::civil::DateTime;
1380    ///
1381    /// // This is the gap, where by default we select the later time.
1382    /// let dt: DateTime = "2024-03-10 02:30".parse()?;
1383    /// let zdt = dt.in_tz("America/New_York")?;
1384    /// assert_eq!(zdt.to_string(), "2024-03-10T03:30:00-04:00[America/New_York]");
1385    ///
1386    /// // This is the fold, where by default we select the earlier time.
1387    /// let dt: DateTime = "2024-11-03 01:30".parse()?;
1388    /// let zdt = dt.in_tz("America/New_York")?;
1389    /// // Since this is a fold, the wall clock time is repeated. It might be
1390    /// // hard to see that this is the earlier time, but notice the offset:
1391    /// // it is the offset for DST time in New York. The later time, or the
1392    /// // repetition of the 1 o'clock hour, would occur in standard time,
1393    /// // which is an offset of -05 for New York.
1394    /// assert_eq!(zdt.to_string(), "2024-11-03T01:30:00-04:00[America/New_York]");
1395    ///
1396    /// # Ok::<(), Box<dyn std::error::Error>>(())
1397    /// ```
1398    ///
1399    /// # Example: errors
1400    ///
1401    /// This routine can return an error when the time zone is unrecognized:
1402    ///
1403    /// ```
1404    /// use jiff::civil::date;
1405    ///
1406    /// let dt = date(2024, 6, 20).at(15, 6, 0, 0);
1407    /// assert!(dt.in_tz("does not exist").is_err());
1408    /// ```
1409    ///
1410    /// Note that even if a time zone exists in, say, the IANA database, there
1411    /// may have been a problem reading it from your system's installation of
1412    /// that database. To see what wrong, enable Jiff's `logging` crate feature
1413    /// and install a logger. If there was a failure, then a `WARN` level log
1414    /// message should be emitted.
1415    ///
1416    /// This routine can also fail if this datetime cannot be represented
1417    /// within the allowable timestamp limits:
1418    ///
1419    /// ```
1420    /// use jiff::{civil::DateTime, tz::{Offset, TimeZone}};
1421    ///
1422    /// let dt = DateTime::MAX;
1423    /// // All errors because the combination of the offset and the datetime
1424    /// // isn't enough to fit into timestamp limits.
1425    /// assert!(dt.in_tz("UTC").is_err());
1426    /// assert!(dt.in_tz("America/New_York").is_err());
1427    /// assert!(dt.in_tz("Australia/Tasmania").is_err());
1428    /// // In fact, the only valid offset one can use to turn the maximum civil
1429    /// // datetime into a Zoned value is the maximum offset:
1430    /// let tz = Offset::from_seconds(93_599).unwrap().to_time_zone();
1431    /// assert!(dt.to_zoned(tz).is_ok());
1432    /// // One second less than the maximum offset results in a failure at the
1433    /// // maximum datetime boundary.
1434    /// let tz = Offset::from_seconds(93_598).unwrap().to_time_zone();
1435    /// assert!(dt.to_zoned(tz).is_err());
1436    /// ```
1437    ///
1438    /// This behavior exists because it guarantees that every possible `Zoned`
1439    /// value can be converted into a civil datetime, but not every possible
1440    /// combination of civil datetime and offset can be converted into a
1441    /// `Zoned` value. There isn't a way to make every possible roundtrip
1442    /// lossless in both directions, so Jiff chooses to ensure that there is
1443    /// always a way to convert a `Zoned` instant to a human readable wall
1444    /// clock time.
1445    #[inline]
1446    pub fn in_tz(self, time_zone_name: &str) -> Result<Zoned, Error> {
1447        let tz = crate::tz::db().get(time_zone_name)?;
1448        self.to_zoned(tz)
1449    }
1450
1451    /// Converts a civil datetime to a [`Zoned`] datetime by adding the given
1452    /// [`TimeZone`].
1453    ///
1454    /// In some cases, a civil datetime may be ambiguous in a
1455    /// particular time zone. This routine automatically utilizes the
1456    /// [`Disambiguation::Compatible`](crate::tz::Disambiguation) strategy
1457    /// for resolving ambiguities. That is, if a civil datetime occurs in a
1458    /// backward transition (called a fold), then the earlier time is selected.
1459    /// Or if a civil datetime occurs in a forward transition (called a gap),
1460    /// then the later time is selected.
1461    ///
1462    /// To convert a datetime to a `Zoned` using a different disambiguation
1463    /// strategy, use [`TimeZone::to_ambiguous_zoned`].
1464    ///
1465    /// In the common case of a time zone being represented as a name string,
1466    /// like `Australia/Tasmania`, consider using [`DateTime::in_tz`]
1467    /// instead.
1468    ///
1469    /// # Errors
1470    ///
1471    /// This returns an error if this datetime could not be represented as an
1472    /// instant. This can occur in some cases near the minimum and maximum
1473    /// boundaries of a `DateTime`.
1474    ///
1475    /// # Example
1476    ///
1477    /// This example shows how to create a zoned value with a fixed time zone
1478    /// offset:
1479    ///
1480    /// ```
1481    /// use jiff::{civil::date, tz::{self, TimeZone}};
1482    ///
1483    /// let tz = TimeZone::fixed(tz::offset(-4));
1484    /// let zdt = date(2024, 6, 20).at(17, 3, 0, 0).to_zoned(tz)?;
1485    /// // A time zone annotation is still included in the printable version
1486    /// // of the Zoned value, but it is fixed to a particular offset.
1487    /// assert_eq!(zdt.to_string(), "2024-06-20T17:03:00-04:00[-04:00]");
1488    ///
1489    /// # Ok::<(), Box<dyn std::error::Error>>(())
1490    /// ```
1491    ///
1492    /// # Example: POSIX time zone strings
1493    ///
1494    /// And this example shows how to create a time zone from a POSIX time
1495    /// zone string that describes the transition to and from daylight saving
1496    /// time for `America/St_Johns`. In particular, this rule uses non-zero
1497    /// minutes, which is atypical.
1498    ///
1499    /// ```
1500    /// use jiff::{civil::date, tz::TimeZone};
1501    ///
1502    /// let tz = TimeZone::posix("NST3:30NDT,M3.2.0,M11.1.0")?;
1503    /// let zdt = date(2024, 6, 20).at(17, 3, 0, 0).to_zoned(tz)?;
1504    /// // There isn't any agreed upon mechanism for transmitting a POSIX time
1505    /// // zone string within an RFC 9557 TZ annotation, so Jiff just emits the
1506    /// // offset. In practice, POSIX TZ strings are rarely user facing anyway.
1507    /// // (They are still in widespread use as an implementation detail of the
1508    /// // IANA Time Zone Database however.)
1509    /// assert_eq!(zdt.to_string(), "2024-06-20T17:03:00-02:30[-02:30]");
1510    ///
1511    /// # Ok::<(), Box<dyn std::error::Error>>(())
1512    /// ```
1513    #[inline]
1514    pub fn to_zoned(self, tz: TimeZone) -> Result<Zoned, Error> {
1515        use crate::tz::AmbiguousOffset;
1516
1517        // It's pretty disappointing that we do this instead of the
1518        // simpler:
1519        //
1520        //     tz.into_ambiguous_zoned(self).compatible()
1521        //
1522        // Below, in the common case of an unambiguous datetime,
1523        // we avoid doing the work to re-derive the datetime *and*
1524        // offset from the timestamp we find from tzdb. In particular,
1525        // `Zoned::new` does this work given a timestamp and a time
1526        // zone. But we circumvent `Zoned::new` and use a special
1527        // `Zoned::from_parts` crate-internal constructor to handle
1528        // this case.
1529        //
1530        // Ideally we could do this in `AmbiguousZoned::compatible`
1531        // itself, but it turns out that it doesn't always work.
1532        // Namely, that API supports providing an unambiguous
1533        // offset even when the civil datetime is within a
1534        // DST transition. In that case, once the timestamp
1535        // is resolved, the offset given might actually
1536        // change. See `2024-03-11T02:02[America/New_York]`
1537        // example for `AlwaysOffset` conflict resolution on
1538        // `ZonedWith::disambiguation`.
1539        //
1540        // But the optimization works here because if we get an
1541        // unambiguous offset from tzdb, then we know it isn't in a DST
1542        // transition and that it won't change with the timestamp.
1543        //
1544        // This ends up saving a fair bit of cycles re-computing
1545        // the offset (which requires another tzdb lookup) and
1546        // re-generating the civil datetime from the timestamp for the
1547        // re-computed offset. This helps the
1548        // `civil_datetime_to_timestamp_tzdb_lookup/zoneinfo/jiff`
1549        // micro-benchmark quite a bit.
1550        let dt = self;
1551        let amb_ts = tz.to_ambiguous_timestamp(dt);
1552        let (offset, ts, dt) = match amb_ts.offset() {
1553            AmbiguousOffset::Unambiguous { offset } => {
1554                let ts = offset.to_timestamp(dt)?;
1555                (offset, ts, dt)
1556            }
1557            AmbiguousOffset::Gap { before, .. } => {
1558                let ts = before.to_timestamp(dt)?;
1559                let offset = tz.to_offset(ts);
1560                let dt = offset.to_datetime(ts);
1561                (offset, ts, dt)
1562            }
1563            AmbiguousOffset::Fold { before, .. } => {
1564                let ts = before.to_timestamp(dt)?;
1565                let offset = tz.to_offset(ts);
1566                let dt = offset.to_datetime(ts);
1567                (offset, ts, dt)
1568            }
1569        };
1570        Ok(Zoned::from_parts(ts, dt, offset, tz))
1571    }
1572
1573    /// Add the given span of time to this datetime. If the sum would overflow
1574    /// the minimum or maximum datetime values, then an error is returned.
1575    ///
1576    /// This operation accepts three different duration types: [`Span`],
1577    /// [`SignedDuration`] or [`std::time::Duration`]. This is achieved via
1578    /// `From` trait implementations for the [`DateTimeArithmetic`] type.
1579    ///
1580    /// # Properties
1581    ///
1582    /// This routine is _not_ reversible because some additions may
1583    /// be ambiguous. For example, adding `1 month` to the datetime
1584    /// `2024-03-31T00:00:00` will produce `2024-04-30T00:00:00` since April
1585    /// has only 30 days in a month. Moreover, subtracting `1 month` from
1586    /// `2024-04-30T00:00:00` will produce `2024-03-30T00:00:00`, which is not
1587    /// the date we started with.
1588    ///
1589    /// If spans of time are limited to units of days (or less), then this
1590    /// routine _is_ reversible. This also implies that all operations with a
1591    /// [`SignedDuration`] or a [`std::time::Duration`] are reversible.
1592    ///
1593    /// # Errors
1594    ///
1595    /// If the span added to this datetime would result in a datetime that
1596    /// exceeds the range of a `DateTime`, then this will return an error.
1597    ///
1598    /// # Example
1599    ///
1600    /// This shows a few examples of adding spans of time to various dates.
1601    /// We make use of the [`ToSpan`](crate::ToSpan) trait for convenient
1602    /// creation of spans.
1603    ///
1604    /// ```
1605    /// use jiff::{civil::date, ToSpan};
1606    ///
1607    /// let dt = date(1995, 12, 7).at(3, 24, 30, 3_500);
1608    /// let got = dt.checked_add(20.years().months(4).nanoseconds(500))?;
1609    /// assert_eq!(got, date(2016, 4, 7).at(3, 24, 30, 4_000));
1610    ///
1611    /// let dt = date(2019, 1, 31).at(15, 30, 0, 0);
1612    /// let got = dt.checked_add(1.months())?;
1613    /// assert_eq!(got, date(2019, 2, 28).at(15, 30, 0, 0));
1614    ///
1615    /// # Ok::<(), Box<dyn std::error::Error>>(())
1616    /// ```
1617    ///
1618    /// # Example: available via addition operator
1619    ///
1620    /// This routine can be used via the `+` operator. Note though that if it
1621    /// fails, it will result in a panic.
1622    ///
1623    /// ```
1624    /// use jiff::{civil::date, ToSpan};
1625    ///
1626    /// let dt = date(1995, 12, 7).at(3, 24, 30, 3_500);
1627    /// let got = dt + 20.years().months(4).nanoseconds(500);
1628    /// assert_eq!(got, date(2016, 4, 7).at(3, 24, 30, 4_000));
1629    /// ```
1630    ///
1631    /// # Example: negative spans are supported
1632    ///
1633    /// ```
1634    /// use jiff::{civil::date, ToSpan};
1635    ///
1636    /// let dt = date(2024, 3, 31).at(19, 5, 59, 999_999_999);
1637    /// assert_eq!(
1638    ///     dt.checked_add(-1.months())?,
1639    ///     date(2024, 2, 29).at(19, 5, 59, 999_999_999),
1640    /// );
1641    ///
1642    /// # Ok::<(), Box<dyn std::error::Error>>(())
1643    /// ```
1644    ///
1645    /// # Example: error on overflow
1646    ///
1647    /// ```
1648    /// use jiff::{civil::date, ToSpan};
1649    ///
1650    /// let dt = date(2024, 3, 31).at(13, 13, 13, 13);
1651    /// assert!(dt.checked_add(9000.years()).is_err());
1652    /// assert!(dt.checked_add(-19000.years()).is_err());
1653    /// ```
1654    ///
1655    /// # Example: adding absolute durations
1656    ///
1657    /// This shows how to add signed and unsigned absolute durations to a
1658    /// `DateTime`.
1659    ///
1660    /// ```
1661    /// use std::time::Duration;
1662    ///
1663    /// use jiff::{civil::date, SignedDuration};
1664    ///
1665    /// let dt = date(2024, 2, 29).at(0, 0, 0, 0);
1666    ///
1667    /// let dur = SignedDuration::from_hours(25);
1668    /// assert_eq!(dt.checked_add(dur)?, date(2024, 3, 1).at(1, 0, 0, 0));
1669    /// assert_eq!(dt.checked_add(-dur)?, date(2024, 2, 27).at(23, 0, 0, 0));
1670    ///
1671    /// let dur = Duration::from_secs(25 * 60 * 60);
1672    /// assert_eq!(dt.checked_add(dur)?, date(2024, 3, 1).at(1, 0, 0, 0));
1673    /// // One cannot negate an unsigned duration,
1674    /// // but you can subtract it!
1675    /// assert_eq!(dt.checked_sub(dur)?, date(2024, 2, 27).at(23, 0, 0, 0));
1676    ///
1677    /// # Ok::<(), Box<dyn std::error::Error>>(())
1678    /// ```
1679    #[inline]
1680    pub fn checked_add<A: Into<DateTimeArithmetic>>(
1681        self,
1682        duration: A,
1683    ) -> Result<DateTime, Error> {
1684        let duration: DateTimeArithmetic = duration.into();
1685        duration.checked_add(self)
1686    }
1687
1688    #[inline]
1689    fn checked_add_span(self, span: &Span) -> Result<DateTime, Error> {
1690        let (old_date, old_time) = (self.date(), self.time());
1691        let units = span.units();
1692        match (units.only_calendar().is_empty(), units.only_time().is_empty())
1693        {
1694            (true, true) => Ok(self),
1695            (false, true) => {
1696                let new_date = old_date
1697                    .checked_add(span)
1698                    .context(E::FailedAddSpanDate)?;
1699                Ok(DateTime::from_parts(new_date, old_time))
1700            }
1701            (true, false) => {
1702                let (new_time, leftovers) = old_time
1703                    .overflowing_add(span)
1704                    .context(E::FailedAddSpanTime)?;
1705                let new_date = old_date
1706                    .checked_add(leftovers)
1707                    .context(E::FailedAddSpanOverflowing)?;
1708                Ok(DateTime::from_parts(new_date, new_time))
1709            }
1710            (false, false) => self.checked_add_span_general(span),
1711        }
1712    }
1713
1714    #[inline(never)]
1715    #[cold]
1716    fn checked_add_span_general(self, span: &Span) -> Result<DateTime, Error> {
1717        let (old_date, old_time) = (self.date(), self.time());
1718        let span_date = span.without_lower(Unit::Day);
1719        let span_time = span.only_lower(Unit::Day);
1720
1721        let (new_time, leftovers) = old_time
1722            .overflowing_add(&span_time)
1723            .context(E::FailedAddSpanTime)?;
1724        let new_date =
1725            old_date.checked_add(span_date).context(E::FailedAddSpanDate)?;
1726        let new_date = new_date
1727            .checked_add(leftovers)
1728            .context(E::FailedAddSpanOverflowing)?;
1729        Ok(DateTime::from_parts(new_date, new_time))
1730    }
1731
1732    #[inline]
1733    fn checked_add_duration(
1734        self,
1735        duration: SignedDuration,
1736    ) -> Result<DateTime, Error> {
1737        let (date, time) = (self.date(), self.time());
1738        let (new_time, leftovers) = time.overflowing_add_duration(duration)?;
1739        let new_date = date
1740            .checked_add(leftovers)
1741            .context(E::FailedAddDurationOverflowing)?;
1742        Ok(DateTime::from_parts(new_date, new_time))
1743    }
1744
1745    /// This routine is identical to [`DateTime::checked_add`] with the
1746    /// duration negated.
1747    ///
1748    /// # Errors
1749    ///
1750    /// This has the same error conditions as [`DateTime::checked_add`].
1751    ///
1752    /// # Example
1753    ///
1754    /// This routine can be used via the `-` operator. Note though that if it
1755    /// fails, it will result in a panic.
1756    ///
1757    /// ```
1758    /// use std::time::Duration;
1759    ///
1760    /// use jiff::{civil::date, SignedDuration, ToSpan};
1761    ///
1762    /// let dt = date(1995, 12, 7).at(3, 24, 30, 3_500);
1763    /// assert_eq!(
1764    ///     dt - 20.years().months(4).nanoseconds(500),
1765    ///     date(1975, 8, 7).at(3, 24, 30, 3_000),
1766    /// );
1767    ///
1768    /// let dur = SignedDuration::new(24 * 60 * 60, 3_500);
1769    /// assert_eq!(dt - dur, date(1995, 12, 6).at(3, 24, 30, 0));
1770    ///
1771    /// let dur = Duration::new(24 * 60 * 60, 3_500);
1772    /// assert_eq!(dt - dur, date(1995, 12, 6).at(3, 24, 30, 0));
1773    ///
1774    /// # Ok::<(), Box<dyn std::error::Error>>(())
1775    /// ```
1776    #[inline]
1777    pub fn checked_sub<A: Into<DateTimeArithmetic>>(
1778        self,
1779        duration: A,
1780    ) -> Result<DateTime, Error> {
1781        let duration: DateTimeArithmetic = duration.into();
1782        duration.checked_neg().and_then(|dta| dta.checked_add(self))
1783    }
1784
1785    /// This routine is identical to [`DateTime::checked_add`], except the
1786    /// result saturates on overflow. That is, instead of overflow, either
1787    /// [`DateTime::MIN`] or [`DateTime::MAX`] is returned.
1788    ///
1789    /// # Example
1790    ///
1791    /// ```
1792    /// use jiff::{civil::{DateTime, date}, SignedDuration, ToSpan};
1793    ///
1794    /// let dt = date(2024, 3, 31).at(13, 13, 13, 13);
1795    /// assert_eq!(DateTime::MAX, dt.saturating_add(9000.years()));
1796    /// assert_eq!(DateTime::MIN, dt.saturating_add(-19000.years()));
1797    /// assert_eq!(DateTime::MAX, dt.saturating_add(SignedDuration::MAX));
1798    /// assert_eq!(DateTime::MIN, dt.saturating_add(SignedDuration::MIN));
1799    /// assert_eq!(DateTime::MAX, dt.saturating_add(std::time::Duration::MAX));
1800    /// ```
1801    #[inline]
1802    pub fn saturating_add<A: Into<DateTimeArithmetic>>(
1803        self,
1804        duration: A,
1805    ) -> DateTime {
1806        let duration: DateTimeArithmetic = duration.into();
1807        self.checked_add(duration).unwrap_or_else(|_| {
1808            if duration.is_negative() {
1809                DateTime::MIN
1810            } else {
1811                DateTime::MAX
1812            }
1813        })
1814    }
1815
1816    /// This routine is identical to [`DateTime::saturating_add`] with the span
1817    /// parameter negated.
1818    ///
1819    /// # Example
1820    ///
1821    /// ```
1822    /// use jiff::{civil::{DateTime, date}, SignedDuration, ToSpan};
1823    ///
1824    /// let dt = date(2024, 3, 31).at(13, 13, 13, 13);
1825    /// assert_eq!(DateTime::MIN, dt.saturating_sub(19000.years()));
1826    /// assert_eq!(DateTime::MAX, dt.saturating_sub(-9000.years()));
1827    /// assert_eq!(DateTime::MIN, dt.saturating_sub(SignedDuration::MAX));
1828    /// assert_eq!(DateTime::MAX, dt.saturating_sub(SignedDuration::MIN));
1829    /// assert_eq!(DateTime::MIN, dt.saturating_sub(std::time::Duration::MAX));
1830    /// ```
1831    #[inline]
1832    pub fn saturating_sub<A: Into<DateTimeArithmetic>>(
1833        self,
1834        duration: A,
1835    ) -> DateTime {
1836        let duration: DateTimeArithmetic = duration.into();
1837        let Ok(duration) = duration.checked_neg() else {
1838            return DateTime::MIN;
1839        };
1840        self.saturating_add(duration)
1841    }
1842
1843    /// Returns a span representing the elapsed time from this datetime until
1844    /// the given `other` datetime.
1845    ///
1846    /// When `other` occurs before this datetime, then the span returned will
1847    /// be negative.
1848    ///
1849    /// Depending on the input provided, the span returned is rounded. It may
1850    /// also be balanced up to bigger units than the default. By default, the
1851    /// span returned is balanced such that the biggest possible unit is days.
1852    /// This default is an API guarantee. Users can rely on the default not
1853    /// returning any calendar units bigger than days in the default
1854    /// configuration.
1855    ///
1856    /// This operation is configured by providing a [`DateTimeDifference`]
1857    /// value. Since this routine accepts anything that implements
1858    /// `Into<DateTimeDifference>`, once can pass a `DateTime` directly.
1859    /// One can also pass a `(Unit, DateTime)`, where `Unit` is treated as
1860    /// [`DateTimeDifference::largest`].
1861    ///
1862    /// # Properties
1863    ///
1864    /// It is guaranteed that if the returned span is subtracted from `other`,
1865    /// and if no rounding is requested, and if the largest unit requested is
1866    /// at most `Unit::Day`, then the original datetime will be returned.
1867    ///
1868    /// This routine is equivalent to `self.since(other).map(|span| -span)`
1869    /// if no rounding options are set. If rounding options are set, then
1870    /// it's equivalent to
1871    /// `self.since(other_without_rounding_options).map(|span| -span)`,
1872    /// followed by a call to [`Span::round`] with the appropriate rounding
1873    /// options set. This is because the negation of a span can result in
1874    /// different rounding results depending on the rounding mode.
1875    ///
1876    /// # Errors
1877    ///
1878    /// An error can occur in some cases when the requested configuration would
1879    /// result in a span that is beyond allowable limits. For example, the
1880    /// nanosecond component of a span cannot the span of time between the
1881    /// minimum and maximum datetime supported by Jiff. Therefore, if one
1882    /// requests a span with its largest unit set to [`Unit::Nanosecond`], then
1883    /// it's possible for this routine to fail.
1884    ///
1885    /// It is guaranteed that if one provides a datetime with the default
1886    /// [`DateTimeDifference`] configuration, then this routine will never
1887    /// fail.
1888    ///
1889    /// # Example
1890    ///
1891    /// ```
1892    /// use jiff::{civil::date, ToSpan};
1893    ///
1894    /// let earlier = date(2006, 8, 24).at(22, 30, 0, 0);
1895    /// let later = date(2019, 1, 31).at(21, 0, 0, 0);
1896    /// assert_eq!(
1897    ///     earlier.until(later)?,
1898    ///     4542.days().hours(22).minutes(30).fieldwise(),
1899    /// );
1900    ///
1901    /// // Flipping the dates is fine, but you'll get a negative span.
1902    /// assert_eq!(
1903    ///     later.until(earlier)?,
1904    ///     -4542.days().hours(22).minutes(30).fieldwise(),
1905    /// );
1906    ///
1907    /// # Ok::<(), Box<dyn std::error::Error>>(())
1908    /// ```
1909    ///
1910    /// # Example: using bigger units
1911    ///
1912    /// This example shows how to expand the span returned to bigger units.
1913    /// This makes use of a `From<(Unit, DateTime)> for DateTimeDifference`
1914    /// trait implementation.
1915    ///
1916    /// ```
1917    /// use jiff::{civil::date, Unit, ToSpan};
1918    ///
1919    /// let dt1 = date(1995, 12, 07).at(3, 24, 30, 3500);
1920    /// let dt2 = date(2019, 01, 31).at(15, 30, 0, 0);
1921    ///
1922    /// // The default limits durations to using "days" as the biggest unit.
1923    /// let span = dt1.until(dt2)?;
1924    /// assert_eq!(span.to_string(), "P8456DT12H5M29.9999965S");
1925    ///
1926    /// // But we can ask for units all the way up to years.
1927    /// let span = dt1.until((Unit::Year, dt2))?;
1928    /// assert_eq!(span.to_string(), "P23Y1M24DT12H5M29.9999965S");
1929    /// # Ok::<(), Box<dyn std::error::Error>>(())
1930    /// ```
1931    ///
1932    /// # Example: rounding the result
1933    ///
1934    /// This shows how one might find the difference between two datetimes and
1935    /// have the result rounded such that sub-seconds are removed.
1936    ///
1937    /// In this case, we need to hand-construct a [`DateTimeDifference`]
1938    /// in order to gain full configurability.
1939    ///
1940    /// ```
1941    /// use jiff::{civil::{DateTimeDifference, date}, Unit, ToSpan};
1942    ///
1943    /// let dt1 = date(1995, 12, 07).at(3, 24, 30, 3500);
1944    /// let dt2 = date(2019, 01, 31).at(15, 30, 0, 0);
1945    ///
1946    /// let span = dt1.until(
1947    ///     DateTimeDifference::from(dt2).smallest(Unit::Second),
1948    /// )?;
1949    /// assert_eq!(format!("{span:#}"), "8456d 12h 5m 29s");
1950    ///
1951    /// // We can combine smallest and largest units too!
1952    /// let span = dt1.until(
1953    ///     DateTimeDifference::from(dt2)
1954    ///         .smallest(Unit::Second)
1955    ///         .largest(Unit::Year),
1956    /// )?;
1957    /// assert_eq!(span.to_string(), "P23Y1M24DT12H5M29S");
1958    /// # Ok::<(), Box<dyn std::error::Error>>(())
1959    /// ```
1960    ///
1961    /// # Example: units biggers than days inhibit reversibility
1962    ///
1963    /// If you ask for units bigger than days, then subtracting the span
1964    /// returned from the `other` datetime is not guaranteed to result in the
1965    /// original datetime. For example:
1966    ///
1967    /// ```
1968    /// use jiff::{civil::date, Unit, ToSpan};
1969    ///
1970    /// let dt1 = date(2024, 3, 2).at(0, 0, 0, 0);
1971    /// let dt2 = date(2024, 5, 1).at(0, 0, 0, 0);
1972    ///
1973    /// let span = dt1.until((Unit::Month, dt2))?;
1974    /// assert_eq!(span, 1.month().days(29).fieldwise());
1975    /// let maybe_original = dt2.checked_sub(span)?;
1976    /// // Not the same as the original datetime!
1977    /// assert_eq!(maybe_original, date(2024, 3, 3).at(0, 0, 0, 0));
1978    ///
1979    /// // But in the default configuration, days are always the biggest unit
1980    /// // and reversibility is guaranteed.
1981    /// let span = dt1.until(dt2)?;
1982    /// assert_eq!(span, 60.days().fieldwise());
1983    /// let is_original = dt2.checked_sub(span)?;
1984    /// assert_eq!(is_original, dt1);
1985    ///
1986    /// # Ok::<(), Box<dyn std::error::Error>>(())
1987    /// ```
1988    ///
1989    /// This occurs because span are added as if by adding the biggest units
1990    /// first, and then the smaller units. Because months vary in length,
1991    /// their meaning can change depending on how the span is added. In this
1992    /// case, adding one month to `2024-03-02` corresponds to 31 days, but
1993    /// subtracting one month from `2024-05-01` corresponds to 30 days.
1994    #[inline]
1995    pub fn until<A: Into<DateTimeDifference>>(
1996        self,
1997        other: A,
1998    ) -> Result<Span, Error> {
1999        let args: DateTimeDifference = other.into();
2000        let span = args.until_with_largest_unit(self)?;
2001        if args.rounding_may_change_span() {
2002            span.round(args.round.relative(self))
2003        } else {
2004            Ok(span)
2005        }
2006    }
2007
2008    /// This routine is identical to [`DateTime::until`], but the order of the
2009    /// parameters is flipped.
2010    ///
2011    /// # Errors
2012    ///
2013    /// This has the same error conditions as [`DateTime::until`].
2014    ///
2015    /// # Example
2016    ///
2017    /// This routine can be used via the `-` operator. Since the default
2018    /// configuration is used and because a `Span` can represent the difference
2019    /// between any two possible datetimes, it will never panic.
2020    ///
2021    /// ```
2022    /// use jiff::{civil::date, ToSpan};
2023    ///
2024    /// let earlier = date(2006, 8, 24).at(22, 30, 0, 0);
2025    /// let later = date(2019, 1, 31).at(21, 0, 0, 0);
2026    /// assert_eq!(
2027    ///     later - earlier,
2028    ///     4542.days().hours(22).minutes(30).fieldwise(),
2029    /// );
2030    /// ```
2031    #[inline]
2032    pub fn since<A: Into<DateTimeDifference>>(
2033        self,
2034        other: A,
2035    ) -> Result<Span, Error> {
2036        let args: DateTimeDifference = other.into();
2037        let span = -args.until_with_largest_unit(self)?;
2038        if args.rounding_may_change_span() {
2039            span.round(args.round.relative(self))
2040        } else {
2041            Ok(span)
2042        }
2043    }
2044
2045    /// Returns an absolute duration representing the elapsed time from this
2046    /// datetime until the given `other` datetime.
2047    ///
2048    /// When `other` occurs before this datetime, then the duration returned
2049    /// will be negative.
2050    ///
2051    /// Unlike [`DateTime::until`], this returns a duration corresponding to a
2052    /// 96-bit integer of nanoseconds between two datetimes.
2053    ///
2054    /// # Fallibility
2055    ///
2056    /// This routine never panics or returns an error. Since there are no
2057    /// configuration options that can be incorrectly provided, no error is
2058    /// possible when calling this routine. In contrast, [`DateTime::until`]
2059    /// can return an error in some cases due to misconfiguration. But like
2060    /// this routine, [`DateTime::until`] never panics or returns an error in
2061    /// its default configuration.
2062    ///
2063    /// # When should I use this versus [`DateTime::until`]?
2064    ///
2065    /// See the type documentation for [`SignedDuration`] for the section on
2066    /// when one should use [`Span`] and when one should use `SignedDuration`.
2067    /// In short, use `Span` (and therefore `DateTime::until`) unless you have
2068    /// a specific reason to do otherwise.
2069    ///
2070    /// # Example
2071    ///
2072    /// ```
2073    /// use jiff::{civil::date, SignedDuration};
2074    ///
2075    /// let earlier = date(2006, 8, 24).at(22, 30, 0, 0);
2076    /// let later = date(2019, 1, 31).at(21, 0, 0, 0);
2077    /// assert_eq!(
2078    ///     earlier.duration_until(later),
2079    ///     SignedDuration::from_hours(4542 * 24)
2080    ///     + SignedDuration::from_hours(22)
2081    ///     + SignedDuration::from_mins(30),
2082    /// );
2083    /// // Flipping the datetimes is fine, but you'll get a negative duration.
2084    /// assert_eq!(
2085    ///     later.duration_until(earlier),
2086    ///     -SignedDuration::from_hours(4542 * 24)
2087    ///     - SignedDuration::from_hours(22)
2088    ///     - SignedDuration::from_mins(30),
2089    /// );
2090    /// ```
2091    ///
2092    /// # Example: difference with [`DateTime::until`]
2093    ///
2094    /// The main difference between this routine and `DateTime::until` is that
2095    /// the latter can return units other than a 96-bit integer of nanoseconds.
2096    /// While a 96-bit integer of nanoseconds can be converted into other units
2097    /// like hours, this can only be done for uniform units. (Uniform units are
2098    /// units for which each individual unit always corresponds to the same
2099    /// elapsed time regardless of the datetime it is relative to.) This can't
2100    /// be done for units like years or months.
2101    ///
2102    /// ```
2103    /// use jiff::{civil::date, SignedDuration, Span, SpanRound, ToSpan, Unit};
2104    ///
2105    /// let dt1 = date(2024, 1, 1).at(0, 0, 0, 0);
2106    /// let dt2 = date(2025, 4, 1).at(0, 0, 0, 0);
2107    ///
2108    /// let span = dt1.until((Unit::Year, dt2))?;
2109    /// assert_eq!(span, 1.year().months(3).fieldwise());
2110    ///
2111    /// let duration = dt1.duration_until(dt2);
2112    /// assert_eq!(duration, SignedDuration::from_hours(456 * 24));
2113    /// // There's no way to extract years or months from the signed
2114    /// // duration like one might extract hours (because every hour
2115    /// // is the same length). Instead, you actually have to convert
2116    /// // it to a span and then balance it by providing a relative date!
2117    /// let options = SpanRound::new().largest(Unit::Year).relative(dt1);
2118    /// let span = Span::try_from(duration)?.round(options)?;
2119    /// assert_eq!(span, 1.year().months(3).fieldwise());
2120    ///
2121    /// # Ok::<(), Box<dyn std::error::Error>>(())
2122    /// ```
2123    ///
2124    /// # Example: getting an unsigned duration
2125    ///
2126    /// If you're looking to find the duration between two datetimes as a
2127    /// [`std::time::Duration`], you'll need to use this method to get a
2128    /// [`SignedDuration`] and then convert it to a `std::time::Duration`:
2129    ///
2130    /// ```
2131    /// use std::time::Duration;
2132    ///
2133    /// use jiff::civil::date;
2134    ///
2135    /// let dt1 = date(2024, 7, 1).at(0, 0, 0, 0);
2136    /// let dt2 = date(2024, 8, 1).at(0, 0, 0, 0);
2137    /// let duration = Duration::try_from(dt1.duration_until(dt2))?;
2138    /// assert_eq!(duration, Duration::from_secs(31 * 24 * 60 * 60));
2139    ///
2140    /// // Note that unsigned durations cannot represent all
2141    /// // possible differences! If the duration would be negative,
2142    /// // then the conversion fails:
2143    /// assert!(Duration::try_from(dt2.duration_until(dt1)).is_err());
2144    ///
2145    /// # Ok::<(), Box<dyn std::error::Error>>(())
2146    /// ```
2147    #[inline]
2148    pub fn duration_until(self, other: DateTime) -> SignedDuration {
2149        SignedDuration::datetime_until(self, other)
2150    }
2151
2152    /// This routine is identical to [`DateTime::duration_until`], but the
2153    /// order of the parameters is flipped.
2154    ///
2155    /// # Example
2156    ///
2157    /// ```
2158    /// use jiff::{civil::date, SignedDuration};
2159    ///
2160    /// let earlier = date(2006, 8, 24).at(22, 30, 0, 0);
2161    /// let later = date(2019, 1, 31).at(21, 0, 0, 0);
2162    /// assert_eq!(
2163    ///     later.duration_since(earlier),
2164    ///     SignedDuration::from_hours(4542 * 24)
2165    ///     + SignedDuration::from_hours(22)
2166    ///     + SignedDuration::from_mins(30),
2167    /// );
2168    /// ```
2169    #[inline]
2170    pub fn duration_since(self, other: DateTime) -> SignedDuration {
2171        SignedDuration::datetime_until(other, self)
2172    }
2173
2174    /// Rounds this datetime according to the [`DateTimeRound`] configuration
2175    /// given.
2176    ///
2177    /// The principal option is [`DateTimeRound::smallest`], which allows one
2178    /// to configure the smallest units in the returned datetime. Rounding
2179    /// is what determines whether that unit should keep its current value
2180    /// or whether it should be incremented. Moreover, the amount it should
2181    /// be incremented can be configured via [`DateTimeRound::increment`].
2182    /// Finally, the rounding strategy itself can be configured via
2183    /// [`DateTimeRound::mode`].
2184    ///
2185    /// Note that this routine is generic and accepts anything that
2186    /// implements `Into<DateTimeRound>`. Some notable implementations are:
2187    ///
2188    /// * `From<Unit> for DateTimeRound`, which will automatically create a
2189    /// `DateTimeRound::new().smallest(unit)` from the unit provided.
2190    /// * `From<(Unit, i64)> for DateTimeRound`, which will automatically
2191    /// create a `DateTimeRound::new().smallest(unit).increment(number)` from
2192    /// the unit and increment provided.
2193    ///
2194    /// # Errors
2195    ///
2196    /// This returns an error if the smallest unit configured on the given
2197    /// [`DateTimeRound`] is bigger than days. An error is also returned if
2198    /// the rounding increment is greater than 1 when the units are days.
2199    /// (Currently, rounding to the nearest week, month or year is not
2200    /// supported.)
2201    ///
2202    /// When the smallest unit is less than days, the rounding increment must
2203    /// divide evenly into the next highest unit after the smallest unit
2204    /// configured (and must not be equivalent to it). For example, if the
2205    /// smallest unit is [`Unit::Nanosecond`], then *some* of the valid values
2206    /// for the rounding increment are `1`, `2`, `4`, `5`, `100` and `500`.
2207    /// Namely, any integer that divides evenly into `1,000` nanoseconds since
2208    /// there are `1,000` nanoseconds in the next highest unit (microseconds).
2209    ///
2210    /// This can also return an error in some cases where rounding would
2211    /// require arithmetic that exceeds the maximum datetime value.
2212    ///
2213    /// # Example
2214    ///
2215    /// This is a basic example that demonstrates rounding a datetime to the
2216    /// nearest day. This also demonstrates calling this method with the
2217    /// smallest unit directly, instead of constructing a `DateTimeRound`
2218    /// manually.
2219    ///
2220    /// ```
2221    /// use jiff::{civil::date, Unit};
2222    ///
2223    /// let dt = date(2024, 6, 19).at(15, 0, 0, 0);
2224    /// assert_eq!(dt.round(Unit::Day)?, date(2024, 6, 20).at(0, 0, 0, 0));
2225    /// let dt = date(2024, 6, 19).at(10, 0, 0, 0);
2226    /// assert_eq!(dt.round(Unit::Day)?, date(2024, 6, 19).at(0, 0, 0, 0));
2227    ///
2228    /// # Ok::<(), Box<dyn std::error::Error>>(())
2229    /// ```
2230    ///
2231    /// # Example: changing the rounding mode
2232    ///
2233    /// The default rounding mode is [`RoundMode::HalfExpand`], which
2234    /// breaks ties by rounding away from zero. But other modes like
2235    /// [`RoundMode::Trunc`] can be used too:
2236    ///
2237    /// ```
2238    /// use jiff::{civil::{DateTimeRound, date}, RoundMode, Unit};
2239    ///
2240    /// let dt = date(2024, 6, 19).at(15, 0, 0, 0);
2241    /// assert_eq!(dt.round(Unit::Day)?, date(2024, 6, 20).at(0, 0, 0, 0));
2242    /// // The default will round up to the next day for any time past noon,
2243    /// // but using truncation rounding will always round down.
2244    /// assert_eq!(
2245    ///     dt.round(
2246    ///         DateTimeRound::new().smallest(Unit::Day).mode(RoundMode::Trunc),
2247    ///     )?,
2248    ///     date(2024, 6, 19).at(0, 0, 0, 0),
2249    /// );
2250    ///
2251    /// # Ok::<(), Box<dyn std::error::Error>>(())
2252    /// ```
2253    ///
2254    /// # Example: rounding to the nearest 5 minute increment
2255    ///
2256    /// ```
2257    /// use jiff::{civil::date, Unit};
2258    ///
2259    /// // rounds down
2260    /// let dt = date(2024, 6, 19).at(15, 27, 29, 999_999_999);
2261    /// assert_eq!(
2262    ///     dt.round((Unit::Minute, 5))?,
2263    ///     date(2024, 6, 19).at(15, 25, 0, 0),
2264    /// );
2265    /// // rounds up
2266    /// let dt = date(2024, 6, 19).at(15, 27, 30, 0);
2267    /// assert_eq!(
2268    ///     dt.round((Unit::Minute, 5))?,
2269    ///     date(2024, 6, 19).at(15, 30, 0, 0),
2270    /// );
2271    ///
2272    /// # Ok::<(), Box<dyn std::error::Error>>(())
2273    /// ```
2274    ///
2275    /// # Example: overflow error
2276    ///
2277    /// This example demonstrates that it's possible for this operation to
2278    /// result in an error from datetime arithmetic overflow.
2279    ///
2280    /// ```
2281    /// use jiff::{civil::DateTime, Unit};
2282    ///
2283    /// let dt = DateTime::MAX;
2284    /// assert!(dt.round(Unit::Day).is_err());
2285    /// ```
2286    ///
2287    /// This occurs because rounding to the nearest day for the maximum
2288    /// datetime would result in rounding up to the next day. But the next day
2289    /// is greater than the maximum, and so this returns an error.
2290    ///
2291    /// If one were to use a rounding mode like [`RoundMode::Trunc`] (which
2292    /// will never round up), always set a correct increment and always used
2293    /// units less than or equal to days, then this routine is guaranteed to
2294    /// never fail:
2295    ///
2296    /// ```
2297    /// use jiff::{civil::{DateTime, DateTimeRound, date}, RoundMode, Unit};
2298    ///
2299    /// let round = DateTimeRound::new()
2300    ///     .smallest(Unit::Day)
2301    ///     .mode(RoundMode::Trunc);
2302    /// assert_eq!(
2303    ///     DateTime::MAX.round(round)?,
2304    ///     date(9999, 12, 31).at(0, 0, 0, 0),
2305    /// );
2306    /// assert_eq!(
2307    ///     DateTime::MIN.round(round)?,
2308    ///     date(-9999, 1, 1).at(0, 0, 0, 0),
2309    /// );
2310    ///
2311    /// # Ok::<(), Box<dyn std::error::Error>>(())
2312    /// ```
2313    #[inline]
2314    pub fn round<R: Into<DateTimeRound>>(
2315        self,
2316        options: R,
2317    ) -> Result<DateTime, Error> {
2318        let options: DateTimeRound = options.into();
2319        options.round(self)
2320    }
2321
2322    /// Return an iterator of periodic datetimes determined by the given span.
2323    ///
2324    /// The given span may be negative, in which case, the iterator will move
2325    /// backwards through time. The iterator won't stop until either the span
2326    /// itself overflows, or it would otherwise exceed the minimum or maximum
2327    /// `DateTime` value.
2328    ///
2329    /// # Example: when to check a glucose monitor
2330    ///
2331    /// When my cat had diabetes, my veterinarian installed a glucose monitor
2332    /// and instructed me to scan it about every 5 hours. This example lists
2333    /// all of the times I need to scan it for the 2 days following its
2334    /// installation:
2335    ///
2336    /// ```
2337    /// use jiff::{civil::datetime, ToSpan};
2338    ///
2339    /// let start = datetime(2023, 7, 15, 16, 30, 0, 0);
2340    /// let end = start.checked_add(2.days())?;
2341    /// let mut scan_times = vec![];
2342    /// for dt in start.series(5.hours()).take_while(|&dt| dt <= end) {
2343    ///     scan_times.push(dt);
2344    /// }
2345    /// assert_eq!(scan_times, vec![
2346    ///     datetime(2023, 7, 15, 16, 30, 0, 0),
2347    ///     datetime(2023, 7, 15, 21, 30, 0, 0),
2348    ///     datetime(2023, 7, 16, 2, 30, 0, 0),
2349    ///     datetime(2023, 7, 16, 7, 30, 0, 0),
2350    ///     datetime(2023, 7, 16, 12, 30, 0, 0),
2351    ///     datetime(2023, 7, 16, 17, 30, 0, 0),
2352    ///     datetime(2023, 7, 16, 22, 30, 0, 0),
2353    ///     datetime(2023, 7, 17, 3, 30, 0, 0),
2354    ///     datetime(2023, 7, 17, 8, 30, 0, 0),
2355    ///     datetime(2023, 7, 17, 13, 30, 0, 0),
2356    /// ]);
2357    ///
2358    /// # Ok::<(), Box<dyn std::error::Error>>(())
2359    /// ```
2360    #[inline]
2361    pub fn series(self, period: Span) -> DateTimeSeries {
2362        DateTimeSeries { start: self, period, step: 0 }
2363    }
2364
2365    /// Converts this datetime to a nanosecond timestamp assuming a Zulu time
2366    /// zone offset and where all days are exactly 24 hours long.
2367    #[inline]
2368    fn to_duration(self) -> SignedDuration {
2369        let mut dur = SignedDuration::from_civil_days32(
2370            self.date().to_unix_epoch_day().day(),
2371        );
2372        dur += self.time().to_duration();
2373        dur
2374    }
2375
2376    #[inline]
2377    pub(crate) const fn from_jcore(dt: JDateTime) -> DateTime {
2378        DateTime::from_parts(
2379            Date::from_jcore(dt.date()),
2380            Time::from_jcore(dt.time()),
2381        )
2382    }
2383
2384    #[inline]
2385    pub(crate) const fn to_jcore(&self) -> JDateTime {
2386        JDateTime::from_parts(self.date.to_jcore(), self.time.to_jcore())
2387    }
2388}
2389
2390/// Parsing and formatting using a "printf"-style API.
2391impl DateTime {
2392    /// Parses a civil datetime in `input` matching the given `format`.
2393    ///
2394    /// The format string uses a "printf"-style API where conversion
2395    /// specifiers can be used as place holders to match components of
2396    /// a datetime. For details on the specifiers supported, see the
2397    /// [`fmt::strtime`] module documentation.
2398    ///
2399    /// # Errors
2400    ///
2401    /// This returns an error when parsing failed. This might happen because
2402    /// the format string itself was invalid, or because the input didn't match
2403    /// the format string.
2404    ///
2405    /// This also returns an error if there wasn't sufficient information to
2406    /// construct a civil datetime. For example, if an offset wasn't parsed.
2407    ///
2408    /// # Example
2409    ///
2410    /// This example shows how to parse a civil datetime:
2411    ///
2412    /// ```
2413    /// use jiff::civil::DateTime;
2414    ///
2415    /// let dt = DateTime::strptime("%F %H:%M", "2024-07-14 21:14")?;
2416    /// assert_eq!(dt.to_string(), "2024-07-14T21:14:00");
2417    ///
2418    /// # Ok::<(), Box<dyn std::error::Error>>(())
2419    /// ```
2420    #[inline]
2421    pub fn strptime(
2422        format: impl AsRef<[u8]>,
2423        input: impl AsRef<[u8]>,
2424    ) -> Result<DateTime, Error> {
2425        fmt::strtime::parse(format, input).and_then(|tm| tm.to_datetime())
2426    }
2427
2428    /// Formats this civil datetime according to the given `format`.
2429    ///
2430    /// The format string uses a "printf"-style API where conversion
2431    /// specifiers can be used as place holders to format components of
2432    /// a datetime. For details on the specifiers supported, see the
2433    /// [`fmt::strtime`] module documentation.
2434    ///
2435    /// # Errors and panics
2436    ///
2437    /// This will never error or panic. In particular,
2438    /// [lenient mode](crate::fmt::strtime::Config::lenient) is enabled, which
2439    /// means that all possible strings have some non-error interpretation.
2440    /// Note that because of this, and since Jiff may add new conversion
2441    /// specifiers in the future, the behavior of a format string may change
2442    /// when it would otherwise be invalid.
2443    ///
2444    /// To format in a way that surfaces errors, use either
2445    /// [`fmt::strtime::format`] or [`fmt::strtime::BrokenDownTime::format`].
2446    ///
2447    /// # Example
2448    ///
2449    /// This example shows how to format a civil datetime:
2450    ///
2451    /// ```
2452    /// use jiff::civil::date;
2453    ///
2454    /// let dt = date(2024, 7, 15).at(16, 24, 59, 0);
2455    /// let string = dt.strftime("%A, %B %e, %Y at %H:%M:%S").to_string();
2456    /// assert_eq!(string, "Monday, July 15, 2024 at 16:24:59");
2457    /// ```
2458    ///
2459    /// # Example: errors are silently ignored
2460    ///
2461    /// If the formatting string is malformed in some way, then it is silently
2462    /// ignored. For example, when using an invalid formatting directive:
2463    ///
2464    /// ```
2465    /// use jiff::civil::date;
2466    ///
2467    /// let dt = date(2024, 7, 15).at(16, 24, 59, 0);
2468    /// let string = dt.strftime("%Y %").to_string();
2469    /// assert_eq!(string, "2024 %");
2470    /// ```
2471    ///
2472    /// If one wants to surface errors from a formatting string, use a lower
2473    /// level API:
2474    ///
2475    /// ```
2476    /// use jiff::civil::date;
2477    ///
2478    /// let dt = date(2024, 7, 15).at(16, 24, 59, 0);
2479    /// assert_eq!(
2480    ///     jiff::fmt::strtime::format("%Y %", dt).unwrap_err().to_string(),
2481    ///     "strftime formatting failed: invalid format string, \
2482    ///      expected byte after `%`, but found end of format string",
2483    /// );
2484    /// ```
2485    #[inline]
2486    pub fn strftime<'f, F: 'f + ?Sized + AsRef<[u8]>>(
2487        &self,
2488        format: &'f F,
2489    ) -> fmt::strtime::Display<'f> {
2490        fmt::strtime::Display { fmt: format.as_ref(), tm: (*self).into() }
2491    }
2492}
2493
2494impl Default for DateTime {
2495    #[inline]
2496    fn default() -> DateTime {
2497        DateTime::ZERO
2498    }
2499}
2500
2501/// Converts a `DateTime` into a human readable datetime string.
2502///
2503/// (This `Debug` representation currently emits the same string as the
2504/// `Display` representation, but this is not a guarantee.)
2505///
2506/// Options currently supported:
2507///
2508/// * [`std::fmt::Formatter::precision`] can be set to control the precision
2509/// of the fractional second component.
2510///
2511/// # Example
2512///
2513/// ```
2514/// use jiff::civil::date;
2515///
2516/// let dt = date(2024, 6, 15).at(7, 0, 0, 123_000_000);
2517/// assert_eq!(format!("{dt:.6?}"), "2024-06-15T07:00:00.123000");
2518/// // Precision values greater than 9 are clamped to 9.
2519/// assert_eq!(format!("{dt:.300?}"), "2024-06-15T07:00:00.123000000");
2520/// // A precision of 0 implies the entire fractional
2521/// // component is always truncated.
2522/// assert_eq!(format!("{dt:.0?}"), "2024-06-15T07:00:00");
2523///
2524/// # Ok::<(), Box<dyn std::error::Error>>(())
2525/// ```
2526impl core::fmt::Debug for DateTime {
2527    #[inline]
2528    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
2529        core::fmt::Display::fmt(self, f)
2530    }
2531}
2532
2533/// Converts a `DateTime` into an ISO 8601 compliant string.
2534///
2535/// # Formatting options supported
2536///
2537/// * [`std::fmt::Formatter::precision`] can be set to control the precision
2538/// of the fractional second component. When not set, the minimum precision
2539/// required to losslessly render the value is used.
2540///
2541/// # Example
2542///
2543/// This shows the default rendering:
2544///
2545/// ```
2546/// use jiff::civil::date;
2547///
2548/// // No fractional seconds:
2549/// let dt = date(2024, 6, 15).at(7, 0, 0, 0);
2550/// assert_eq!(format!("{dt}"), "2024-06-15T07:00:00");
2551///
2552/// // With fractional seconds:
2553/// let dt = date(2024, 6, 15).at(7, 0, 0, 123_000_000);
2554/// assert_eq!(format!("{dt}"), "2024-06-15T07:00:00.123");
2555///
2556/// # Ok::<(), Box<dyn std::error::Error>>(())
2557/// ```
2558///
2559/// # Example: setting the precision
2560///
2561/// ```
2562/// use jiff::civil::date;
2563///
2564/// let dt = date(2024, 6, 15).at(7, 0, 0, 123_000_000);
2565/// assert_eq!(format!("{dt:.6}"), "2024-06-15T07:00:00.123000");
2566/// // Precision values greater than 9 are clamped to 9.
2567/// assert_eq!(format!("{dt:.300}"), "2024-06-15T07:00:00.123000000");
2568/// // A precision of 0 implies the entire fractional
2569/// // component is always truncated.
2570/// assert_eq!(format!("{dt:.0}"), "2024-06-15T07:00:00");
2571///
2572/// # Ok::<(), Box<dyn std::error::Error>>(())
2573/// ```
2574impl core::fmt::Display for DateTime {
2575    #[inline]
2576    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
2577        use crate::fmt::StdFmtWrite;
2578
2579        let precision =
2580            f.precision().map(|p| u8::try_from(p).unwrap_or(u8::MAX));
2581        temporal::DateTimePrinter::new()
2582            .precision(precision)
2583            .print_datetime(self, StdFmtWrite(f))
2584            .map_err(|_| core::fmt::Error)
2585    }
2586}
2587
2588impl core::str::FromStr for DateTime {
2589    type Err = Error;
2590
2591    #[inline]
2592    fn from_str(string: &str) -> Result<DateTime, Error> {
2593        DEFAULT_DATETIME_PARSER.parse_datetime(string)
2594    }
2595}
2596
2597/// Converts a [`Date`] to a [`DateTime`] with the time set to midnight.
2598impl From<Date> for DateTime {
2599    #[inline]
2600    fn from(date: Date) -> DateTime {
2601        date.to_datetime(Time::midnight())
2602    }
2603}
2604
2605/// Converts a [`Zoned`] to a [`DateTime`].
2606impl From<Zoned> for DateTime {
2607    #[inline]
2608    fn from(zdt: Zoned) -> DateTime {
2609        zdt.datetime()
2610    }
2611}
2612
2613/// Converts a [`&Zoned`](Zoned) to a [`DateTime`].
2614impl<'a> From<&'a Zoned> for DateTime {
2615    #[inline]
2616    fn from(zdt: &'a Zoned) -> DateTime {
2617        zdt.datetime()
2618    }
2619}
2620
2621/// Adds a span of time to a datetime.
2622///
2623/// This uses checked arithmetic and panics on overflow. To handle overflow
2624/// without panics, use [`DateTime::checked_add`].
2625impl core::ops::Add<Span> for DateTime {
2626    type Output = DateTime;
2627
2628    #[inline]
2629    fn add(self, rhs: Span) -> DateTime {
2630        self.checked_add(rhs).expect("adding span to datetime overflowed")
2631    }
2632}
2633
2634/// Adds a span of time to a datetime in place.
2635///
2636/// This uses checked arithmetic and panics on overflow. To handle overflow
2637/// without panics, use [`DateTime::checked_add`].
2638impl core::ops::AddAssign<Span> for DateTime {
2639    #[inline]
2640    fn add_assign(&mut self, rhs: Span) {
2641        *self = *self + rhs
2642    }
2643}
2644
2645/// Subtracts a span of time from a datetime.
2646///
2647/// This uses checked arithmetic and panics on overflow. To handle overflow
2648/// without panics, use [`DateTime::checked_sub`].
2649impl core::ops::Sub<Span> for DateTime {
2650    type Output = DateTime;
2651
2652    #[inline]
2653    fn sub(self, rhs: Span) -> DateTime {
2654        self.checked_sub(rhs)
2655            .expect("subtracting span from datetime overflowed")
2656    }
2657}
2658
2659/// Subtracts a span of time from a datetime in place.
2660///
2661/// This uses checked arithmetic and panics on overflow. To handle overflow
2662/// without panics, use [`DateTime::checked_sub`].
2663impl core::ops::SubAssign<Span> for DateTime {
2664    #[inline]
2665    fn sub_assign(&mut self, rhs: Span) {
2666        *self = *self - rhs
2667    }
2668}
2669
2670/// Computes the span of time between two datetimes.
2671///
2672/// This will return a negative span when the datetime being subtracted is
2673/// greater.
2674///
2675/// Since this uses the default configuration for calculating a span between
2676/// two datetimes (no rounding and largest units is days), this will never
2677/// panic or fail in any way. It is guaranteed that the largest non-zero
2678/// unit in the `Span` returned will be days.
2679///
2680/// To configure the largest unit or enable rounding, use [`DateTime::since`].
2681///
2682/// If you need a [`SignedDuration`] representing the span between two civil
2683/// datetimes, then use [`DateTime::duration_since`].
2684impl core::ops::Sub for DateTime {
2685    type Output = Span;
2686
2687    #[inline]
2688    fn sub(self, rhs: DateTime) -> Span {
2689        self.since(rhs).expect("since never fails when given DateTime")
2690    }
2691}
2692
2693/// Adds a signed duration of time to a datetime.
2694///
2695/// This uses checked arithmetic and panics on overflow. To handle overflow
2696/// without panics, use [`DateTime::checked_add`].
2697impl core::ops::Add<SignedDuration> for DateTime {
2698    type Output = DateTime;
2699
2700    #[inline]
2701    fn add(self, rhs: SignedDuration) -> DateTime {
2702        self.checked_add(rhs)
2703            .expect("adding signed duration to datetime overflowed")
2704    }
2705}
2706
2707/// Adds a signed duration of time to a datetime in place.
2708///
2709/// This uses checked arithmetic and panics on overflow. To handle overflow
2710/// without panics, use [`DateTime::checked_add`].
2711impl core::ops::AddAssign<SignedDuration> for DateTime {
2712    #[inline]
2713    fn add_assign(&mut self, rhs: SignedDuration) {
2714        *self = *self + rhs
2715    }
2716}
2717
2718/// Subtracts a signed duration of time from a datetime.
2719///
2720/// This uses checked arithmetic and panics on overflow. To handle overflow
2721/// without panics, use [`DateTime::checked_sub`].
2722impl core::ops::Sub<SignedDuration> for DateTime {
2723    type Output = DateTime;
2724
2725    #[inline]
2726    fn sub(self, rhs: SignedDuration) -> DateTime {
2727        self.checked_sub(rhs)
2728            .expect("subtracting signed duration from datetime overflowed")
2729    }
2730}
2731
2732/// Subtracts a signed duration of time from a datetime in place.
2733///
2734/// This uses checked arithmetic and panics on overflow. To handle overflow
2735/// without panics, use [`DateTime::checked_sub`].
2736impl core::ops::SubAssign<SignedDuration> for DateTime {
2737    #[inline]
2738    fn sub_assign(&mut self, rhs: SignedDuration) {
2739        *self = *self - rhs
2740    }
2741}
2742
2743/// Adds an unsigned duration of time to a datetime.
2744///
2745/// This uses checked arithmetic and panics on overflow. To handle overflow
2746/// without panics, use [`DateTime::checked_add`].
2747impl core::ops::Add<UnsignedDuration> for DateTime {
2748    type Output = DateTime;
2749
2750    #[inline]
2751    fn add(self, rhs: UnsignedDuration) -> DateTime {
2752        self.checked_add(rhs)
2753            .expect("adding unsigned duration to datetime overflowed")
2754    }
2755}
2756
2757/// Adds an unsigned duration of time to a datetime in place.
2758///
2759/// This uses checked arithmetic and panics on overflow. To handle overflow
2760/// without panics, use [`DateTime::checked_add`].
2761impl core::ops::AddAssign<UnsignedDuration> for DateTime {
2762    #[inline]
2763    fn add_assign(&mut self, rhs: UnsignedDuration) {
2764        *self = *self + rhs
2765    }
2766}
2767
2768/// Subtracts an unsigned duration of time from a datetime.
2769///
2770/// This uses checked arithmetic and panics on overflow. To handle overflow
2771/// without panics, use [`DateTime::checked_sub`].
2772impl core::ops::Sub<UnsignedDuration> for DateTime {
2773    type Output = DateTime;
2774
2775    #[inline]
2776    fn sub(self, rhs: UnsignedDuration) -> DateTime {
2777        self.checked_sub(rhs)
2778            .expect("subtracting unsigned duration from datetime overflowed")
2779    }
2780}
2781
2782/// Subtracts an unsigned duration of time from a datetime in place.
2783///
2784/// This uses checked arithmetic and panics on overflow. To handle overflow
2785/// without panics, use [`DateTime::checked_sub`].
2786impl core::ops::SubAssign<UnsignedDuration> for DateTime {
2787    #[inline]
2788    fn sub_assign(&mut self, rhs: UnsignedDuration) {
2789        *self = *self - rhs
2790    }
2791}
2792
2793#[cfg(feature = "defmt")]
2794impl defmt::Format for DateTime {
2795    fn format(&self, f: defmt::Formatter) {
2796        use crate::fmt::{temporal::DEFAULT_DATETIME_PRINTER, DefmtWrite};
2797
2798        defmt::unwrap!(
2799            DEFAULT_DATETIME_PRINTER.print_datetime(self, DefmtWrite(f))
2800        );
2801    }
2802}
2803
2804#[cfg(feature = "serde")]
2805impl serde_core::Serialize for DateTime {
2806    #[inline]
2807    fn serialize<S: serde_core::Serializer>(
2808        &self,
2809        serializer: S,
2810    ) -> Result<S::Ok, S::Error> {
2811        serializer.collect_str(self)
2812    }
2813}
2814
2815#[cfg(feature = "serde")]
2816impl<'de> serde_core::Deserialize<'de> for DateTime {
2817    #[inline]
2818    fn deserialize<D: serde_core::Deserializer<'de>>(
2819        deserializer: D,
2820    ) -> Result<DateTime, D::Error> {
2821        use serde_core::de;
2822
2823        struct DateTimeVisitor;
2824
2825        impl<'de> de::Visitor<'de> for DateTimeVisitor {
2826            type Value = DateTime;
2827
2828            fn expecting(
2829                &self,
2830                f: &mut core::fmt::Formatter,
2831            ) -> core::fmt::Result {
2832                f.write_str("a datetime string")
2833            }
2834
2835            #[inline]
2836            fn visit_bytes<E: de::Error>(
2837                self,
2838                value: &[u8],
2839            ) -> Result<DateTime, E> {
2840                DEFAULT_DATETIME_PARSER
2841                    .parse_datetime(value)
2842                    .map_err(de::Error::custom)
2843            }
2844
2845            #[inline]
2846            fn visit_str<E: de::Error>(
2847                self,
2848                value: &str,
2849            ) -> Result<DateTime, E> {
2850                self.visit_bytes(value.as_bytes())
2851            }
2852        }
2853
2854        deserializer.deserialize_str(DateTimeVisitor)
2855    }
2856}
2857
2858#[cfg(test)]
2859impl quickcheck::Arbitrary for DateTime {
2860    fn arbitrary(g: &mut quickcheck::Gen) -> DateTime {
2861        let date = Date::arbitrary(g);
2862        let time = Time::arbitrary(g);
2863        DateTime::from_parts(date, time)
2864    }
2865
2866    fn shrink(&self) -> alloc::boxed::Box<dyn Iterator<Item = DateTime>> {
2867        alloc::boxed::Box::new(
2868            (self.date(), self.time())
2869                .shrink()
2870                .map(|(date, time)| DateTime::from_parts(date, time)),
2871        )
2872    }
2873}
2874
2875/// An iterator over periodic datetimes, created by [`DateTime::series`].
2876///
2877/// It is exhausted when the next value would exceed the limits of a [`Span`]
2878/// or [`DateTime`] value.
2879///
2880/// This iterator is created by [`DateTime::series`].
2881#[derive(Clone, Debug)]
2882pub struct DateTimeSeries {
2883    start: DateTime,
2884    period: Span,
2885    step: i64,
2886}
2887
2888impl Iterator for DateTimeSeries {
2889    type Item = DateTime;
2890
2891    #[inline]
2892    fn next(&mut self) -> Option<DateTime> {
2893        let span = self.period.checked_mul(self.step).ok()?;
2894        self.step = self.step.checked_add(1)?;
2895        let date = self.start.checked_add(span).ok()?;
2896        Some(date)
2897    }
2898}
2899
2900impl core::iter::FusedIterator for DateTimeSeries {}
2901
2902/// Options for [`DateTime::checked_add`] and [`DateTime::checked_sub`].
2903///
2904/// This type provides a way to ergonomically add one of a few different
2905/// duration types to a [`DateTime`].
2906///
2907/// The main way to construct values of this type is with its `From` trait
2908/// implementations:
2909///
2910/// * `From<Span> for DateTimeArithmetic` adds (or subtracts) the given span to
2911/// the receiver datetime.
2912/// * `From<SignedDuration> for DateTimeArithmetic` adds (or subtracts)
2913/// the given signed duration to the receiver datetime.
2914/// * `From<std::time::Duration> for DateTimeArithmetic` adds (or subtracts)
2915/// the given unsigned duration to the receiver datetime.
2916///
2917/// # Example
2918///
2919/// ```
2920/// use std::time::Duration;
2921///
2922/// use jiff::{civil::date, SignedDuration, ToSpan};
2923///
2924/// let dt = date(2024, 2, 29).at(0, 0, 0, 0);
2925/// assert_eq!(
2926///     dt.checked_add(1.year())?,
2927///     date(2025, 2, 28).at(0, 0, 0, 0),
2928/// );
2929/// assert_eq!(
2930///     dt.checked_add(SignedDuration::from_hours(24))?,
2931///     date(2024, 3, 1).at(0, 0, 0, 0),
2932/// );
2933/// assert_eq!(
2934///     dt.checked_add(Duration::from_secs(24 * 60 * 60))?,
2935///     date(2024, 3, 1).at(0, 0, 0, 0),
2936/// );
2937///
2938/// # Ok::<(), Box<dyn std::error::Error>>(())
2939/// ```
2940#[derive(Clone, Copy, Debug)]
2941pub struct DateTimeArithmetic {
2942    duration: Duration,
2943}
2944
2945impl DateTimeArithmetic {
2946    #[inline]
2947    fn checked_add(self, dt: DateTime) -> Result<DateTime, Error> {
2948        match self.duration.to_signed()? {
2949            SDuration::Span(span) => dt.checked_add_span(span),
2950            SDuration::Absolute(sdur) => dt.checked_add_duration(sdur),
2951        }
2952    }
2953
2954    #[inline]
2955    fn checked_neg(self) -> Result<DateTimeArithmetic, Error> {
2956        let duration = self.duration.checked_neg()?;
2957        Ok(DateTimeArithmetic { duration })
2958    }
2959
2960    #[inline]
2961    fn is_negative(&self) -> bool {
2962        self.duration.is_negative()
2963    }
2964}
2965
2966impl From<Span> for DateTimeArithmetic {
2967    fn from(span: Span) -> DateTimeArithmetic {
2968        let duration = Duration::from(span);
2969        DateTimeArithmetic { duration }
2970    }
2971}
2972
2973impl From<SignedDuration> for DateTimeArithmetic {
2974    fn from(sdur: SignedDuration) -> DateTimeArithmetic {
2975        let duration = Duration::from(sdur);
2976        DateTimeArithmetic { duration }
2977    }
2978}
2979
2980impl From<UnsignedDuration> for DateTimeArithmetic {
2981    fn from(udur: UnsignedDuration) -> DateTimeArithmetic {
2982        let duration = Duration::from(udur);
2983        DateTimeArithmetic { duration }
2984    }
2985}
2986
2987impl<'a> From<&'a Span> for DateTimeArithmetic {
2988    fn from(span: &'a Span) -> DateTimeArithmetic {
2989        DateTimeArithmetic::from(*span)
2990    }
2991}
2992
2993impl<'a> From<&'a SignedDuration> for DateTimeArithmetic {
2994    fn from(sdur: &'a SignedDuration) -> DateTimeArithmetic {
2995        DateTimeArithmetic::from(*sdur)
2996    }
2997}
2998
2999impl<'a> From<&'a UnsignedDuration> for DateTimeArithmetic {
3000    fn from(udur: &'a UnsignedDuration) -> DateTimeArithmetic {
3001        DateTimeArithmetic::from(*udur)
3002    }
3003}
3004
3005/// Options for [`DateTime::since`] and [`DateTime::until`].
3006///
3007/// This type provides a way to configure the calculation of
3008/// spans between two [`DateTime`] values. In particular, both
3009/// `DateTime::since` and `DateTime::until` accept anything that implements
3010/// `Into<DateTimeDifference>`. There are a few key trait implementations that
3011/// make this convenient:
3012///
3013/// * `From<DateTime> for DateTimeDifference` will construct a configuration
3014/// consisting of just the datetime. So for example, `dt1.since(dt2)` returns
3015/// the span from `dt2` to `dt1`.
3016/// * `From<Date> for DateTimeDifference` will construct a configuration
3017/// consisting of just the datetime built from the date given at midnight on
3018/// that day.
3019/// * `From<(Unit, DateTime)>` is a convenient way to specify the largest units
3020/// that should be present on the span returned. By default, the largest units
3021/// are days. Using this trait implementation is equivalent to
3022/// `DateTimeDifference::new(datetime).largest(unit)`.
3023/// * `From<(Unit, Date)>` is like the one above, but with the time component
3024/// fixed to midnight.
3025///
3026/// One can also provide a `DateTimeDifference` value directly. Doing so
3027/// is necessary to use the rounding features of calculating a span. For
3028/// example, setting the smallest unit (defaults to [`Unit::Nanosecond`]), the
3029/// rounding mode (defaults to [`RoundMode::Trunc`]) and the rounding increment
3030/// (defaults to `1`). The defaults are selected such that no rounding occurs.
3031///
3032/// Rounding a span as part of calculating it is provided as a convenience.
3033/// Callers may choose to round the span as a distinct step via
3034/// [`Span::round`], but callers may need to provide a reference date
3035/// for rounding larger units. By coupling rounding with routines like
3036/// [`DateTime::since`], the reference date can be set automatically based on
3037/// the input to `DateTime::since`.
3038///
3039/// # Example
3040///
3041/// This example shows how to round a span between two datetimes to the nearest
3042/// half-hour, with ties breaking away from zero.
3043///
3044/// ```
3045/// use jiff::{civil::{DateTime, DateTimeDifference}, RoundMode, ToSpan, Unit};
3046///
3047/// let dt1 = "2024-03-15 08:14:00.123456789".parse::<DateTime>()?;
3048/// let dt2 = "2030-03-22 15:00".parse::<DateTime>()?;
3049/// let span = dt1.until(
3050///     DateTimeDifference::new(dt2)
3051///         .smallest(Unit::Minute)
3052///         .largest(Unit::Year)
3053///         .mode(RoundMode::HalfExpand)
3054///         .increment(30),
3055/// )?;
3056/// assert_eq!(span, 6.years().days(7).hours(7).fieldwise());
3057///
3058/// # Ok::<(), Box<dyn std::error::Error>>(())
3059/// ```
3060#[derive(Clone, Copy, Debug)]
3061pub struct DateTimeDifference {
3062    datetime: DateTime,
3063    round: SpanRound<'static>,
3064}
3065
3066impl DateTimeDifference {
3067    /// Create a new default configuration for computing the span between the
3068    /// given datetime and some other datetime (specified as the receiver in
3069    /// [`DateTime::since`] or [`DateTime::until`]).
3070    #[inline]
3071    pub fn new(datetime: DateTime) -> DateTimeDifference {
3072        // We use truncation rounding by default since it seems that's
3073        // what is generally expected when computing the difference between
3074        // datetimes.
3075        //
3076        // See: https://github.com/tc39/proposal-temporal/issues/1122
3077        let round = SpanRound::new().mode(RoundMode::Trunc);
3078        DateTimeDifference { datetime, round }
3079    }
3080
3081    /// Set the smallest units allowed in the span returned.
3082    ///
3083    /// When a largest unit is not specified and the smallest unit is days
3084    /// or greater, then the largest unit is automatically set to be equal to
3085    /// the smallest unit.
3086    ///
3087    /// # Errors
3088    ///
3089    /// The smallest units must be no greater than the largest units. If this
3090    /// is violated, then computing a span with this configuration will result
3091    /// in an error.
3092    ///
3093    /// # Example
3094    ///
3095    /// This shows how to round a span between two datetimes to the nearest
3096    /// number of weeks.
3097    ///
3098    /// ```
3099    /// use jiff::{
3100    ///     civil::{DateTime, DateTimeDifference},
3101    ///     RoundMode, ToSpan, Unit,
3102    /// };
3103    ///
3104    /// let dt1 = "2024-03-15 08:14".parse::<DateTime>()?;
3105    /// let dt2 = "2030-11-22 08:30".parse::<DateTime>()?;
3106    /// let span = dt1.until(
3107    ///     DateTimeDifference::new(dt2)
3108    ///         .smallest(Unit::Week)
3109    ///         .largest(Unit::Week)
3110    ///         .mode(RoundMode::HalfExpand),
3111    /// )?;
3112    /// assert_eq!(span, 349.weeks().fieldwise());
3113    ///
3114    /// # Ok::<(), Box<dyn std::error::Error>>(())
3115    /// ```
3116    #[inline]
3117    pub fn smallest(self, unit: Unit) -> DateTimeDifference {
3118        DateTimeDifference { round: self.round.smallest(unit), ..self }
3119    }
3120
3121    /// Set the largest units allowed in the span returned.
3122    ///
3123    /// When a largest unit is not specified and the smallest unit is days
3124    /// or greater, then the largest unit is automatically set to be equal to
3125    /// the smallest unit. Otherwise, when the largest unit is not specified,
3126    /// it is set to days.
3127    ///
3128    /// Once a largest unit is set, there is no way to change this rounding
3129    /// configuration back to using the "automatic" default. Instead, callers
3130    /// must create a new configuration.
3131    ///
3132    /// # Errors
3133    ///
3134    /// The largest units, when set, must be at least as big as the smallest
3135    /// units (which defaults to [`Unit::Nanosecond`]). If this is violated,
3136    /// then computing a span with this configuration will result in an error.
3137    ///
3138    /// # Example
3139    ///
3140    /// This shows how to round a span between two datetimes to units no
3141    /// bigger than seconds.
3142    ///
3143    /// ```
3144    /// use jiff::{civil::{DateTime, DateTimeDifference}, ToSpan, Unit};
3145    ///
3146    /// let dt1 = "2024-03-15 08:14".parse::<DateTime>()?;
3147    /// let dt2 = "2030-11-22 08:30".parse::<DateTime>()?;
3148    /// let span = dt1.until(
3149    ///     DateTimeDifference::new(dt2).largest(Unit::Second),
3150    /// )?;
3151    /// assert_eq!(span, 211076160.seconds().fieldwise());
3152    ///
3153    /// # Ok::<(), Box<dyn std::error::Error>>(())
3154    /// ```
3155    #[inline]
3156    pub fn largest(self, unit: Unit) -> DateTimeDifference {
3157        DateTimeDifference { round: self.round.largest(unit), ..self }
3158    }
3159
3160    /// Set the rounding mode.
3161    ///
3162    /// This defaults to [`RoundMode::Trunc`] since it's plausible that
3163    /// rounding "up" in the context of computing the span between
3164    /// two datetimes could be surprising in a number of cases. The
3165    /// [`RoundMode::HalfExpand`] mode corresponds to typical rounding you
3166    /// might have learned about in school. But a variety of other rounding
3167    /// modes exist.
3168    ///
3169    /// # Example
3170    ///
3171    /// This shows how to always round "up" towards positive infinity.
3172    ///
3173    /// ```
3174    /// use jiff::{
3175    ///     civil::{DateTime, DateTimeDifference},
3176    ///     RoundMode, ToSpan, Unit,
3177    /// };
3178    ///
3179    /// let dt1 = "2024-03-15 08:10".parse::<DateTime>()?;
3180    /// let dt2 = "2024-03-15 08:11".parse::<DateTime>()?;
3181    /// let span = dt1.until(
3182    ///     DateTimeDifference::new(dt2)
3183    ///         .smallest(Unit::Hour)
3184    ///         .mode(RoundMode::Ceil),
3185    /// )?;
3186    /// // Only one minute elapsed, but we asked to always round up!
3187    /// assert_eq!(span, 1.hour().fieldwise());
3188    ///
3189    /// // Since `Ceil` always rounds toward positive infinity, the behavior
3190    /// // flips for a negative span.
3191    /// let span = dt1.since(
3192    ///     DateTimeDifference::new(dt2)
3193    ///         .smallest(Unit::Hour)
3194    ///         .mode(RoundMode::Ceil),
3195    /// )?;
3196    /// assert_eq!(span, 0.hour().fieldwise());
3197    ///
3198    /// # Ok::<(), Box<dyn std::error::Error>>(())
3199    /// ```
3200    #[inline]
3201    pub fn mode(self, mode: RoundMode) -> DateTimeDifference {
3202        DateTimeDifference { round: self.round.mode(mode), ..self }
3203    }
3204
3205    /// Set the rounding increment for the smallest unit.
3206    ///
3207    /// The default value is `1`. Other values permit rounding the smallest
3208    /// unit to the nearest integer increment specified. For example, if the
3209    /// smallest unit is set to [`Unit::Minute`], then a rounding increment of
3210    /// `30` would result in rounding in increments of a half hour. That is,
3211    /// the only minute value that could result would be `0` or `30`.
3212    ///
3213    /// # Errors
3214    ///
3215    /// When the smallest unit is less than days, the rounding increment must
3216    /// divide evenly into the next highest unit after the smallest unit
3217    /// configured (and must not be equivalent to it). For example, if the
3218    /// smallest unit is [`Unit::Nanosecond`], then *some* of the valid values
3219    /// for the rounding increment are `1`, `2`, `4`, `5`, `100` and `500`.
3220    /// Namely, any integer that divides evenly into `1,000` nanoseconds since
3221    /// there are `1,000` nanoseconds in the next highest unit (microseconds).
3222    ///
3223    /// In all cases, the increment must be greater than zero and less than
3224    /// or equal to `1_000_000_000`.
3225    ///
3226    /// The error will occur when computing the span, and not when setting
3227    /// the increment here.
3228    ///
3229    /// # Example
3230    ///
3231    /// This shows how to round the span between two datetimes to the nearest
3232    /// 5 minute increment.
3233    ///
3234    /// ```
3235    /// use jiff::{
3236    ///     civil::{DateTime, DateTimeDifference},
3237    ///     RoundMode, ToSpan, Unit,
3238    /// };
3239    ///
3240    /// let dt1 = "2024-03-15 08:19".parse::<DateTime>()?;
3241    /// let dt2 = "2024-03-15 12:52".parse::<DateTime>()?;
3242    /// let span = dt1.until(
3243    ///     DateTimeDifference::new(dt2)
3244    ///         .smallest(Unit::Minute)
3245    ///         .increment(5)
3246    ///         .mode(RoundMode::HalfExpand),
3247    /// )?;
3248    /// assert_eq!(span, 4.hour().minutes(35).fieldwise());
3249    ///
3250    /// # Ok::<(), Box<dyn std::error::Error>>(())
3251    /// ```
3252    #[inline]
3253    pub fn increment(self, increment: i64) -> DateTimeDifference {
3254        DateTimeDifference { round: self.round.increment(increment), ..self }
3255    }
3256
3257    /// Returns true if and only if this configuration could change the span
3258    /// via rounding.
3259    #[inline]
3260    fn rounding_may_change_span(&self) -> bool {
3261        self.round.rounding_may_change_span()
3262    }
3263
3264    /// Returns the span of time from `dt1` to the datetime in this
3265    /// configuration. The biggest units allowed are determined by the
3266    /// `smallest` and `largest` settings, but defaults to `Unit::Day`.
3267    #[inline]
3268    fn until_with_largest_unit(&self, dt1: DateTime) -> Result<Span, Error> {
3269        let dt2 = self.datetime;
3270        let largest = self
3271            .round
3272            .get_largest()
3273            .unwrap_or_else(|| self.round.get_smallest().max(Unit::Day));
3274        if largest <= Unit::Day {
3275            let diff = dt2.to_duration() - dt1.to_duration();
3276            // Note that this can fail! If largest unit is nanoseconds and the
3277            // datetimes are far enough apart, a single i64 won't be able to
3278            // represent the time difference.
3279            //
3280            // This is only true for nanoseconds. A single i64 in units of
3281            // microseconds can represent the interval between all valid
3282            // datetimes.
3283            return Span::from_invariant_duration(largest, diff);
3284        }
3285
3286        let (d1, mut d2) = (dt1.date(), dt2.date());
3287        let (t1, t2) = (dt1.time(), dt2.time());
3288        let sign = Sign::from_ordinals(d2, d1);
3289        let mut time_diff = t1.until_nanoseconds(t2);
3290        if Sign::from(time_diff) == -sign {
3291            // These unwraps will always succeed, but the argument for why is
3292            // subtle. The key here is that the only way, e.g., d2.tomorrow()
3293            // can fail is when d2 is the max date. But, if d2 is the max date,
3294            // then it's impossible for `sign < 0` since the max date is at
3295            // least as big as every other date. And thus, d2.tomorrow() is
3296            // never reached in cases where it would fail.
3297            if sign.is_positive() {
3298                d2 = d2.yesterday().unwrap();
3299            } else if sign.is_negative() {
3300                d2 = d2.tomorrow().unwrap();
3301            }
3302            time_diff += c::NANOS_PER_CIVIL_DAY * sign;
3303        }
3304        let date_span = d1.until((largest, d2))?;
3305        // Unlike in the <=Unit::Day case, this always succeeds because
3306        // every unit except for nanoseconds (which is not used here) can
3307        // represent all possible spans of time between any two civil
3308        // datetimes.
3309        let time_span = Span::from_invariant_duration(
3310            largest,
3311            SignedDuration::from_nanos(time_diff),
3312        )
3313        .expect("difference between time always fits in span");
3314        Ok(time_span
3315            .years(date_span.get_years())
3316            .months(date_span.get_months())
3317            .weeks(date_span.get_weeks())
3318            .days(date_span.get_days()))
3319    }
3320}
3321
3322impl From<DateTime> for DateTimeDifference {
3323    #[inline]
3324    fn from(dt: DateTime) -> DateTimeDifference {
3325        DateTimeDifference::new(dt)
3326    }
3327}
3328
3329impl From<Date> for DateTimeDifference {
3330    #[inline]
3331    fn from(date: Date) -> DateTimeDifference {
3332        DateTimeDifference::from(DateTime::from(date))
3333    }
3334}
3335
3336impl From<Zoned> for DateTimeDifference {
3337    #[inline]
3338    fn from(zdt: Zoned) -> DateTimeDifference {
3339        DateTimeDifference::from(DateTime::from(zdt))
3340    }
3341}
3342
3343impl<'a> From<&'a Zoned> for DateTimeDifference {
3344    #[inline]
3345    fn from(zdt: &'a Zoned) -> DateTimeDifference {
3346        DateTimeDifference::from(zdt.datetime())
3347    }
3348}
3349
3350impl From<(Unit, DateTime)> for DateTimeDifference {
3351    #[inline]
3352    fn from((largest, dt): (Unit, DateTime)) -> DateTimeDifference {
3353        DateTimeDifference::from(dt).largest(largest)
3354    }
3355}
3356
3357impl From<(Unit, Date)> for DateTimeDifference {
3358    #[inline]
3359    fn from((largest, date): (Unit, Date)) -> DateTimeDifference {
3360        DateTimeDifference::from(date).largest(largest)
3361    }
3362}
3363
3364impl From<(Unit, Zoned)> for DateTimeDifference {
3365    #[inline]
3366    fn from((largest, zdt): (Unit, Zoned)) -> DateTimeDifference {
3367        DateTimeDifference::from((largest, DateTime::from(zdt)))
3368    }
3369}
3370
3371impl<'a> From<(Unit, &'a Zoned)> for DateTimeDifference {
3372    #[inline]
3373    fn from((largest, zdt): (Unit, &'a Zoned)) -> DateTimeDifference {
3374        DateTimeDifference::from((largest, zdt.datetime()))
3375    }
3376}
3377
3378/// Options for [`DateTime::round`].
3379///
3380/// This type provides a way to configure the rounding of a civil datetime. In
3381/// particular, `DateTime::round` accepts anything that implements the
3382/// `Into<DateTimeRound>` trait. There are some trait implementations that
3383/// therefore make calling `DateTime::round` in some common cases more
3384/// ergonomic:
3385///
3386/// * `From<Unit> for DateTimeRound` will construct a rounding
3387/// configuration that rounds to the unit given. Specifically,
3388/// `DateTimeRound::new().smallest(unit)`.
3389/// * `From<(Unit, i64)> for DateTimeRound` is like the one above, but also
3390/// specifies the rounding increment for [`DateTimeRound::increment`].
3391///
3392/// Note that in the default configuration, no rounding occurs.
3393///
3394/// # Example
3395///
3396/// This example shows how to round a datetime to the nearest second:
3397///
3398/// ```
3399/// use jiff::{civil::{DateTime, date}, Unit};
3400///
3401/// let dt: DateTime = "2024-06-20 16:24:59.5".parse()?;
3402/// assert_eq!(
3403///     dt.round(Unit::Second)?,
3404///     // The second rounds up and causes minutes to increase.
3405///     date(2024, 6, 20).at(16, 25, 0, 0),
3406/// );
3407///
3408/// # Ok::<(), Box<dyn std::error::Error>>(())
3409/// ```
3410///
3411/// The above makes use of the fact that `Unit` implements
3412/// `Into<DateTimeRound>`. If you want to change the rounding mode to, say,
3413/// truncation, then you'll need to construct a `DateTimeRound` explicitly
3414/// since there are no convenience `Into` trait implementations for
3415/// [`RoundMode`].
3416///
3417/// ```
3418/// use jiff::{civil::{DateTime, DateTimeRound, date}, RoundMode, Unit};
3419///
3420/// let dt: DateTime = "2024-06-20 16:24:59.5".parse()?;
3421/// assert_eq!(
3422///     dt.round(
3423///         DateTimeRound::new().smallest(Unit::Second).mode(RoundMode::Trunc),
3424///     )?,
3425///     // The second just gets truncated as if it wasn't there.
3426///     date(2024, 6, 20).at(16, 24, 59, 0),
3427/// );
3428///
3429/// # Ok::<(), Box<dyn std::error::Error>>(())
3430/// ```
3431#[derive(Clone, Copy, Debug)]
3432pub struct DateTimeRound {
3433    smallest: Unit,
3434    mode: RoundMode,
3435    increment: i64,
3436}
3437
3438impl DateTimeRound {
3439    /// Create a new default configuration for rounding a [`DateTime`].
3440    #[inline]
3441    pub fn new() -> DateTimeRound {
3442        DateTimeRound {
3443            smallest: Unit::Nanosecond,
3444            mode: RoundMode::HalfExpand,
3445            increment: 1,
3446        }
3447    }
3448
3449    /// Set the smallest units allowed in the datetime returned after rounding.
3450    ///
3451    /// Any units below the smallest configured unit will be used, along with
3452    /// the rounding increment and rounding mode, to determine the value of the
3453    /// smallest unit. For example, when rounding `2024-06-20T03:25:30` to the
3454    /// nearest minute, the `30` second unit will result in rounding the minute
3455    /// unit of `25` up to `26` and zeroing out everything below minutes.
3456    ///
3457    /// This defaults to [`Unit::Nanosecond`].
3458    ///
3459    /// # Errors
3460    ///
3461    /// The smallest units must be no greater than [`Unit::Day`]. And when the
3462    /// smallest unit is `Unit::Day`, the rounding increment must be equal to
3463    /// `1`. Otherwise an error will be returned from [`DateTime::round`].
3464    ///
3465    /// # Example
3466    ///
3467    /// ```
3468    /// use jiff::{civil::{DateTimeRound, date}, Unit};
3469    ///
3470    /// let dt = date(2024, 6, 20).at(3, 25, 30, 0);
3471    /// assert_eq!(
3472    ///     dt.round(DateTimeRound::new().smallest(Unit::Minute))?,
3473    ///     date(2024, 6, 20).at(3, 26, 0, 0),
3474    /// );
3475    /// // Or, utilize the `From<Unit> for DateTimeRound` impl:
3476    /// assert_eq!(
3477    ///     dt.round(Unit::Minute)?,
3478    ///     date(2024, 6, 20).at(3, 26, 0, 0),
3479    /// );
3480    ///
3481    /// # Ok::<(), Box<dyn std::error::Error>>(())
3482    /// ```
3483    #[inline]
3484    pub fn smallest(self, unit: Unit) -> DateTimeRound {
3485        DateTimeRound { smallest: unit, ..self }
3486    }
3487
3488    /// Set the rounding mode.
3489    ///
3490    /// This defaults to [`RoundMode::HalfExpand`], which rounds away from
3491    /// zero. It matches the kind of rounding you might have been taught in
3492    /// school.
3493    ///
3494    /// # Example
3495    ///
3496    /// This shows how to always round datetimes up towards positive infinity.
3497    ///
3498    /// ```
3499    /// use jiff::{civil::{DateTime, DateTimeRound, date}, RoundMode, Unit};
3500    ///
3501    /// let dt: DateTime = "2024-06-20 03:25:01".parse()?;
3502    /// assert_eq!(
3503    ///     dt.round(
3504    ///         DateTimeRound::new()
3505    ///             .smallest(Unit::Minute)
3506    ///             .mode(RoundMode::Ceil),
3507    ///     )?,
3508    ///     date(2024, 6, 20).at(3, 26, 0, 0),
3509    /// );
3510    ///
3511    /// # Ok::<(), Box<dyn std::error::Error>>(())
3512    /// ```
3513    #[inline]
3514    pub fn mode(self, mode: RoundMode) -> DateTimeRound {
3515        DateTimeRound { mode, ..self }
3516    }
3517
3518    /// Set the rounding increment for the smallest unit.
3519    ///
3520    /// The default value is `1`. Other values permit rounding the smallest
3521    /// unit to the nearest integer increment specified. For example, if the
3522    /// smallest unit is set to [`Unit::Minute`], then a rounding increment of
3523    /// `30` would result in rounding in increments of a half hour. That is,
3524    /// the only minute value that could result would be `0` or `30`.
3525    ///
3526    /// # Errors
3527    ///
3528    /// When the smallest unit is `Unit::Day`, then the rounding increment must
3529    /// be `1` or else [`DateTime::round`] will return an error.
3530    ///
3531    /// For other units, the rounding increment must divide evenly into the
3532    /// next highest unit above the smallest unit set. The rounding increment
3533    /// must also not be equal to the next highest unit. For example, if the
3534    /// smallest unit is [`Unit::Nanosecond`], then *some* of the valid values
3535    /// for the rounding increment are `1`, `2`, `4`, `5`, `100` and `500`.
3536    /// Namely, any integer that divides evenly into `1,000` nanoseconds since
3537    /// there are `1,000` nanoseconds in the next highest unit (microseconds).
3538    ///
3539    /// In all cases, the increment must be greater than zero and less than or
3540    /// equal to `1_000_000_000`.
3541    ///
3542    /// # Example
3543    ///
3544    /// This example shows how to round a datetime to the nearest 10 minute
3545    /// increment.
3546    ///
3547    /// ```
3548    /// use jiff::{civil::{DateTime, DateTimeRound, date}, RoundMode, Unit};
3549    ///
3550    /// let dt: DateTime = "2024-06-20 03:24:59".parse()?;
3551    /// assert_eq!(
3552    ///     dt.round((Unit::Minute, 10))?,
3553    ///     date(2024, 6, 20).at(3, 20, 0, 0),
3554    /// );
3555    ///
3556    /// # Ok::<(), Box<dyn std::error::Error>>(())
3557    /// ```
3558    #[inline]
3559    pub fn increment(self, increment: i64) -> DateTimeRound {
3560        DateTimeRound { increment, ..self }
3561    }
3562
3563    /// Does the actual rounding.
3564    ///
3565    /// A non-public configuration here is the length of a day. For civil
3566    /// datetimes, this should always be `NANOS_PER_CIVIL_DAY`. But this
3567    /// rounding routine is also used for `Zoned` rounding, and in that
3568    /// context, the length of a day can vary based on the time zone.
3569    pub(crate) fn round(&self, dt: DateTime) -> Result<DateTime, Error> {
3570        // ref: https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.round
3571
3572        // We don't do any rounding in this case and there are no possible
3573        // error conditions under this configuration. So just bail.
3574        if self.smallest == Unit::Nanosecond && self.increment == 1 {
3575            return Ok(dt);
3576        }
3577
3578        let increment =
3579            Increment::for_datetime(self.smallest, self.increment)?;
3580        let time_nanos = dt.time().to_duration();
3581        let sign = Sign::from(dt.date().year());
3582        let time_rounded = increment.round(self.mode, time_nanos)?;
3583        let (days, time_nanos) = time_rounded.as_civil_days_with_remainder();
3584        // OK because `abs(days)` here can never be greater than 1. Namely,
3585        // rounding time increments are limited to values that divide evenly
3586        // into the corresponding maximal value. And a `day` increment is
3587        // limited to `1`. So even starting with the maximal `dt.time()` value
3588        // (the last nanosecond in a civil day), we can never round past 1 day.
3589        let days = sign * days;
3590        // OK because `time_nanos` is guaranteed to be less than a single full
3591        // civil day.
3592        let time = Time::from_duration(time_nanos).unwrap();
3593
3594        // OK because `abs(days) <= 1` (see above comment) and
3595        // `dt.date().day()` can never exceed `31`. So the result always fits
3596        // into an `i64`.
3597        let days_len = (i64::from(dt.date().day()) - 1) + days;
3598        let start = dt.date().first_of_month();
3599        // `abs(days)` is always <= 1, and so `days_len` should
3600        // always be at most 1 greater (or less) than where we started. If we
3601        // started at, e.g., `DateTime::MAX`, then this could overflow.
3602        let date = start
3603            .checked_add(Span::new().days(days_len))
3604            .context(E::FailedAddDays)?;
3605        Ok(DateTime::from_parts(date, time))
3606    }
3607
3608    pub(crate) fn get_smallest(&self) -> Unit {
3609        self.smallest
3610    }
3611
3612    pub(crate) fn get_mode(&self) -> RoundMode {
3613        self.mode
3614    }
3615
3616    pub(crate) fn get_increment(&self) -> i64 {
3617        self.increment
3618    }
3619}
3620
3621impl Default for DateTimeRound {
3622    #[inline]
3623    fn default() -> DateTimeRound {
3624        DateTimeRound::new()
3625    }
3626}
3627
3628impl From<Unit> for DateTimeRound {
3629    #[inline]
3630    fn from(unit: Unit) -> DateTimeRound {
3631        DateTimeRound::default().smallest(unit)
3632    }
3633}
3634
3635impl From<(Unit, i64)> for DateTimeRound {
3636    #[inline]
3637    fn from((unit, increment): (Unit, i64)) -> DateTimeRound {
3638        DateTimeRound::from(unit).increment(increment)
3639    }
3640}
3641
3642/// A builder for setting the fields on a [`DateTime`].
3643///
3644/// This builder is constructed via [`DateTime::with`].
3645///
3646/// # Example
3647///
3648/// The builder ensures one can chain together the individual components of a
3649/// datetime without it failing at an intermediate step. For example, if you
3650/// had a date of `2024-10-31T00:00:00` and wanted to change both the day and
3651/// the month, and each setting was validated independent of the other, you
3652/// would need to be careful to set the day first and then the month. In some
3653/// cases, you would need to set the month first and then the day!
3654///
3655/// But with the builder, you can set values in any order:
3656///
3657/// ```
3658/// use jiff::civil::date;
3659///
3660/// let dt1 = date(2024, 10, 31).at(0, 0, 0, 0);
3661/// let dt2 = dt1.with().month(11).day(30).build()?;
3662/// assert_eq!(dt2, date(2024, 11, 30).at(0, 0, 0, 0));
3663///
3664/// let dt1 = date(2024, 4, 30).at(0, 0, 0, 0);
3665/// let dt2 = dt1.with().day(31).month(7).build()?;
3666/// assert_eq!(dt2, date(2024, 7, 31).at(0, 0, 0, 0));
3667///
3668/// # Ok::<(), Box<dyn std::error::Error>>(())
3669/// ```
3670#[derive(Clone, Copy, Debug)]
3671pub struct DateTimeWith {
3672    date_with: DateWith,
3673    time_with: TimeWith,
3674}
3675
3676impl DateTimeWith {
3677    #[inline]
3678    fn new(original: DateTime) -> DateTimeWith {
3679        DateTimeWith {
3680            date_with: original.date().with(),
3681            time_with: original.time().with(),
3682        }
3683    }
3684
3685    /// Create a new `DateTime` from the fields set on this configuration.
3686    ///
3687    /// An error occurs when the fields combine to an invalid datetime.
3688    ///
3689    /// For any fields not set on this configuration, the values are taken from
3690    /// the [`DateTime`] that originally created this configuration. When no
3691    /// values are set, this routine is guaranteed to succeed and will always
3692    /// return the original datetime without modification.
3693    ///
3694    /// # Example
3695    ///
3696    /// This creates a datetime corresponding to the last day in the year at
3697    /// noon:
3698    ///
3699    /// ```
3700    /// use jiff::civil::date;
3701    ///
3702    /// let dt = date(2023, 1, 1).at(12, 0, 0, 0);
3703    /// assert_eq!(
3704    ///     dt.with().day_of_year_no_leap(365).build()?,
3705    ///     date(2023, 12, 31).at(12, 0, 0, 0),
3706    /// );
3707    ///
3708    /// // It also works with leap years for the same input:
3709    /// let dt = date(2024, 1, 1).at(12, 0, 0, 0);
3710    /// assert_eq!(
3711    ///     dt.with().day_of_year_no_leap(365).build()?,
3712    ///     date(2024, 12, 31).at(12, 0, 0, 0),
3713    /// );
3714    ///
3715    /// # Ok::<(), Box<dyn std::error::Error>>(())
3716    /// ```
3717    ///
3718    /// # Example: error for invalid datetime
3719    ///
3720    /// If the fields combine to form an invalid date, then an error is
3721    /// returned:
3722    ///
3723    /// ```
3724    /// use jiff::civil::date;
3725    ///
3726    /// let dt = date(2024, 11, 30).at(15, 30, 0, 0);
3727    /// assert!(dt.with().day(31).build().is_err());
3728    ///
3729    /// let dt = date(2024, 2, 29).at(15, 30, 0, 0);
3730    /// assert!(dt.with().year(2023).build().is_err());
3731    /// ```
3732    #[inline]
3733    pub fn build(self) -> Result<DateTime, Error> {
3734        let date = self.date_with.build()?;
3735        let time = self.time_with.build()?;
3736        Ok(DateTime::from_parts(date, time))
3737    }
3738
3739    /// Set the year, month and day fields via the `Date` given.
3740    ///
3741    /// This overrides any previous year, month or day settings.
3742    ///
3743    /// # Example
3744    ///
3745    /// This shows how to create a new datetime with a different date:
3746    ///
3747    /// ```
3748    /// use jiff::civil::date;
3749    ///
3750    /// let dt1 = date(2005, 11, 5).at(15, 30, 0, 0);
3751    /// let dt2 = dt1.with().date(date(2017, 10, 31)).build()?;
3752    /// // The date changes but the time remains the same.
3753    /// assert_eq!(dt2, date(2017, 10, 31).at(15, 30, 0, 0));
3754    ///
3755    /// # Ok::<(), Box<dyn std::error::Error>>(())
3756    /// ```
3757    #[inline]
3758    pub fn date(self, date: Date) -> DateTimeWith {
3759        DateTimeWith { date_with: date.with(), ..self }
3760    }
3761
3762    /// Set the hour, minute, second, millisecond, microsecond and nanosecond
3763    /// fields via the `Time` given.
3764    ///
3765    /// This overrides any previous hour, minute, second, millisecond,
3766    /// microsecond, nanosecond or subsecond nanosecond settings.
3767    ///
3768    /// # Example
3769    ///
3770    /// This shows how to create a new datetime with a different time:
3771    ///
3772    /// ```
3773    /// use jiff::civil::{date, time};
3774    ///
3775    /// let dt1 = date(2005, 11, 5).at(15, 30, 0, 0);
3776    /// let dt2 = dt1.with().time(time(23, 59, 59, 123_456_789)).build()?;
3777    /// // The time changes but the date remains the same.
3778    /// assert_eq!(dt2, date(2005, 11, 5).at(23, 59, 59, 123_456_789));
3779    ///
3780    /// # Ok::<(), Box<dyn std::error::Error>>(())
3781    /// ```
3782    #[inline]
3783    pub fn time(self, time: Time) -> DateTimeWith {
3784        DateTimeWith { time_with: time.with(), ..self }
3785    }
3786
3787    /// Set the year field on a [`DateTime`].
3788    ///
3789    /// One can access this value via [`DateTime::year`].
3790    ///
3791    /// This overrides any previous year settings.
3792    ///
3793    /// # Errors
3794    ///
3795    /// This returns an error when [`DateTimeWith::build`] is called if the
3796    /// given year is outside the range `-9999..=9999`. This can also return an
3797    /// error if the resulting date is otherwise invalid.
3798    ///
3799    /// # Example
3800    ///
3801    /// This shows how to create a new datetime with a different year:
3802    ///
3803    /// ```
3804    /// use jiff::civil::date;
3805    ///
3806    /// let dt1 = date(2005, 11, 5).at(15, 30, 0, 0);
3807    /// assert_eq!(dt1.year(), 2005);
3808    /// let dt2 = dt1.with().year(2007).build()?;
3809    /// assert_eq!(dt2.year(), 2007);
3810    ///
3811    /// # Ok::<(), Box<dyn std::error::Error>>(())
3812    /// ```
3813    ///
3814    /// # Example: only changing the year can fail
3815    ///
3816    /// For example, while `2024-02-29T01:30:00` is valid,
3817    /// `2023-02-29T01:30:00` is not:
3818    ///
3819    /// ```
3820    /// use jiff::civil::date;
3821    ///
3822    /// let dt = date(2024, 2, 29).at(1, 30, 0, 0);
3823    /// assert!(dt.with().year(2023).build().is_err());
3824    /// ```
3825    #[inline]
3826    pub fn year(self, year: i16) -> DateTimeWith {
3827        DateTimeWith { date_with: self.date_with.year(year), ..self }
3828    }
3829
3830    /// Set year of a datetime via its era and its non-negative numeric
3831    /// component.
3832    ///
3833    /// One can access this value via [`DateTime::era_year`].
3834    ///
3835    /// # Errors
3836    ///
3837    /// This returns an error when [`DateTimeWith::build`] is called if the
3838    /// year is outside the range for the era specified. For [`Era::BCE`], the
3839    /// range is `1..=10000`. For [`Era::CE`], the range is `1..=9999`.
3840    ///
3841    /// # Example
3842    ///
3843    /// This shows that `CE` years are equivalent to the years used by this
3844    /// crate:
3845    ///
3846    /// ```
3847    /// use jiff::civil::{Era, date};
3848    ///
3849    /// let dt1 = date(2005, 11, 5).at(8, 0, 0, 0);
3850    /// assert_eq!(dt1.year(), 2005);
3851    /// let dt2 = dt1.with().era_year(2007, Era::CE).build()?;
3852    /// assert_eq!(dt2.year(), 2007);
3853    ///
3854    /// // CE years are always positive and can be at most 9999:
3855    /// assert!(dt1.with().era_year(-5, Era::CE).build().is_err());
3856    /// assert!(dt1.with().era_year(10_000, Era::CE).build().is_err());
3857    ///
3858    /// # Ok::<(), Box<dyn std::error::Error>>(())
3859    /// ```
3860    ///
3861    /// But `BCE` years always correspond to years less than or equal to `0`
3862    /// in this crate:
3863    ///
3864    /// ```
3865    /// use jiff::civil::{Era, date};
3866    ///
3867    /// let dt1 = date(-27, 7, 1).at(8, 22, 30, 0);
3868    /// assert_eq!(dt1.year(), -27);
3869    /// assert_eq!(dt1.era_year(), (28, Era::BCE));
3870    ///
3871    /// let dt2 = dt1.with().era_year(509, Era::BCE).build()?;
3872    /// assert_eq!(dt2.year(), -508);
3873    /// assert_eq!(dt2.era_year(), (509, Era::BCE));
3874    ///
3875    /// let dt2 = dt1.with().era_year(10_000, Era::BCE).build()?;
3876    /// assert_eq!(dt2.year(), -9_999);
3877    /// assert_eq!(dt2.era_year(), (10_000, Era::BCE));
3878    ///
3879    /// // BCE years are always positive and can be at most 10000:
3880    /// assert!(dt1.with().era_year(-5, Era::BCE).build().is_err());
3881    /// assert!(dt1.with().era_year(10_001, Era::BCE).build().is_err());
3882    ///
3883    /// # Ok::<(), Box<dyn std::error::Error>>(())
3884    /// ```
3885    ///
3886    /// # Example: overrides `DateTimeWith::year`
3887    ///
3888    /// Setting this option will override any previous `DateTimeWith::year`
3889    /// option:
3890    ///
3891    /// ```
3892    /// use jiff::civil::{Era, date};
3893    ///
3894    /// let dt1 = date(2024, 7, 2).at(10, 27, 10, 123);
3895    /// let dt2 = dt1.with().year(2000).era_year(1900, Era::CE).build()?;
3896    /// assert_eq!(dt2, date(1900, 7, 2).at(10, 27, 10, 123));
3897    ///
3898    /// # Ok::<(), Box<dyn std::error::Error>>(())
3899    /// ```
3900    ///
3901    /// Similarly, `DateTimeWith::year` will override any previous call to
3902    /// `DateTimeWith::era_year`:
3903    ///
3904    /// ```
3905    /// use jiff::civil::{Era, date};
3906    ///
3907    /// let dt1 = date(2024, 7, 2).at(19, 0, 1, 1);
3908    /// let dt2 = dt1.with().era_year(1900, Era::CE).year(2000).build()?;
3909    /// assert_eq!(dt2, date(2000, 7, 2).at(19, 0, 1, 1));
3910    ///
3911    /// # Ok::<(), Box<dyn std::error::Error>>(())
3912    /// ```
3913    #[inline]
3914    pub fn era_year(self, year: i16, era: Era) -> DateTimeWith {
3915        DateTimeWith { date_with: self.date_with.era_year(year, era), ..self }
3916    }
3917
3918    /// Set the month field on a [`DateTime`].
3919    ///
3920    /// One can access this value via [`DateTime::month`].
3921    ///
3922    /// This overrides any previous month settings.
3923    ///
3924    /// # Errors
3925    ///
3926    /// This returns an error when [`DateTimeWith::build`] is called if the
3927    /// given month is outside the range `1..=12`. This can also return an
3928    /// error if the resulting date is otherwise invalid.
3929    ///
3930    /// # Example
3931    ///
3932    /// This shows how to create a new datetime with a different month:
3933    ///
3934    /// ```
3935    /// use jiff::civil::date;
3936    ///
3937    /// let dt1 = date(2005, 11, 5).at(18, 3, 59, 123_456_789);
3938    /// assert_eq!(dt1.month(), 11);
3939    /// let dt2 = dt1.with().month(6).build()?;
3940    /// assert_eq!(dt2.month(), 6);
3941    ///
3942    /// # Ok::<(), Box<dyn std::error::Error>>(())
3943    /// ```
3944    ///
3945    /// # Example: only changing the month can fail
3946    ///
3947    /// For example, while `2024-10-31T00:00:00` is valid,
3948    /// `2024-11-31T00:00:00` is not:
3949    ///
3950    /// ```
3951    /// use jiff::civil::date;
3952    ///
3953    /// let dt = date(2024, 10, 31).at(0, 0, 0, 0);
3954    /// assert!(dt.with().month(11).build().is_err());
3955    /// ```
3956    #[inline]
3957    pub fn month(self, month: i8) -> DateTimeWith {
3958        DateTimeWith { date_with: self.date_with.month(month), ..self }
3959    }
3960
3961    /// Set the day field on a [`DateTime`].
3962    ///
3963    /// One can access this value via [`DateTime::day`].
3964    ///
3965    /// This overrides any previous day settings.
3966    ///
3967    /// # Errors
3968    ///
3969    /// This returns an error when [`DateTimeWith::build`] is called if the
3970    /// given given day is outside of allowable days for the corresponding year
3971    /// and month fields.
3972    ///
3973    /// # Example
3974    ///
3975    /// This shows some examples of setting the day, including a leap day:
3976    ///
3977    /// ```
3978    /// use jiff::civil::date;
3979    ///
3980    /// let dt1 = date(2024, 2, 5).at(21, 59, 1, 999);
3981    /// assert_eq!(dt1.day(), 5);
3982    /// let dt2 = dt1.with().day(10).build()?;
3983    /// assert_eq!(dt2.day(), 10);
3984    /// let dt3 = dt1.with().day(29).build()?;
3985    /// assert_eq!(dt3.day(), 29);
3986    ///
3987    /// # Ok::<(), Box<dyn std::error::Error>>(())
3988    /// ```
3989    ///
3990    /// # Example: changing only the day can fail
3991    ///
3992    /// This shows some examples that will fail:
3993    ///
3994    /// ```
3995    /// use jiff::civil::date;
3996    ///
3997    /// let dt1 = date(2023, 2, 5).at(22, 58, 58, 9_999);
3998    /// // 2023 is not a leap year
3999    /// assert!(dt1.with().day(29).build().is_err());
4000    ///
4001    /// // September has 30 days, not 31.
4002    /// let dt1 = date(2023, 9, 5).at(22, 58, 58, 9_999);
4003    /// assert!(dt1.with().day(31).build().is_err());
4004    /// ```
4005    #[inline]
4006    pub fn day(self, day: i8) -> DateTimeWith {
4007        DateTimeWith { date_with: self.date_with.day(day), ..self }
4008    }
4009
4010    /// Set the day field on a [`DateTime`] via the ordinal number of a day
4011    /// within a year.
4012    ///
4013    /// When used, any settings for month are ignored since the month is
4014    /// determined by the day of the year.
4015    ///
4016    /// The valid values for `day` are `1..=366`. Note though that `366` is
4017    /// only valid for leap years.
4018    ///
4019    /// This overrides any previous day settings.
4020    ///
4021    /// # Errors
4022    ///
4023    /// This returns an error when [`DateTimeWith::build`] is called if the
4024    /// given day is outside the allowed range of `1..=366`, or when a value of
4025    /// `366` is given for a non-leap year.
4026    ///
4027    /// # Example
4028    ///
4029    /// This demonstrates that if a year is a leap year, then `60` corresponds
4030    /// to February 29:
4031    ///
4032    /// ```
4033    /// use jiff::civil::date;
4034    ///
4035    /// let dt = date(2024, 1, 1).at(23, 59, 59, 999_999_999);
4036    /// assert_eq!(
4037    ///     dt.with().day_of_year(60).build()?,
4038    ///     date(2024, 2, 29).at(23, 59, 59, 999_999_999),
4039    /// );
4040    ///
4041    /// # Ok::<(), Box<dyn std::error::Error>>(())
4042    /// ```
4043    ///
4044    /// But for non-leap years, day 60 is March 1:
4045    ///
4046    /// ```
4047    /// use jiff::civil::date;
4048    ///
4049    /// let dt = date(2023, 1, 1).at(23, 59, 59, 999_999_999);
4050    /// assert_eq!(
4051    ///     dt.with().day_of_year(60).build()?,
4052    ///     date(2023, 3, 1).at(23, 59, 59, 999_999_999),
4053    /// );
4054    ///
4055    /// # Ok::<(), Box<dyn std::error::Error>>(())
4056    /// ```
4057    ///
4058    /// And using `366` for a non-leap year will result in an error, since
4059    /// non-leap years only have 365 days:
4060    ///
4061    /// ```
4062    /// use jiff::civil::date;
4063    ///
4064    /// let dt = date(2023, 1, 1).at(0, 0, 0, 0);
4065    /// assert!(dt.with().day_of_year(366).build().is_err());
4066    /// // The maximal year is not a leap year, so it returns an error too.
4067    /// let dt = date(9999, 1, 1).at(0, 0, 0, 0);
4068    /// assert!(dt.with().day_of_year(366).build().is_err());
4069    /// ```
4070    #[inline]
4071    pub fn day_of_year(self, day: i16) -> DateTimeWith {
4072        DateTimeWith { date_with: self.date_with.day_of_year(day), ..self }
4073    }
4074
4075    /// Set the day field on a [`DateTime`] via the ordinal number of a day
4076    /// within a year, but ignoring leap years.
4077    ///
4078    /// When used, any settings for month are ignored since the month is
4079    /// determined by the day of the year.
4080    ///
4081    /// The valid values for `day` are `1..=365`. The value `365` always
4082    /// corresponds to the last day of the year, even for leap years. It is
4083    /// impossible for this routine to return a datetime corresponding to
4084    /// February 29.
4085    ///
4086    /// This overrides any previous day settings.
4087    ///
4088    /// # Errors
4089    ///
4090    /// This returns an error when [`DateTimeWith::build`] is called if the
4091    /// given day is outside the allowed range of `1..=365`.
4092    ///
4093    /// # Example
4094    ///
4095    /// This demonstrates that `60` corresponds to March 1, regardless of
4096    /// whether the year is a leap year or not:
4097    ///
4098    /// ```
4099    /// use jiff::civil::date;
4100    ///
4101    /// let dt = date(2023, 1, 1).at(23, 59, 59, 999_999_999);
4102    /// assert_eq!(
4103    ///     dt.with().day_of_year_no_leap(60).build()?,
4104    ///     date(2023, 3, 1).at(23, 59, 59, 999_999_999),
4105    /// );
4106    ///
4107    /// let dt = date(2024, 1, 1).at(23, 59, 59, 999_999_999);
4108    /// assert_eq!(
4109    ///     dt.with().day_of_year_no_leap(60).build()?,
4110    ///     date(2024, 3, 1).at(23, 59, 59, 999_999_999),
4111    /// );
4112    ///
4113    /// # Ok::<(), Box<dyn std::error::Error>>(())
4114    /// ```
4115    ///
4116    /// And using `365` for any year will always yield the last day of the
4117    /// year:
4118    ///
4119    /// ```
4120    /// use jiff::civil::date;
4121    ///
4122    /// let dt = date(2023, 1, 1).at(23, 59, 59, 999_999_999);
4123    /// assert_eq!(
4124    ///     dt.with().day_of_year_no_leap(365).build()?,
4125    ///     dt.last_of_year(),
4126    /// );
4127    ///
4128    /// let dt = date(2024, 1, 1).at(23, 59, 59, 999_999_999);
4129    /// assert_eq!(
4130    ///     dt.with().day_of_year_no_leap(365).build()?,
4131    ///     dt.last_of_year(),
4132    /// );
4133    ///
4134    /// let dt = date(9999, 1, 1).at(23, 59, 59, 999_999_999);
4135    /// assert_eq!(
4136    ///     dt.with().day_of_year_no_leap(365).build()?,
4137    ///     dt.last_of_year(),
4138    /// );
4139    ///
4140    /// # Ok::<(), Box<dyn std::error::Error>>(())
4141    /// ```
4142    ///
4143    /// A value of `366` is out of bounds, even for leap years:
4144    ///
4145    /// ```
4146    /// use jiff::civil::date;
4147    ///
4148    /// let dt = date(2024, 1, 1).at(5, 30, 0, 0);
4149    /// assert!(dt.with().day_of_year_no_leap(366).build().is_err());
4150    /// ```
4151    #[inline]
4152    pub fn day_of_year_no_leap(self, day: i16) -> DateTimeWith {
4153        DateTimeWith {
4154            date_with: self.date_with.day_of_year_no_leap(day),
4155            ..self
4156        }
4157    }
4158
4159    /// Set the hour field on a [`DateTime`].
4160    ///
4161    /// One can access this value via [`DateTime::hour`].
4162    ///
4163    /// This overrides any previous hour settings.
4164    ///
4165    /// # Errors
4166    ///
4167    /// This returns an error when [`DateTimeWith::build`] is called if the
4168    /// given hour is outside the range `0..=23`.
4169    ///
4170    /// # Example
4171    ///
4172    /// ```
4173    /// use jiff::civil::time;
4174    ///
4175    /// let dt1 = time(15, 21, 59, 0).on(2010, 6, 1);
4176    /// assert_eq!(dt1.hour(), 15);
4177    /// let dt2 = dt1.with().hour(3).build()?;
4178    /// assert_eq!(dt2.hour(), 3);
4179    ///
4180    /// # Ok::<(), Box<dyn std::error::Error>>(())
4181    /// ```
4182    #[inline]
4183    pub fn hour(self, hour: i8) -> DateTimeWith {
4184        DateTimeWith { time_with: self.time_with.hour(hour), ..self }
4185    }
4186
4187    /// Set the minute field on a [`DateTime`].
4188    ///
4189    /// One can access this value via [`DateTime::minute`].
4190    ///
4191    /// This overrides any previous minute settings.
4192    ///
4193    /// # Errors
4194    ///
4195    /// This returns an error when [`DateTimeWith::build`] is called if the
4196    /// given minute is outside the range `0..=59`.
4197    ///
4198    /// # Example
4199    ///
4200    /// ```
4201    /// use jiff::civil::time;
4202    ///
4203    /// let dt1 = time(15, 21, 59, 0).on(2010, 6, 1);
4204    /// assert_eq!(dt1.minute(), 21);
4205    /// let dt2 = dt1.with().minute(3).build()?;
4206    /// assert_eq!(dt2.minute(), 3);
4207    ///
4208    /// # Ok::<(), Box<dyn std::error::Error>>(())
4209    /// ```
4210    #[inline]
4211    pub fn minute(self, minute: i8) -> DateTimeWith {
4212        DateTimeWith { time_with: self.time_with.minute(minute), ..self }
4213    }
4214
4215    /// Set the second field on a [`DateTime`].
4216    ///
4217    /// One can access this value via [`DateTime::second`].
4218    ///
4219    /// This overrides any previous second settings.
4220    ///
4221    /// # Errors
4222    ///
4223    /// This returns an error when [`DateTimeWith::build`] is called if the
4224    /// given second is outside the range `0..=59`.
4225    ///
4226    /// # Example
4227    ///
4228    /// ```
4229    /// use jiff::civil::time;
4230    ///
4231    /// let dt1 = time(15, 21, 59, 0).on(2010, 6, 1);
4232    /// assert_eq!(dt1.second(), 59);
4233    /// let dt2 = dt1.with().second(3).build()?;
4234    /// assert_eq!(dt2.second(), 3);
4235    ///
4236    /// # Ok::<(), Box<dyn std::error::Error>>(())
4237    /// ```
4238    #[inline]
4239    pub fn second(self, second: i8) -> DateTimeWith {
4240        DateTimeWith { time_with: self.time_with.second(second), ..self }
4241    }
4242
4243    /// Set the millisecond field on a [`DateTime`].
4244    ///
4245    /// One can access this value via [`DateTime::millisecond`].
4246    ///
4247    /// This overrides any previous millisecond settings.
4248    ///
4249    /// Note that this only sets the millisecond component. It does
4250    /// not change the microsecond or nanosecond components. To set
4251    /// the fractional second component to nanosecond precision, use
4252    /// [`DateTimeWith::subsec_nanosecond`].
4253    ///
4254    /// # Errors
4255    ///
4256    /// This returns an error when [`DateTimeWith::build`] is called if the
4257    /// given millisecond is outside the range `0..=999`, or if both this and
4258    /// [`DateTimeWith::subsec_nanosecond`] are set.
4259    ///
4260    /// # Example
4261    ///
4262    /// This shows the relationship between [`DateTime::millisecond`] and
4263    /// [`DateTime::subsec_nanosecond`]:
4264    ///
4265    /// ```
4266    /// use jiff::civil::time;
4267    ///
4268    /// let dt1 = time(15, 21, 35, 0).on(2010, 6, 1);
4269    /// let dt2 = dt1.with().millisecond(123).build()?;
4270    /// assert_eq!(dt2.subsec_nanosecond(), 123_000_000);
4271    ///
4272    /// # Ok::<(), Box<dyn std::error::Error>>(())
4273    /// ```
4274    #[inline]
4275    pub fn millisecond(self, millisecond: i16) -> DateTimeWith {
4276        DateTimeWith {
4277            time_with: self.time_with.millisecond(millisecond),
4278            ..self
4279        }
4280    }
4281
4282    /// Set the microsecond field on a [`DateTime`].
4283    ///
4284    /// One can access this value via [`DateTime::microsecond`].
4285    ///
4286    /// This overrides any previous microsecond settings.
4287    ///
4288    /// Note that this only sets the microsecond component. It does
4289    /// not change the millisecond or nanosecond components. To set
4290    /// the fractional second component to nanosecond precision, use
4291    /// [`DateTimeWith::subsec_nanosecond`].
4292    ///
4293    /// # Errors
4294    ///
4295    /// This returns an error when [`DateTimeWith::build`] is called if the
4296    /// given microsecond is outside the range `0..=999`, or if both this and
4297    /// [`DateTimeWith::subsec_nanosecond`] are set.
4298    ///
4299    /// # Example
4300    ///
4301    /// This shows the relationship between [`DateTime::microsecond`] and
4302    /// [`DateTime::subsec_nanosecond`]:
4303    ///
4304    /// ```
4305    /// use jiff::civil::time;
4306    ///
4307    /// let dt1 = time(15, 21, 35, 0).on(2010, 6, 1);
4308    /// let dt2 = dt1.with().microsecond(123).build()?;
4309    /// assert_eq!(dt2.subsec_nanosecond(), 123_000);
4310    ///
4311    /// # Ok::<(), Box<dyn std::error::Error>>(())
4312    /// ```
4313    #[inline]
4314    pub fn microsecond(self, microsecond: i16) -> DateTimeWith {
4315        DateTimeWith {
4316            time_with: self.time_with.microsecond(microsecond),
4317            ..self
4318        }
4319    }
4320
4321    /// Set the nanosecond field on a [`DateTime`].
4322    ///
4323    /// One can access this value via [`DateTime::nanosecond`].
4324    ///
4325    /// This overrides any previous nanosecond settings.
4326    ///
4327    /// Note that this only sets the nanosecond component. It does
4328    /// not change the millisecond or microsecond components. To set
4329    /// the fractional second component to nanosecond precision, use
4330    /// [`DateTimeWith::subsec_nanosecond`].
4331    ///
4332    /// # Errors
4333    ///
4334    /// This returns an error when [`DateTimeWith::build`] is called if the
4335    /// given nanosecond is outside the range `0..=999`, or if both this and
4336    /// [`DateTimeWith::subsec_nanosecond`] are set.
4337    ///
4338    /// # Example
4339    ///
4340    /// This shows the relationship between [`DateTime::nanosecond`] and
4341    /// [`DateTime::subsec_nanosecond`]:
4342    ///
4343    /// ```
4344    /// use jiff::civil::time;
4345    ///
4346    /// let dt1 = time(15, 21, 35, 0).on(2010, 6, 1);
4347    /// let dt2 = dt1.with().nanosecond(123).build()?;
4348    /// assert_eq!(dt2.subsec_nanosecond(), 123);
4349    ///
4350    /// # Ok::<(), Box<dyn std::error::Error>>(())
4351    /// ```
4352    #[inline]
4353    pub fn nanosecond(self, nanosecond: i16) -> DateTimeWith {
4354        DateTimeWith {
4355            time_with: self.time_with.nanosecond(nanosecond),
4356            ..self
4357        }
4358    }
4359
4360    /// Set the subsecond nanosecond field on a [`DateTime`].
4361    ///
4362    /// If you want to access this value on `DateTime`, then use
4363    /// [`DateTime::subsec_nanosecond`].
4364    ///
4365    /// This overrides any previous subsecond nanosecond settings.
4366    ///
4367    /// Note that this sets the entire fractional second component to
4368    /// nanosecond precision, and overrides any individual millisecond,
4369    /// microsecond or nanosecond settings. To set individual components,
4370    /// use [`DateTimeWith::millisecond`], [`DateTimeWith::microsecond`] or
4371    /// [`DateTimeWith::nanosecond`].
4372    ///
4373    /// # Errors
4374    ///
4375    /// This returns an error when [`DateTimeWith::build`] is called if the
4376    /// given subsecond nanosecond is outside the range `0..=999,999,999`,
4377    /// or if both this and one of [`DateTimeWith::millisecond`],
4378    /// [`DateTimeWith::microsecond`] or [`DateTimeWith::nanosecond`] are set.
4379    ///
4380    /// # Example
4381    ///
4382    /// This shows the relationship between constructing a `DateTime` value
4383    /// with subsecond nanoseconds and its individual subsecond fields:
4384    ///
4385    /// ```
4386    /// use jiff::civil::time;
4387    ///
4388    /// let dt1 = time(15, 21, 35, 0).on(2010, 6, 1);
4389    /// let dt2 = dt1.with().subsec_nanosecond(123_456_789).build()?;
4390    /// assert_eq!(dt2.millisecond(), 123);
4391    /// assert_eq!(dt2.microsecond(), 456);
4392    /// assert_eq!(dt2.nanosecond(), 789);
4393    ///
4394    /// # Ok::<(), Box<dyn std::error::Error>>(())
4395    /// ```
4396    #[inline]
4397    pub fn subsec_nanosecond(self, subsec_nanosecond: i32) -> DateTimeWith {
4398        DateTimeWith {
4399            time_with: self.time_with.subsec_nanosecond(subsec_nanosecond),
4400            ..self
4401        }
4402    }
4403}
4404
4405#[cfg(test)]
4406mod tests {
4407    use std::io::Cursor;
4408
4409    use crate::{
4410        civil::{date, time},
4411        span::span_eq,
4412        RoundMode, ToSpan, Unit,
4413    };
4414
4415    use super::*;
4416
4417    #[test]
4418    fn from_temporal_docs() {
4419        let dt = DateTime::from_parts(
4420            date(1995, 12, 7),
4421            time(3, 24, 30, 000_003_500),
4422        );
4423
4424        let got = dt.round(Unit::Hour).unwrap();
4425        let expected =
4426            DateTime::from_parts(date(1995, 12, 7), time(3, 0, 0, 0));
4427        assert_eq!(got, expected);
4428
4429        let got = dt.round((Unit::Minute, 30)).unwrap();
4430        let expected =
4431            DateTime::from_parts(date(1995, 12, 7), time(3, 30, 0, 0));
4432        assert_eq!(got, expected);
4433
4434        let got = dt
4435            .round(
4436                DateTimeRound::new()
4437                    .smallest(Unit::Minute)
4438                    .increment(30)
4439                    .mode(RoundMode::Floor),
4440            )
4441            .unwrap();
4442        let expected =
4443            DateTime::from_parts(date(1995, 12, 7), time(3, 0, 0, 0));
4444        assert_eq!(got, expected);
4445    }
4446
4447    #[test]
4448    fn since() {
4449        let later = date(2024, 5, 9).at(2, 0, 0, 0);
4450        let earlier = date(2024, 5, 8).at(3, 0, 0, 0);
4451        span_eq!(later.since(earlier).unwrap(), 23.hours());
4452
4453        let later = date(2024, 5, 9).at(3, 0, 0, 0);
4454        let earlier = date(2024, 5, 8).at(2, 0, 0, 0);
4455        span_eq!(later.since(earlier).unwrap(), 1.days().hours(1));
4456
4457        let later = date(2024, 5, 9).at(2, 0, 0, 0);
4458        let earlier = date(2024, 5, 10).at(3, 0, 0, 0);
4459        span_eq!(later.since(earlier).unwrap(), -1.days().hours(1));
4460
4461        let later = date(2024, 5, 9).at(3, 0, 0, 0);
4462        let earlier = date(2024, 5, 10).at(2, 0, 0, 0);
4463        span_eq!(later.since(earlier).unwrap(), -23.hours());
4464    }
4465
4466    #[test]
4467    fn until() {
4468        let a = date(9999, 12, 30).at(3, 0, 0, 0);
4469        let b = date(9999, 12, 31).at(2, 0, 0, 0);
4470        span_eq!(a.until(b).unwrap(), 23.hours());
4471
4472        let a = date(-9999, 1, 2).at(2, 0, 0, 0);
4473        let b = date(-9999, 1, 1).at(3, 0, 0, 0);
4474        span_eq!(a.until(b).unwrap(), -23.hours());
4475
4476        let a = date(1995, 12, 7).at(3, 24, 30, 3500);
4477        let b = date(2019, 1, 31).at(15, 30, 0, 0);
4478        span_eq!(
4479            a.until(b).unwrap(),
4480            8456.days()
4481                .hours(12)
4482                .minutes(5)
4483                .seconds(29)
4484                .milliseconds(999)
4485                .microseconds(996)
4486                .nanoseconds(500)
4487        );
4488        span_eq!(
4489            a.until((Unit::Year, b)).unwrap(),
4490            23.years()
4491                .months(1)
4492                .days(24)
4493                .hours(12)
4494                .minutes(5)
4495                .seconds(29)
4496                .milliseconds(999)
4497                .microseconds(996)
4498                .nanoseconds(500)
4499        );
4500        span_eq!(
4501            b.until((Unit::Year, a)).unwrap(),
4502            -23.years()
4503                .months(1)
4504                .days(24)
4505                .hours(12)
4506                .minutes(5)
4507                .seconds(29)
4508                .milliseconds(999)
4509                .microseconds(996)
4510                .nanoseconds(500)
4511        );
4512        span_eq!(
4513            a.until((Unit::Nanosecond, b)).unwrap(),
4514            730641929999996500i64.nanoseconds(),
4515        );
4516
4517        let a = date(-9999, 1, 1).at(0, 0, 0, 0);
4518        let b = date(9999, 12, 31).at(23, 59, 59, 999_999_999);
4519        assert!(a.until((Unit::Nanosecond, b)).is_err());
4520        span_eq!(
4521            a.until((Unit::Microsecond, b)).unwrap(),
4522            Span::new()
4523                .microseconds(631_107_417_600_000_000i64 - 1)
4524                .nanoseconds(999),
4525        );
4526    }
4527
4528    #[test]
4529    fn until_month_lengths() {
4530        let jan1 = date(2020, 1, 1).at(0, 0, 0, 0);
4531        let feb1 = date(2020, 2, 1).at(0, 0, 0, 0);
4532        let mar1 = date(2020, 3, 1).at(0, 0, 0, 0);
4533
4534        span_eq!(jan1.until(feb1).unwrap(), 31.days());
4535        span_eq!(jan1.until((Unit::Month, feb1)).unwrap(), 1.month());
4536        span_eq!(feb1.until(mar1).unwrap(), 29.days());
4537        span_eq!(feb1.until((Unit::Month, mar1)).unwrap(), 1.month());
4538        span_eq!(jan1.until(mar1).unwrap(), 60.days());
4539        span_eq!(jan1.until((Unit::Month, mar1)).unwrap(), 2.months());
4540    }
4541
4542    #[test]
4543    fn datetime_size() {
4544        #[cfg(debug_assertions)]
4545        {
4546            assert_eq!(12, core::mem::size_of::<DateTime>());
4547        }
4548        #[cfg(not(debug_assertions))]
4549        {
4550            assert_eq!(12, core::mem::size_of::<DateTime>());
4551        }
4552    }
4553
4554    /// # `serde` deserializer compatibility test
4555    ///
4556    /// Serde YAML used to be unable to deserialize `jiff` types,
4557    /// as deserializing from bytes is not supported by the deserializer.
4558    ///
4559    /// - <https://github.com/BurntSushi/jiff/issues/138>
4560    /// - <https://github.com/BurntSushi/jiff/discussions/148>
4561    #[test]
4562    fn civil_datetime_deserialize_yaml() {
4563        let expected = datetime(2024, 10, 31, 16, 33, 53, 123456789);
4564
4565        let deserialized: DateTime =
4566            serde_yaml::from_str("2024-10-31 16:33:53.123456789").unwrap();
4567
4568        assert_eq!(deserialized, expected);
4569
4570        let deserialized: DateTime =
4571            serde_yaml::from_slice("2024-10-31 16:33:53.123456789".as_bytes())
4572                .unwrap();
4573
4574        assert_eq!(deserialized, expected);
4575
4576        let cursor = Cursor::new(b"2024-10-31 16:33:53.123456789");
4577        let deserialized: DateTime = serde_yaml::from_reader(cursor).unwrap();
4578
4579        assert_eq!(deserialized, expected);
4580    }
4581}