Coverage Report

Created: 2026-03-31 07:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/jiff-0.2.23/src/civil/datetime.rs
Line
Count
Source
1
use core::time::Duration as UnsignedDuration;
2
3
use 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)]
216
pub struct DateTime {
217
    date: Date,
218
    time: Time,
219
}
220
221
impl 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
0
    pub fn new(
301
0
        year: i16,
302
0
        month: i8,
303
0
        day: i8,
304
0
        hour: i8,
305
0
        minute: i8,
306
0
        second: i8,
307
0
        subsec_nanosecond: i32,
308
0
    ) -> Result<DateTime, Error> {
309
0
        let date = Date::new(year, month, day)?;
310
0
        let time = Time::new(hour, minute, second, subsec_nanosecond)?;
311
0
        Ok(DateTime { date, time })
312
0
    }
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
0
    pub const fn constant(
374
0
        year: i16,
375
0
        month: i8,
376
0
        day: i8,
377
0
        hour: i8,
378
0
        minute: i8,
379
0
        second: i8,
380
0
        subsec_nanosecond: i32,
381
0
    ) -> DateTime {
382
0
        let date = Date::constant(year, month, day);
383
0
        let time = Time::constant(hour, minute, second, subsec_nanosecond);
384
0
        DateTime { date, time }
385
0
    }
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
8.85k
    pub const fn from_parts(date: Date, time: Time) -> DateTime {
404
8.85k
        DateTime { date, time }
405
8.85k
    }
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
0
    pub fn with(self) -> DateTimeWith {
440
0
        DateTimeWith::new(self)
441
0
    }
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
0
    pub fn year(self) -> i16 {
463
0
        self.date().year()
464
0
    }
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
0
    pub fn era_year(self) -> (i16, Era) {
504
0
        self.date().era_year()
505
0
    }
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
0
    pub fn month(self) -> i8 {
521
0
        self.date().month()
522
0
    }
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
0
    pub fn day(self) -> i8 {
538
0
        self.date().day()
539
0
    }
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
0
    pub fn hour(self) -> i8 {
555
0
        self.time().hour()
556
0
    }
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
0
    pub fn minute(self) -> i8 {
572
0
        self.time().minute()
573
0
    }
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
0
    pub fn second(self) -> i8 {
589
0
        self.time().second()
590
0
    }
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
0
    pub fn millisecond(self) -> i16 {
606
0
        self.time().millisecond()
607
0
    }
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
0
    pub fn microsecond(self) -> i16 {
623
0
        self.time().microsecond()
624
0
    }
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
0
    pub fn nanosecond(self) -> i16 {
640
0
        self.time().nanosecond()
641
0
    }
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
0
    pub fn subsec_nanosecond(self) -> i32 {
694
0
        self.time().subsec_nanosecond()
695
0
    }
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
0
    pub fn weekday(self) -> Weekday {
715
0
        self.date().weekday()
716
0
    }
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
0
    pub fn day_of_year(self) -> i16 {
739
0
        self.date().day_of_year()
740
0
    }
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
0
    pub fn day_of_year_no_leap(self) -> Option<i16> {
771
0
        self.date().day_of_year_no_leap()
772
0
    }
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
0
    pub fn start_of_day(&self) -> DateTime {
789
0
        DateTime::from_parts(self.date(), Time::MIN)
790
0
    }
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
0
    pub fn end_of_day(&self) -> DateTime {
810
0
        DateTime::from_parts(self.date(), Time::MAX)
811
0
    }
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
0
    pub fn first_of_month(self) -> DateTime {
827
0
        DateTime::from_parts(self.date().first_of_month(), self.time())
828
0
    }
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
0
    pub fn last_of_month(self) -> DateTime {
844
0
        DateTime::from_parts(self.date().last_of_month(), self.time())
845
0
    }
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
0
    pub fn days_in_month(self) -> i8 {
869
0
        self.date().days_in_month()
870
0
    }
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
0
    pub fn first_of_year(self) -> DateTime {
886
0
        DateTime::from_parts(self.date().first_of_year(), self.time())
887
0
    }
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
0
    pub fn last_of_year(self) -> DateTime {
903
0
        DateTime::from_parts(self.date().last_of_year(), self.time())
904
0
    }
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
0
    pub fn days_in_year(self) -> i16 {
924
0
        self.date().days_in_year()
925
0
    }
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
0
    pub fn in_leap_year(self) -> bool {
940
0
        self.date().in_leap_year()
941
0
    }
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
0
    pub fn tomorrow(self) -> Result<DateTime, Error> {
966
0
        Ok(DateTime::from_parts(self.date().tomorrow()?, self.time()))
967
0
    }
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
0
    pub fn yesterday(self) -> Result<DateTime, Error> {
992
0
        Ok(DateTime::from_parts(self.date().yesterday()?, self.time()))
993
0
    }
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
0
    pub fn nth_weekday_of_month(
1061
0
        self,
1062
0
        nth: i8,
1063
0
        weekday: Weekday,
1064
0
    ) -> Result<DateTime, Error> {
1065
0
        let date = self.date().nth_weekday_of_month(nth, weekday)?;
1066
0
        Ok(DateTime::from_parts(date, self.time()))
1067
0
    }
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
0
    pub fn nth_weekday(
1219
0
        self,
1220
0
        nth: i32,
1221
0
        weekday: Weekday,
1222
0
    ) -> Result<DateTime, Error> {
1223
0
        let date = self.date().nth_weekday(nth, weekday)?;
1224
0
        Ok(DateTime::from_parts(date, self.time()))
1225
0
    }
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
3.41k
    pub fn date(self) -> Date {
1239
3.41k
        self.date
1240
3.41k
    }
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
3.41k
    pub fn time(self) -> Time {
1254
3.41k
        self.time
1255
3.41k
    }
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
0
    pub fn iso_week_date(self) -> ISOWeekDate {
1314
0
        self.date().iso_week_date()
1315
0
    }
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
0
    pub fn in_tz(self, time_zone_name: &str) -> Result<Zoned, Error> {
1445
0
        let tz = crate::tz::db().get(time_zone_name)?;
1446
0
        self.to_zoned(tz)
1447
0
    }
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
1.50k
    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
