Skip to main content

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