jiff/civil/
datetime.rs

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