1.50k
        let dt = self;
1549
1.50k
        let amb_ts = tz.to_ambiguous_timestamp(dt);
1550
1.50k
        let (offset, ts, dt) = match amb_ts.offset() {
1551
1.50k
            AmbiguousOffset::Unambiguous { offset } => {
1552
1.50k
                let ts = offset.to_timestamp(dt)?;
1553
1.37k
                (offset, ts, dt)
1554
            }
1555
0
            AmbiguousOffset::Gap { before, .. } => {
1556
0
                let ts = before.to_timestamp(dt)?;
1557
0
                let offset = tz.to_offset(ts);
1558
0
                let dt = offset.to_datetime(ts);
1559
0
                (offset, ts, dt)
1560
            }
1561
0
            AmbiguousOffset::Fold { before, .. } => {
1562
0
                let ts = before.to_timestamp(dt)?;
1563
0
                let offset = tz.to_offset(ts);
1564
0
                let dt = offset.to_datetime(ts);
1565
0
                (offset, ts, dt)
1566
            }
1567
        };
1568
1.37k
        Ok(Zoned::from_parts(ts, tz, offset, dt))
1569
1.50k
    }
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
807
    pub fn checked_add<A: Into<DateTimeArithmetic>>(
1679
807
        self,
1680
807
        duration: A,
1681
807
    ) -> Result<DateTime, Error> {
1682
807
        let duration: DateTimeArithmetic = duration.into();
1683
807
        duration.checked_add(self)
1684
807
    }
Unexecuted instantiation: <jiff::civil::datetime::DateTime>::checked_add::<jiff::span::Span>
Unexecuted instantiation: <jiff::civil::datetime::DateTime>::checked_add::<jiff::signed_duration::SignedDuration>
Unexecuted instantiation: <jiff::civil::datetime::DateTime>::checked_add::<jiff::span::Span>
<jiff::civil::datetime::DateTime>::checked_add::<jiff::span::Span>
Line
Count
Source
1678
807
    pub fn checked_add<A: Into<DateTimeArithmetic>>(
1679
807
        self,
1680
807
        duration: A,
1681
807
    ) -> Result<DateTime, Error> {
1682
807
        let duration: DateTimeArithmetic = duration.into();
1683
807
        duration.checked_add(self)
1684
807
    }
Unexecuted instantiation: <jiff::civil::datetime::DateTime>::checked_add::<jiff::span::Span>
Unexecuted instantiation: <jiff::civil::datetime::DateTime>::checked_add::<jiff::span::Span>
1685
1686
    #[inline]
1687
807
    fn checked_add_span(self, span: &Span) -> Result<DateTime, Error> {
1688
807
        let (old_date, old_time) = (self.date(), self.time());
1689
807
        let units = span.units();
1690
807
        match (units.only_calendar().is_empty(), units.only_time().is_empty())
1691
        {
1692
0
            (true, true) => Ok(self),
1693
            (false, true) => {
1694
807
                let new_date = old_date
1695
807
                    .checked_add(span)
1696
807
                    .context(E::FailedAddSpanDate)?;
1697
461
                Ok(DateTime::from_parts(new_date, old_time))
1698
            }
1699
            (true, false) => {
1700
0
                let (new_time, leftovers) = old_time
1701
0
                    .overflowing_add(span)
1702
0
                    .context(E::FailedAddSpanTime)?;
1703
0
                let new_date = old_date
1704
0
                    .checked_add(leftovers)
1705
0
                    .context(E::FailedAddSpanOverflowing)?;
1706
0
                Ok(DateTime::from_parts(new_date, new_time))
1707
            }
1708
0
            (false, false) => self.checked_add_span_general(span),
1709
        }
1710
807
    }
