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