Coverage Report

Created: 2025-09-27 06:48

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