1711
1712
    #[inline(never)]
1713
    #[cold]
1714
0
    fn checked_add_span_general(self, span: &Span) -> Result<DateTime, Error> {
1715
0
        let (old_date, old_time) = (self.date(), self.time());
1716
0
        let span_date = span.without_lower(Unit::Day);
1717
0
        let span_time = span.only_lower(Unit::Day);
1718
1719
0
        let (new_time, leftovers) = old_time
1720
0
            .overflowing_add(&span_time)
1721
0
            .context(E::FailedAddSpanTime)?;
1722
0
        let new_date =
1723
0
            old_date.checked_add(span_date).context(E::FailedAddSpanDate)?;
1724
0
        let new_date = new_date
1725
0
            .checked_add(leftovers)
1726
0
            .context(E::FailedAddSpanOverflowing)?;
1727
0
        Ok(DateTime::from_parts(new_date, new_time))
1728
0
    }
1729
1730
    #[inline]
1731
0
    fn checked_add_duration(
1732
0
        self,
1733
0
        duration: SignedDuration,
1734
0
    ) -> Result<DateTime, Error> {
1735
0
        let (date, time) = (self.date(), self.time());
1736
0
        let (new_time, leftovers) = time.overflowing_add_duration(duration)?;
1737
0
        let new_date = date
1738
0
            .checked_add(leftovers)
1739
0
            .context(E::FailedAddDurationOverflowing)?;
1740
0
        Ok(DateTime::from_parts(new_date, new_time))
1741
0
    }
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
0
    pub fn checked_sub<A: Into<DateTimeArithmetic>>(
1776
0
        self,
1777
0
        duration: A,
1778
0
    ) -> Result<DateTime, Error> {
1779
0
        let duration: DateTimeArithmetic = duration.into();
1780
0
        duration.checked_neg().and_then(|dta| dta.checked_add(self))
1781
0
    }
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
0
    pub fn saturating_add<A: Into<DateTimeArithmetic>>(
1801
0
        self,
1802
0
        duration: A,
1803
0
    ) -> DateTime {
1804
0
        let duration: DateTimeArithmetic = duration.into();
1805
0
        self.checked_add(duration).unwrap_or_else(|_| {
1806
0
            if duration.is_negative() {
1807
0
                DateTime::MIN
1808
            } else {
1809
0
                DateTime::MAX
1810
            }
1811
0
        })
1812
0
    }
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
0
    pub fn saturating_sub<A: Into<DateTimeArithmetic>>(
1831
0
        self,
1832
0
        duration: A,
1833
0
    ) -> DateTime {
1834
0
        let duration: DateTimeArithmetic = duration.into();
1835
0
        let Ok(duration) = duration.checked_neg() else {
1836
0
            return DateTime::MIN;
1837
        };
1838
0
        self.saturating_add(duration)
1839
0
    }
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
0
    pub fn until<A: Into<DateTimeDifference>>(
1994
0
        self,
1995
0
        other: A,
1996
0
    ) -> Result<Span, Error> {
1997
0
        let args: DateTimeDifference = other.into();
1998
0
        let span = args.until_with_largest_unit(self)?;
1999
0
        if args.rounding_may_change_span() {
2000
0
            span.round(args.round.relative(self))
2001
        } else {
2002
0
            Ok(span)
2003
        }
2004
0
    }
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
0
    pub fn since<A: Into<DateTimeDifference>>(
2031
0
        self,
2032
0
        other: A,
2033
0
    ) -> Result<Span, Error> {
2034
0
        let args: DateTimeDifference = other.into();
2035
0
        let span = -args.until_with_largest_unit(self)?;
2036
0
        if args.rounding_may_change_span() {
2037
0
            span.round(args.round.relative(self))
2038
        } else {
2039
0
            Ok(span)
2040
        }
2041
0
    }
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
0
    pub fn duration_until(self, other: DateTime) -> SignedDuration {
2147
0
        SignedDuration::datetime_until(self, other)
2148
0
    }
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
0
    pub fn duration_since(self, other: DateTime) -> SignedDuration {
2169
0
        SignedDuration::datetime_until(other, self)
2170
0
    }
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
0
    pub fn round<R: Into<DateTimeRound>>(
2313
0
        self,
2314
0
        options: R,
2315
0
    ) -> Result<DateTime, Error> {
2316
0
        let options: DateTimeRound = options.into();
2317
0
        options.round(self)
2318
0
    }
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
0
    pub fn series(self, period: Span) -> DateTimeSeries {
2360
0
        DateTimeSeries { start: self, period, step: 0 }
2361
0
    }
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
0
    fn to_duration(self) -> SignedDuration {
2367
0
        let mut dur =
2368
0
            SignedDuration::from_civil_days32(self.date().to_unix_epoch_day());
2369
0
        dur += self.time().to_duration();
2370
0
        dur
2371
0
    }
