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