2372
2373
    #[inline]
2374
3.20k
    pub(crate) const fn to_idatetime_const(&self) -> IDateTime {
2375
3.20k
        IDateTime {
2376
3.20k
            date: self.date.to_idate_const(),
2377
3.20k
            time: self.time.to_itime_const(),
2378
3.20k
        }
2379
3.20k
    }
2380
2381
    #[inline]
2382
4.98k
    pub(crate) const fn from_idatetime_const(idt: IDateTime) -> DateTime {
2383
4.98k
        DateTime::from_parts(
2384
4.98k
            Date::from_idate_const(idt.date),
2385
4.98k
            Time::from_itime_const(idt.time),
2386
        )
2387
4.98k
    }
2388
}
2389
2390
/// Parsing and formatting using a "printf"-style API.
2391
impl 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
0
    pub fn strptime(
2422
0
        format: impl AsRef<[u8]>,
2423
0
        input: impl AsRef<[u8]>,
2424
0
    ) -> Result<DateTime, Error> {
2425
0
        fmt::strtime::parse(format, input).and_then(|tm| tm.to_datetime())
2426
0
    }
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
0
    pub fn strftime<'f, F: 'f + ?Sized + AsRef<[u8]>>(
2457
0
        &self,
2458
0
        format: &'f F,
2459
0
    ) -> fmt::strtime::Display<'f> {
2460
0
        fmt::strtime::Display { fmt: format.as_ref(), tm: (*self).into() }
2461
0
    }
2462
}
2463
2464
impl Default for DateTime {
2465
    #[inline]
2466
0
    fn default() -> DateTime {
2467
0
        DateTime::ZERO
2468
0
    }
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
/// ```
2496
impl core::fmt::Debug for DateTime {
2497
    #[inline]
2498
0
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
2499
0
        core::fmt::Display::fmt(self, f)
2500
0
    }
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
/// ```
2544
impl core::fmt::Display for DateTime {
2545
    #[inline]
2546
0
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
2547
        use crate::fmt::StdFmtWrite;
2548
2549
0
        let precision =
2550
0
            f.precision().map(|p| u8::try_from(p).unwrap_or(u8::MAX));
2551
0
        temporal::DateTimePrinter::new()
2552
0
            .precision(precision)
2553
0
            .print_datetime(self, StdFmtWrite(f))
2554
0
            .map_err(|_| core::fmt::Error)
2555
0
    }
2556
}
2557
2558
impl core::str::FromStr for DateTime {
2559
    type Err = Error;
2560
2561
    #[inline]
2562
0
    fn from_str(string: &str) -> Result<DateTime, Error> {
2563
0
        DEFAULT_DATETIME_PARSER.parse_datetime(string)
2564
0
    }
2565
}
2566
2567
/// Converts a [`Date`] to a [`DateTime`] with the time set to midnight.
2568
impl From<Date> for DateTime {
2569
    #[inline]
2570
700
    fn from(date: Date) -> DateTime {
2571
700
        date.to_datetime(Time::midnight())
2572
700
    }
2573
}
2574
2575
/// Converts a [`Zoned`] to a [`DateTime`].
2576
impl From<Zoned> for DateTime {
2577
    #[inline]
2578
0
    fn from(zdt: Zoned) -> DateTime {
2579
0
        zdt.datetime()
2580
0
    }
2581
}
2582
2583
/// Converts a [`&Zoned`](Zoned) to a [`DateTime`].
2584
impl<'a> From<&'a Zoned> for DateTime {
2585
    #[inline]
2586
0
    fn from(zdt: &'a Zoned) -> DateTime {
2587
0
        zdt.datetime()
2588
0
    }
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`].
2595
impl core::ops::Add<Span> for DateTime {
2596
    type Output = DateTime;
2597
2598
    #[inline]
2599
0
    fn add(self, rhs: Span) -> DateTime {
2600
0
        self.checked_add(rhs).expect("adding span to datetime overflowed")
2601
0
    }
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`].
2608
impl core::ops::AddAssign<Span> for DateTime {
2609
    #[inline]
2610
0
    fn add_assign(&mut self, rhs: Span) {
2611
0
        *self = *self + rhs
2612
0
    }
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`].
2619
impl core::ops::Sub<Span> for DateTime {
2620
    type Output = DateTime;
2621
2622
    #[inline]
2623
0
    fn sub(self, rhs: Span) -> DateTime {
2624
0
        self.checked_sub(rhs)
2625
0
            .expect("subtracting span from datetime overflowed")
2626
0
    }
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`].
2633
impl core::ops::SubAssign<Span> for DateTime {
2634
    #[inline]
2635
0
    fn sub_assign(&mut self, rhs: Span) {
2636
0
        *self = *self - rhs
2637
0
    }
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`].
2654
impl core::ops::Sub for DateTime {
2655
    type Output = Span;
2656
2657
    #[inline]
2658
0
    fn sub(self, rhs: DateTime) -> Span {
2659
0
        self.since(rhs).expect("since never fails when given DateTime")
2660
0
    }
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`].
2667
impl core::ops::Add<SignedDuration> for DateTime {
2668
    type Output = DateTime;
2669
2670
    #[inline]
2671
0
    fn add(self, rhs: SignedDuration) -> DateTime {
2672
0
        self.checked_add(rhs)
2673
0
            .expect("adding signed duration to datetime overflowed")
2674
0
    }
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`].
2681
impl core::ops::AddAssign<SignedDuration> for DateTime {
2682
    #[inline]
2683
0
    fn add_assign(&mut self, rhs: SignedDuration) {
2684
0
        *self = *self + rhs
2685
0
    }
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`].
2692
impl core::ops::Sub<SignedDuration> for DateTime {
2693
    type Output = DateTime;
2694
2695
    #[inline]
2696
0
    fn sub(self, rhs: SignedDuration) -> DateTime {
2697
0
        self.checked_sub(rhs)
2698
0
            .expect("subtracting signed duration from datetime overflowed")
2699
0
    }
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`].
2706
impl core::ops::SubAssign<SignedDuration> for DateTime {
2707
    #[inline]
2708
0
    fn sub_assign(&mut self, rhs: SignedDuration) {
2709
0
        *self = *self - rhs
2710
0
    }
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`].
2717
impl core::ops::Add<UnsignedDuration> for DateTime {
2718
    type Output = DateTime;
2719
2720
    #[inline]
2721
0
    fn add(self, rhs: UnsignedDuration) -> DateTime {
2722
0
        self.checked_add(rhs)
2723
0
            .expect("adding unsigned duration to datetime overflowed")
2724
0
    }
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`].
2731
impl core::ops::AddAssign<UnsignedDuration> for DateTime {
2732
    #[inline]
2733
0
    fn add_assign(&mut self, rhs: UnsignedDuration) {
2734
0
        *self = *self + rhs
2735
0
    }
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`].
2742
impl core::ops::Sub<UnsignedDuration> for DateTime {
2743
    type Output = DateTime;
2744
2745
    #[inline]
2746
0
    fn sub(self, rhs: UnsignedDuration) -> DateTime {
2747
0
        self.checked_sub(rhs)
2748
0
            .expect("subtracting unsigned duration from datetime overflowed")
2749
0
    }
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`].
2756
impl core::ops::SubAssign<UnsignedDuration> for DateTime {
2757
    #[inline]
2758
0
    fn sub_assign(&mut self, rhs: UnsignedDuration) {
2759
0
        *self = *self - rhs
2760
0
    }
2761
}
2762
2763
#[cfg(feature = "serde")]
2764
impl 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")]
2775
impl<'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)]
2818
impl 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)]
2841
pub struct DateTimeSeries {
2842
    start: DateTime,
2843
    period: Span,
2844
    step: i64,
2845
}
2846
2847
impl Iterator for DateTimeSeries {
2848
    type Item = DateTime;
2849
2850
    #[inline]
2851
0
    fn next(&mut self) -> Option<DateTime> {
2852
0
        let span = self.period.checked_mul(self.step).ok()?;
2853
0
        self.step = self.step.checked_add(1)?;
2854
0
        let date = self.start.checked_add(span).ok()?;
2855
0
        Some(date)
2856
0
    }
2857
}
2858
2859
impl 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)]
2900
pub struct DateTimeArithmetic {
2901
    duration: Duration,
2902
}
2903
2904
impl DateTimeArithmetic {
2905
    #[inline]
2906
807
    fn checked_add(self, dt: DateTime) -> Result<DateTime, Error> {
2907
807
        match self.duration.to_signed()? {
2908
807
            SDuration::Span(span) => dt.checked_add_span(span),
2909
0
            SDuration::Absolute(sdur) => dt.checked_add_duration(sdur),
2910
        }
2911
807
    }
2912
2913
    #[inline]
2914
0
    fn checked_neg(self) -> Result<DateTimeArithmetic, Error> {
2915
0
        let duration = self.duration.checked_neg()?;
2916
0
        Ok(DateTimeArithmetic { duration })
2917
0
    }
2918
2919
    #[inline]
2920
0
    fn is_negative(&self) -> bool {
2921
0
        self.duration.is_negative()
2922
0
    }
2923
}
2924
2925
impl From<Span> for DateTimeArithmetic {
2926
807
    fn from(span: Span) -> DateTimeArithmetic {
2927
807
        let duration = Duration::from(span);
2928
807
        DateTimeArithmetic { duration }
2929
807
    }
2930
}
2931
2932
impl From<SignedDuration> for DateTimeArithmetic {
2933
0
    fn from(sdur: SignedDuration) -> DateTimeArithmetic {
2934
0
        let duration = Duration::from(sdur);
2935
0
        DateTimeArithmetic { duration }
2936
0
    }
2937
}
2938
2939
impl From<UnsignedDuration> for DateTimeArithmetic {
2940
0
    fn from(udur: UnsignedDuration) -> DateTimeArithmetic {
2941
0
        let duration = Duration::from(udur);
2942
0
        DateTimeArithmetic { duration }
2943
0
    }
2944
}
2945
2946
impl<'a> From<&'a Span> for DateTimeArithmetic {
2947
0
    fn from(span: &'a Span) -> DateTimeArithmetic {
2948
0
        DateTimeArithmetic::from(*span)
2949
0
    }
2950
}
2951
2952
impl<'a> From<&'a SignedDuration> for DateTimeArithmetic {
2953
0
    fn from(sdur: &'a SignedDuration) -> DateTimeArithmetic {
2954
0
        DateTimeArithmetic::from(*sdur)
2955
0
    }
2956
}
2957
2958
impl<'a> From<&'a UnsignedDuration> for DateTimeArithmetic {
2959
0
    fn from(udur: &'a UnsignedDuration) -> DateTimeArithmetic {
2960
0
        DateTimeArithmetic::from(*udur)
2961
0
    }
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)]
3020
pub struct DateTimeDifference {
3021
    datetime: DateTime,
3022
    round: SpanRound<'static>,
3023
}
3024
3025
impl 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
0
    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
0
        let round = SpanRound::new().mode(RoundMode::Trunc);
3037
0
        DateTimeDifference { datetime, round }
3038
0
    }
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
0
    pub fn smallest(self, unit: Unit) -> DateTimeDifference {
3077
0
        DateTimeDifference { round: self.round.smallest(unit), ..self }
3078
0
    }
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
0
    pub fn largest(self, unit: Unit) -> DateTimeDifference {
3116
0
        DateTimeDifference { round: self.round.largest(unit), ..self }
3117
0
    }
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
0
    pub fn mode(self, mode: RoundMode) -> DateTimeDifference {
3161
0
        DateTimeDifference { round: self.round.mode(mode), ..self }
3162
0
    }
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
0
    pub fn increment(self, increment: i64) -> DateTimeDifference {
3213
0
        DateTimeDifference { round: self.round.increment(increment), ..self }
3214
0
    }
3215
3216
    /// Returns true if and only if this configuration could change the span
3217
    /// via rounding.
3218
    #[inline]
3219
0
    fn rounding_may_change_span(&self) -> bool {
3220
0
        self.round.rounding_may_change_span()
3221
0
    }
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
0
    fn until_with_largest_unit(&self, dt1: DateTime) -> Result<Span, Error> {
3228
0
        let dt2 = self.datetime;
3229
0
        let largest = self
3230
0
            .round
3231
0
            .get_largest()
3232
0
            .unwrap_or_else(|| self.round.get_smallest().max(Unit::Day));
3233
0
        if largest <= Unit::Day {
3234
0
            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
0
            return Span::from_invariant_duration(largest, diff);
3243
0
        }
3244
3245
0
        let (d1, mut d2) = (dt1.date(), dt2.date());
3246
0
        let (t1, t2) = (dt1.time(), dt2.time());
3247
0
        let sign = b::Sign::from_ordinals(d2, d1);
3248
0
        let mut time_diff = t1.until_nanoseconds(t2);
3249
0
        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
0
            if sign.is_positive() {
3257
0
                d2 = d2.yesterday().unwrap();
3258
0
            } else if sign.is_negative() {
3259
0
                d2 = d2.tomorrow().unwrap();
3260
0
            }
3261
0
            time_diff += b::NANOS_PER_CIVIL_DAY * sign;
3262
0
        }
3263
0
        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
0
        let time_span = Span::from_invariant_duration(
3269
0
            largest,
3270
0
            SignedDuration::from_nanos(time_diff),
3271
        )
3272
0
        .expect("difference between time always fits in span");
3273
0
        Ok(time_span
3274
0
            .years(date_span.get_years())
3275
0
            .months(date_span.get_months())
3276
0
            .weeks(date_span.get_weeks())
3277
0
            .days(date_span.get_days()))
3278
0
    }
3279
}
3280
3281
impl From<DateTime> for DateTimeDifference {
3282
    #[inline]
3283
0
    fn from(dt: DateTime) -> DateTimeDifference {
3284
0
        DateTimeDifference::new(dt)
3285
0
    }
3286
}
3287
3288
impl From<Date> for DateTimeDifference {
3289
    #[inline]
3290
0
    fn from(date: Date) -> DateTimeDifference {
3291
0
        DateTimeDifference::from(DateTime::from(date))
3292
0
    }
3293
}
3294
3295
impl From<Zoned> for DateTimeDifference {
3296
    #[inline]
3297
0
    fn from(zdt: Zoned) -> DateTimeDifference {
3298
0
        DateTimeDifference::from(DateTime::from(zdt))
3299
0
    }
3300
}
3301
3302
impl<'a> From<&'a Zoned> for DateTimeDifference {
3303
    #[inline]
3304
0
    fn from(zdt: &'a Zoned) -> DateTimeDifference {
3305
0
        DateTimeDifference::from(zdt.datetime())
3306
0
    }
3307
}
3308
3309
impl From<(Unit, DateTime)> for DateTimeDifference {
3310
    #[inline]
3311
0
    fn from((largest, dt): (Unit, DateTime)) -> DateTimeDifference {
3312
0
        DateTimeDifference::from(dt).largest(largest)
3313
0
    }
3314
}
3315
3316
impl From<(Unit, Date)> for DateTimeDifference {
3317
    #[inline]
3318
0
    fn from((largest, date): (Unit, Date)) -> DateTimeDifference {
3319
0
        DateTimeDifference::from(date).largest(largest)
3320
0
    }
3321
}
3322
3323
impl From<(Unit, Zoned)> for DateTimeDifference {
3324
    #[inline]
3325
0
    fn from((largest, zdt): (Unit, Zoned)) -> DateTimeDifference {
3326
0
        DateTimeDifference::from((largest, DateTime::from(zdt)))
3327
0
    }
3328
}
3329
3330
impl<'a> From<(Unit, &'a Zoned)> for DateTimeDifference {
3331
    #[inline]
3332
0
    fn from((largest, zdt): (Unit, &'a Zoned)) -> DateTimeDifference {
3333
0
        DateTimeDifference::from((largest, zdt.datetime()))
3334
0
    }
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)]
3391
pub struct DateTimeRound {
3392
    smallest: Unit,
3393
    mode: RoundMode,
3394
    increment: i64,
3395
}
3396
3397
impl DateTimeRound {
3398
    /// Create a new default configuration for rounding a [`DateTime`].
3399
    #[inline]
3400
0
    pub fn new() -> DateTimeRound {
3401
0
        DateTimeRound {
3402
0
            smallest: Unit::Nanosecond,
3403
0
            mode: RoundMode::HalfExpand,
3404
0
            increment: 1,
3405
0
        }
3406
0
    }
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
0
    pub fn smallest(self, unit: Unit) -> DateTimeRound {
3444
0
        DateTimeRound { smallest: unit, ..self }
3445
0
    }
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
0
    pub fn mode(self, mode: RoundMode) -> DateTimeRound {
3474
0
        DateTimeRound { mode, ..self }
3475
0
    }
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
0
    pub fn increment(self, increment: i64) -> DateTimeRound {
3519
0
        DateTimeRound { increment, ..self }
3520
0
    }
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
0
    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
0
        if self.smallest == Unit::Nanosecond && self.increment == 1 {
3534
0
            return Ok(dt);
3535
0
        }
3536
3537
0
        let increment =
3538
0
            Increment::for_datetime(self.smallest, self.increment)?;
3539
0
        let time_nanos = dt.time().to_duration();
3540
0
        let sign = b::Sign::from(dt.date().year());
3541
0
        let time_rounded = increment.round(self.mode, time_nanos)?;
3542
0
        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
0
        let days = sign * days;
3549
0
        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
0
        let days_len = (i64::from(dt.date().day()) - 1) + days;
3555
0
        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
0
        let date = start
3560
0
            .checked_add(Span::new().days(days_len))
3561
0
            .context(E::FailedAddDays)?;
3562
0
        Ok(DateTime::from_parts(date, time))
3563
0
    }
3564
3565
0
    pub(crate) fn get_smallest(&self) -> Unit {
3566
0
        self.smallest
3567
0
    }
3568
3569
0
    pub(crate) fn get_mode(&self) -> RoundMode {
3570
0
        self.mode
3571
0
    }
3572
3573
0
    pub(crate) fn get_increment(&self) -> i64 {
3574
0
        self.increment
3575
0
    }
3576
}
3577
3578
impl Default for DateTimeRound {
3579
    #[inline]
3580
0
    fn default() -> DateTimeRound {
3581
0
        DateTimeRound::new()
3582
0
    }
3583
}
3584
3585
impl From<Unit> for DateTimeRound {
3586
    #[inline]
3587
0
    fn from(unit: Unit) -> DateTimeRound {
3588
0
        DateTimeRound::default().smallest(unit)
3589
0
    }
3590
}
3591
3592
impl From<(Unit, i64)> for DateTimeRound {
3593
    #[inline]
3594
0
    fn from((unit, increment): (Unit, i64)) -> DateTimeRound {
3595
0
        DateTimeRound::from(unit).increment(increment)
3596
0
    }
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)]
3628
pub struct DateTimeWith {
3629
    date_with: DateWith,
3630
    time_with: TimeWith,
3631
}
3632
3633
impl DateTimeWith {
3634
    #[inline]
3635
0
    fn new(original: DateTime) -> DateTimeWith {
3636
0
        DateTimeWith {
3637
0
            date_with: original.date().with(),
3638
0
            time_with: original.time().with(),
3639
0
        }
3640
0
    }
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
0
    pub fn build(self) -> Result<DateTime, Error> {
3691
0
        let date = self.date_with.build()?;
3692
0
        let time = self.time_with.build()?;
3693
0
        Ok(DateTime::from_parts(date, time))
3694
0
    }
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
0
    pub fn date(self, date: Date) -> DateTimeWith {
3716
0
        DateTimeWith { date_with: date.with(), ..self }
3717
0
    }
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
0
    pub fn time(self, time: Time) -> DateTimeWith {
3741
0
        DateTimeWith { time_with: time.with(), ..self }
3742
0
    }
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
0
    pub fn year(self, year: i16) -> DateTimeWith {
3784
0
        DateTimeWith { date_with: self.date_with.year(year), ..self }
3785
0
    }
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
0
    pub fn era_year(self, year: i16, era: Era) -> DateTimeWith {
3872
0
        DateTimeWith { date_with: self.date_with.era_year(year, era), ..self }
3873
0
    }
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
0
    pub fn month(self, month: i8) -> DateTimeWith {
3915
0
        DateTimeWith { date_with: self.date_with.month(month), ..self }
3916
0
    }
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
0
    pub fn day(self, day: i8) -> DateTimeWith {
3964
0
        DateTimeWith { date_with: self.date_with.day(day), ..self }
3965
0
    }
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
0
    pub fn day_of_year(self, day: i16) -> DateTimeWith {
4029
0
        DateTimeWith { date_with: self.date_with.day_of_year(day), ..self }
4030
0
    }
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
0
    pub fn day_of_year_no_leap(self, day: i16) -> DateTimeWith {
4110
0
        DateTimeWith {
4111
0
            date_with: self.date_with.day_of_year_no_leap(day),
4112
0
            ..self
4113
0
        }
4114
0
    }
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
0
    pub fn hour(self, hour: i8) -> DateTimeWith {
4141
0
        DateTimeWith { time_with: self.time_with.hour(hour), ..self }
4142
0
    }
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
0
    pub fn minute(self, minute: i8) -> DateTimeWith {
4169
0
        DateTimeWith { time_with: self.time_with.minute(minute), ..self }
4170
0
    }
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
0
    pub fn second(self, second: i8) -> DateTimeWith {
4197
0
        DateTimeWith { time_with: self.time_with.second(second), ..self }
4198
0
    }
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
0
    pub fn millisecond(self, millisecond: i16) -> DateTimeWith {
4233
0
        DateTimeWith {
4234
0
            time_with: self.time_with.millisecond(millisecond),
4235
0
            ..self
4236
0
        }
4237
0
    }
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
0
    pub fn microsecond(self, microsecond: i16) -> DateTimeWith {
4272
0
        DateTimeWith {
4273
0
            time_with: self.time_with.microsecond(microsecond),
4274
0
            ..self
4275
0
        }
4276
0
    }
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
0
    pub fn nanosecond(self, nanosecond: i16) -> DateTimeWith {
4311
0
        DateTimeWith {
4312
0
            time_with: self.time_with.nanosecond(nanosecond),
4313
0
            ..self
4314
0
        }
4315
0
    }
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
0
    pub fn subsec_nanosecond(self, subsec_nanosecond: i32) -> DateTimeWith {
4355
0
        DateTimeWith {
4356
0
            time_with: self.time_with.subsec_nanosecond(subsec_nanosecond),
4357
0
            ..self
4358
0
        }
4359
0
    }
4360
}
4361
4362
#[cfg(test)]
4363
mod 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
}