jiff/civil/datetime.rs
1use core::time::Duration as UnsignedDuration;
2
3use crate::{
4 civil::{
5 datetime, Date, DateWith, Era, ISOWeekDate, Time, TimeWith, Weekday,
6 },
7 duration::{Duration, SDuration},
8 error::{civil::Error as E, Error, ErrorContext},
9 fmt::{
10 self,
11 temporal::{self, DEFAULT_DATETIME_PARSER},
12 },
13 shared::util::itime::IDateTime,
14 tz::TimeZone,
15 util::{
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::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 = old_date
1699 .checked_add(span)
1700 .context(E::FailedAddSpanDate)?;
1701 Ok(DateTime::from_parts(new_date, old_time))
1702 }
1703 (true, false) => {
1704 let (new_time, leftovers) = old_time
1705 .overflowing_add(span)
1706 .context(E::FailedAddSpanTime)?;
1707 let new_date = old_date
1708 .checked_add(leftovers)
1709 .context(E::FailedAddSpanOverflowing)?;
1710 Ok(DateTime::from_parts(new_date, new_time))
1711 }
1712 (false, false) => self.checked_add_span_general(&span),
1713 }
1714 }
1715
1716 #[inline(never)]
1717 #[cold]
1718 fn checked_add_span_general(self, span: &Span) -> Result<DateTime, Error> {
1719 let (old_date, old_time) = (self.date(), self.time());
1720 let span_date = span.without_lower(Unit::Day);
1721 let span_time = span.only_lower(Unit::Day);
1722
1723 let (new_time, leftovers) = old_time
1724 .overflowing_add(span_time)
1725 .context(E::FailedAddSpanTime)?;
1726 let new_date =
1727 old_date.checked_add(span_date).context(E::FailedAddSpanDate)?;
1728 let new_date = new_date
1729 .checked_add(leftovers)
1730 .context(E::FailedAddSpanOverflowing)?;
1731 Ok(DateTime::from_parts(new_date, new_time))
1732 }
1733
1734 #[inline]
1735 fn checked_add_duration(
1736 self,
1737 duration: SignedDuration,
1738 ) -> Result<DateTime, Error> {
1739 let (date, time) = (self.date(), self.time());
1740 let (new_time, leftovers) = time.overflowing_add_duration(duration)?;
1741 let new_date = date
1742 .checked_add(leftovers)
1743 .context(E::FailedAddDurationOverflowing)?;
1744 Ok(DateTime::from_parts(new_date, new_time))
1745 }
1746
1747 /// This routine is identical to [`DateTime::checked_add`] with the
1748 /// duration negated.
1749 ///
1750 /// # Errors
1751 ///
1752 /// This has the same error conditions as [`DateTime::checked_add`].
1753 ///
1754 /// # Example
1755 ///
1756 /// This routine can be used via the `-` operator. Note though that if it
1757 /// fails, it will result in a panic.
1758 ///
1759 /// ```
1760 /// use std::time::Duration;
1761 ///
1762 /// use jiff::{civil::date, SignedDuration, ToSpan};
1763 ///
1764 /// let dt = date(1995, 12, 7).at(3, 24, 30, 3_500);
1765 /// assert_eq!(
1766 /// dt - 20.years().months(4).nanoseconds(500),
1767 /// date(1975, 8, 7).at(3, 24, 30, 3_000),
1768 /// );
1769 ///
1770 /// let dur = SignedDuration::new(24 * 60 * 60, 3_500);
1771 /// assert_eq!(dt - dur, date(1995, 12, 6).at(3, 24, 30, 0));
1772 ///
1773 /// let dur = Duration::new(24 * 60 * 60, 3_500);
1774 /// assert_eq!(dt - dur, date(1995, 12, 6).at(3, 24, 30, 0));
1775 ///
1776 /// # Ok::<(), Box<dyn std::error::Error>>(())
1777 /// ```
1778 #[inline]
1779 pub fn checked_sub<A: Into<DateTimeArithmetic>>(
1780 self,
1781 duration: A,
1782 ) -> Result<DateTime, Error> {
1783 let duration: DateTimeArithmetic = duration.into();
1784 duration.checked_neg().and_then(|dta| dta.checked_add(self))
1785 }
1786
1787 /// This routine is identical to [`DateTime::checked_add`], except the
1788 /// result saturates on overflow. That is, instead of overflow, either
1789 /// [`DateTime::MIN`] or [`DateTime::MAX`] is returned.
1790 ///
1791 /// # Example
1792 ///
1793 /// ```
1794 /// use jiff::{civil::{DateTime, date}, SignedDuration, ToSpan};
1795 ///
1796 /// let dt = date(2024, 3, 31).at(13, 13, 13, 13);
1797 /// assert_eq!(DateTime::MAX, dt.saturating_add(9000.years()));
1798 /// assert_eq!(DateTime::MIN, dt.saturating_add(-19000.years()));
1799 /// assert_eq!(DateTime::MAX, dt.saturating_add(SignedDuration::MAX));
1800 /// assert_eq!(DateTime::MIN, dt.saturating_add(SignedDuration::MIN));
1801 /// assert_eq!(DateTime::MAX, dt.saturating_add(std::time::Duration::MAX));
1802 /// ```
1803 #[inline]
1804 pub fn saturating_add<A: Into<DateTimeArithmetic>>(
1805 self,
1806 duration: A,
1807 ) -> DateTime {
1808 let duration: DateTimeArithmetic = duration.into();
1809 self.checked_add(duration).unwrap_or_else(|_| {
1810 if duration.is_negative() {
1811 DateTime::MIN
1812 } else {
1813 DateTime::MAX
1814 }
1815 })
1816 }
1817
1818 /// This routine is identical to [`DateTime::saturating_add`] with the span
1819 /// parameter negated.
1820 ///
1821 /// # Example
1822 ///
1823 /// ```
1824 /// use jiff::{civil::{DateTime, date}, SignedDuration, ToSpan};
1825 ///
1826 /// let dt = date(2024, 3, 31).at(13, 13, 13, 13);
1827 /// assert_eq!(DateTime::MIN, dt.saturating_sub(19000.years()));
1828 /// assert_eq!(DateTime::MAX, dt.saturating_sub(-9000.years()));
1829 /// assert_eq!(DateTime::MIN, dt.saturating_sub(SignedDuration::MAX));
1830 /// assert_eq!(DateTime::MAX, dt.saturating_sub(SignedDuration::MIN));
1831 /// assert_eq!(DateTime::MIN, dt.saturating_sub(std::time::Duration::MAX));
1832 /// ```
1833 #[inline]
1834 pub fn saturating_sub<A: Into<DateTimeArithmetic>>(
1835 self,
1836 duration: A,
1837 ) -> DateTime {
1838 let duration: DateTimeArithmetic = duration.into();
1839 let Ok(duration) = duration.checked_neg() else {
1840 return DateTime::MIN;
1841 };
1842 self.saturating_add(duration)
1843 }
1844
1845 /// Returns a span representing the elapsed time from this datetime until
1846 /// the given `other` datetime.
1847 ///
1848 /// When `other` occurs before this datetime, then the span returned will
1849 /// be negative.
1850 ///
1851 /// Depending on the input provided, the span returned is rounded. It may
1852 /// also be balanced up to bigger units than the default. By default, the
1853 /// span returned is balanced such that the biggest possible unit is days.
1854 /// This default is an API guarantee. Users can rely on the default not
1855 /// returning any calendar units bigger than days in the default
1856 /// configuration.
1857 ///
1858 /// This operation is configured by providing a [`DateTimeDifference`]
1859 /// value. Since this routine accepts anything that implements
1860 /// `Into<DateTimeDifference>`, once can pass a `DateTime` directly.
1861 /// One can also pass a `(Unit, DateTime)`, where `Unit` is treated as
1862 /// [`DateTimeDifference::largest`].
1863 ///
1864 /// # Properties
1865 ///
1866 /// It is guaranteed that if the returned span is subtracted from `other`,
1867 /// and if no rounding is requested, and if the largest unit requested is
1868 /// at most `Unit::Day`, then the original datetime will be returned.
1869 ///
1870 /// This routine is equivalent to `self.since(other).map(|span| -span)`
1871 /// if no rounding options are set. If rounding options are set, then
1872 /// it's equivalent to
1873 /// `self.since(other_without_rounding_options).map(|span| -span)`,
1874 /// followed by a call to [`Span::round`] with the appropriate rounding
1875 /// options set. This is because the negation of a span can result in
1876 /// different rounding results depending on the rounding mode.
1877 ///
1878 /// # Errors
1879 ///
1880 /// An error can occur in some cases when the requested configuration would
1881 /// result in a span that is beyond allowable limits. For example, the
1882 /// nanosecond component of a span cannot the span of time between the
1883 /// minimum and maximum datetime supported by Jiff. Therefore, if one
1884 /// requests a span with its largest unit set to [`Unit::Nanosecond`], then
1885 /// it's possible for this routine to fail.
1886 ///
1887 /// It is guaranteed that if one provides a datetime with the default
1888 /// [`DateTimeDifference`] configuration, then this routine will never
1889 /// fail.
1890 ///
1891 /// # Example
1892 ///
1893 /// ```
1894 /// use jiff::{civil::date, ToSpan};
1895 ///
1896 /// let earlier = date(2006, 8, 24).at(22, 30, 0, 0);
1897 /// let later = date(2019, 1, 31).at(21, 0, 0, 0);
1898 /// assert_eq!(
1899 /// earlier.until(later)?,
1900 /// 4542.days().hours(22).minutes(30).fieldwise(),
1901 /// );
1902 ///
1903 /// // Flipping the dates is fine, but you'll get a negative span.
1904 /// assert_eq!(
1905 /// later.until(earlier)?,
1906 /// -4542.days().hours(22).minutes(30).fieldwise(),
1907 /// );
1908 ///
1909 /// # Ok::<(), Box<dyn std::error::Error>>(())
1910 /// ```
1911 ///
1912 /// # Example: using bigger units
1913 ///
1914 /// This example shows how to expand the span returned to bigger units.
1915 /// This makes use of a `From<(Unit, DateTime)> for DateTimeDifference`
1916 /// trait implementation.
1917 ///
1918 /// ```
1919 /// use jiff::{civil::date, Unit, ToSpan};
1920 ///
1921 /// let dt1 = date(1995, 12, 07).at(3, 24, 30, 3500);
1922 /// let dt2 = date(2019, 01, 31).at(15, 30, 0, 0);
1923 ///
1924 /// // The default limits durations to using "days" as the biggest unit.
1925 /// let span = dt1.until(dt2)?;
1926 /// assert_eq!(span.to_string(), "P8456DT12H5M29.9999965S");
1927 ///
1928 /// // But we can ask for units all the way up to years.
1929 /// let span = dt1.until((Unit::Year, dt2))?;
1930 /// assert_eq!(span.to_string(), "P23Y1M24DT12H5M29.9999965S");
1931 /// # Ok::<(), Box<dyn std::error::Error>>(())
1932 /// ```
1933 ///
1934 /// # Example: rounding the result
1935 ///
1936 /// This shows how one might find the difference between two datetimes and
1937 /// have the result rounded such that sub-seconds are removed.
1938 ///
1939 /// In this case, we need to hand-construct a [`DateTimeDifference`]
1940 /// in order to gain full configurability.
1941 ///
1942 /// ```
1943 /// use jiff::{civil::{DateTimeDifference, date}, Unit, ToSpan};
1944 ///
1945 /// let dt1 = date(1995, 12, 07).at(3, 24, 30, 3500);
1946 /// let dt2 = date(2019, 01, 31).at(15, 30, 0, 0);
1947 ///
1948 /// let span = dt1.until(
1949 /// DateTimeDifference::from(dt2).smallest(Unit::Second),
1950 /// )?;
1951 /// assert_eq!(format!("{span:#}"), "8456d 12h 5m 29s");
1952 ///
1953 /// // We can combine smallest and largest units too!
1954 /// let span = dt1.until(
1955 /// DateTimeDifference::from(dt2)
1956 /// .smallest(Unit::Second)
1957 /// .largest(Unit::Year),
1958 /// )?;
1959 /// assert_eq!(span.to_string(), "P23Y1M24DT12H5M29S");
1960 /// # Ok::<(), Box<dyn std::error::Error>>(())
1961 /// ```
1962 ///
1963 /// # Example: units biggers than days inhibit reversibility
1964 ///
1965 /// If you ask for units bigger than days, then subtracting the span
1966 /// returned from the `other` datetime is not guaranteed to result in the
1967 /// original datetime. For example:
1968 ///
1969 /// ```
1970 /// use jiff::{civil::date, Unit, ToSpan};
1971 ///
1972 /// let dt1 = date(2024, 3, 2).at(0, 0, 0, 0);
1973 /// let dt2 = date(2024, 5, 1).at(0, 0, 0, 0);
1974 ///
1975 /// let span = dt1.until((Unit::Month, dt2))?;
1976 /// assert_eq!(span, 1.month().days(29).fieldwise());
1977 /// let maybe_original = dt2.checked_sub(span)?;
1978 /// // Not the same as the original datetime!
1979 /// assert_eq!(maybe_original, date(2024, 3, 3).at(0, 0, 0, 0));
1980 ///
1981 /// // But in the default configuration, days are always the biggest unit
1982 /// // and reversibility is guaranteed.
1983 /// let span = dt1.until(dt2)?;
1984 /// assert_eq!(span, 60.days().fieldwise());
1985 /// let is_original = dt2.checked_sub(span)?;
1986 /// assert_eq!(is_original, dt1);
1987 ///
1988 /// # Ok::<(), Box<dyn std::error::Error>>(())
1989 /// ```
1990 ///
1991 /// This occurs because span are added as if by adding the biggest units
1992 /// first, and then the smaller units. Because months vary in length,
1993 /// their meaning can change depending on how the span is added. In this
1994 /// case, adding one month to `2024-03-02` corresponds to 31 days, but
1995 /// subtracting one month from `2024-05-01` corresponds to 30 days.
1996 #[inline]
1997 pub fn until<A: Into<DateTimeDifference>>(
1998 self,
1999 other: A,
2000 ) -> Result<Span, Error> {
2001 let args: DateTimeDifference = other.into();
2002 let span = args.until_with_largest_unit(self)?;
2003 if args.rounding_may_change_span() {
2004 span.round(args.round.relative(self))
2005 } else {
2006 Ok(span)
2007 }
2008 }
2009
2010 /// This routine is identical to [`DateTime::until`], but the order of the
2011 /// parameters is flipped.
2012 ///
2013 /// # Errors
2014 ///
2015 /// This has the same error conditions as [`DateTime::until`].
2016 ///
2017 /// # Example
2018 ///
2019 /// This routine can be used via the `-` operator. Since the default
2020 /// configuration is used and because a `Span` can represent the difference
2021 /// between any two possible datetimes, it will never panic.
2022 ///
2023 /// ```
2024 /// use jiff::{civil::date, ToSpan};
2025 ///
2026 /// let earlier = date(2006, 8, 24).at(22, 30, 0, 0);
2027 /// let later = date(2019, 1, 31).at(21, 0, 0, 0);
2028 /// assert_eq!(
2029 /// later - earlier,
2030 /// 4542.days().hours(22).minutes(30).fieldwise(),
2031 /// );
2032 /// ```
2033 #[inline]
2034 pub fn since<A: Into<DateTimeDifference>>(
2035 self,
2036 other: A,
2037 ) -> Result<Span, Error> {
2038 let args: DateTimeDifference = other.into();
2039 let span = -args.until_with_largest_unit(self)?;
2040 if args.rounding_may_change_span() {
2041 span.round(args.round.relative(self))
2042 } else {
2043 Ok(span)
2044 }
2045 }
2046
2047 /// Returns an absolute duration representing the elapsed time from this
2048 /// datetime until the given `other` datetime.
2049 ///
2050 /// When `other` occurs before this datetime, then the duration returned
2051 /// will be negative.
2052 ///
2053 /// Unlike [`DateTime::until`], this returns a duration corresponding to a
2054 /// 96-bit integer of nanoseconds between two datetimes.
2055 ///
2056 /// # Fallibility
2057 ///
2058 /// This routine never panics or returns an error. Since there are no
2059 /// configuration options that can be incorrectly provided, no error is
2060 /// possible when calling this routine. In contrast, [`DateTime::until`]
2061 /// can return an error in some cases due to misconfiguration. But like
2062 /// this routine, [`DateTime::until`] never panics or returns an error in
2063 /// its default configuration.
2064 ///
2065 /// # When should I use this versus [`DateTime::until`]?
2066 ///
2067 /// See the type documentation for [`SignedDuration`] for the section on
2068 /// when one should use [`Span`] and when one should use `SignedDuration`.
2069 /// In short, use `Span` (and therefore `DateTime::until`) unless you have
2070 /// a specific reason to do otherwise.
2071 ///
2072 /// # Example
2073 ///
2074 /// ```
2075 /// use jiff::{civil::date, SignedDuration};
2076 ///
2077 /// let earlier = date(2006, 8, 24).at(22, 30, 0, 0);
2078 /// let later = date(2019, 1, 31).at(21, 0, 0, 0);
2079 /// assert_eq!(
2080 /// earlier.duration_until(later),
2081 /// SignedDuration::from_hours(4542 * 24)
2082 /// + SignedDuration::from_hours(22)
2083 /// + SignedDuration::from_mins(30),
2084 /// );
2085 /// // Flipping the datetimes is fine, but you'll get a negative duration.
2086 /// assert_eq!(
2087 /// later.duration_until(earlier),
2088 /// -SignedDuration::from_hours(4542 * 24)
2089 /// - SignedDuration::from_hours(22)
2090 /// - SignedDuration::from_mins(30),
2091 /// );
2092 /// ```
2093 ///
2094 /// # Example: difference with [`DateTime::until`]
2095 ///
2096 /// The main difference between this routine and `DateTime::until` is that
2097 /// the latter can return units other than a 96-bit integer of nanoseconds.
2098 /// While a 96-bit integer of nanoseconds can be converted into other units
2099 /// like hours, this can only be done for uniform units. (Uniform units are
2100 /// units for which each individual unit always corresponds to the same
2101 /// elapsed time regardless of the datetime it is relative to.) This can't
2102 /// be done for units like years or months.
2103 ///
2104 /// ```
2105 /// use jiff::{civil::date, SignedDuration, Span, SpanRound, ToSpan, Unit};
2106 ///
2107 /// let dt1 = date(2024, 1, 1).at(0, 0, 0, 0);
2108 /// let dt2 = date(2025, 4, 1).at(0, 0, 0, 0);
2109 ///
2110 /// let span = dt1.until((Unit::Year, dt2))?;
2111 /// assert_eq!(span, 1.year().months(3).fieldwise());
2112 ///
2113 /// let duration = dt1.duration_until(dt2);
2114 /// assert_eq!(duration, SignedDuration::from_hours(456 * 24));
2115 /// // There's no way to extract years or months from the signed
2116 /// // duration like one might extract hours (because every hour
2117 /// // is the same length). Instead, you actually have to convert
2118 /// // it to a span and then balance it by providing a relative date!
2119 /// let options = SpanRound::new().largest(Unit::Year).relative(dt1);
2120 /// let span = Span::try_from(duration)?.round(options)?;
2121 /// assert_eq!(span, 1.year().months(3).fieldwise());
2122 ///
2123 /// # Ok::<(), Box<dyn std::error::Error>>(())
2124 /// ```
2125 ///
2126 /// # Example: getting an unsigned duration
2127 ///
2128 /// If you're looking to find the duration between two datetimes as a
2129 /// [`std::time::Duration`], you'll need to use this method to get a
2130 /// [`SignedDuration`] and then convert it to a `std::time::Duration`:
2131 ///
2132 /// ```
2133 /// use std::time::Duration;
2134 ///
2135 /// use jiff::civil::date;
2136 ///
2137 /// let dt1 = date(2024, 7, 1).at(0, 0, 0, 0);
2138 /// let dt2 = date(2024, 8, 1).at(0, 0, 0, 0);
2139 /// let duration = Duration::try_from(dt1.duration_until(dt2))?;
2140 /// assert_eq!(duration, Duration::from_secs(31 * 24 * 60 * 60));
2141 ///
2142 /// // Note that unsigned durations cannot represent all
2143 /// // possible differences! If the duration would be negative,
2144 /// // then the conversion fails:
2145 /// assert!(Duration::try_from(dt2.duration_until(dt1)).is_err());
2146 ///
2147 /// # Ok::<(), Box<dyn std::error::Error>>(())
2148 /// ```
2149 #[inline]
2150 pub fn duration_until(self, other: DateTime) -> SignedDuration {
2151 SignedDuration::datetime_until(self, other)
2152 }
2153
2154 /// This routine is identical to [`DateTime::duration_until`], but the
2155 /// order of the parameters is flipped.
2156 ///
2157 /// # Example
2158 ///
2159 /// ```
2160 /// use jiff::{civil::date, SignedDuration};
2161 ///
2162 /// let earlier = date(2006, 8, 24).at(22, 30, 0, 0);
2163 /// let later = date(2019, 1, 31).at(21, 0, 0, 0);
2164 /// assert_eq!(
2165 /// later.duration_since(earlier),
2166 /// SignedDuration::from_hours(4542 * 24)
2167 /// + SignedDuration::from_hours(22)
2168 /// + SignedDuration::from_mins(30),
2169 /// );
2170 /// ```
2171 #[inline]
2172 pub fn duration_since(self, other: DateTime) -> SignedDuration {
2173 SignedDuration::datetime_until(other, self)
2174 }
2175
2176 /// Rounds this datetime according to the [`DateTimeRound`] configuration
2177 /// given.
2178 ///
2179 /// The principal option is [`DateTimeRound::smallest`], which allows one
2180 /// to configure the smallest units in the returned datetime. Rounding
2181 /// is what determines whether that unit should keep its current value
2182 /// or whether it should be incremented. Moreover, the amount it should
2183 /// be incremented can be configured via [`DateTimeRound::increment`].
2184 /// Finally, the rounding strategy itself can be configured via
2185 /// [`DateTimeRound::mode`].
2186 ///
2187 /// Note that this routine is generic and accepts anything that
2188 /// implements `Into<DateTimeRound>`. Some notable implementations are:
2189 ///
2190 /// * `From<Unit> for DateTimeRound`, which will automatically create a
2191 /// `DateTimeRound::new().smallest(unit)` from the unit provided.
2192 /// * `From<(Unit, i64)> for DateTimeRound`, which will automatically
2193 /// create a `DateTimeRound::new().smallest(unit).increment(number)` from
2194 /// the unit and increment provided.
2195 ///
2196 /// # Errors
2197 ///
2198 /// This returns an error if the smallest unit configured on the given
2199 /// [`DateTimeRound`] is bigger than days. An error is also returned if
2200 /// the rounding increment is greater than 1 when the units are days.
2201 /// (Currently, rounding to the nearest week, month or year is not
2202 /// supported.)
2203 ///
2204 /// When the smallest unit is less than days, the rounding increment must
2205 /// divide evenly into the next highest unit after the smallest unit
2206 /// configured (and must not be equivalent to it). For example, if the
2207 /// smallest unit is [`Unit::Nanosecond`], then *some* of the valid values
2208 /// for the rounding increment are `1`, `2`, `4`, `5`, `100` and `500`.
2209 /// Namely, any integer that divides evenly into `1,000` nanoseconds since
2210 /// there are `1,000` nanoseconds in the next highest unit (microseconds).
2211 ///
2212 /// This can also return an error in some cases where rounding would
2213 /// require arithmetic that exceeds the maximum datetime value.
2214 ///
2215 /// # Example
2216 ///
2217 /// This is a basic example that demonstrates rounding a datetime to the
2218 /// nearest day. This also demonstrates calling this method with the
2219 /// smallest unit directly, instead of constructing a `DateTimeRound`
2220 /// manually.
2221 ///
2222 /// ```
2223 /// use jiff::{civil::date, Unit};
2224 ///
2225 /// let dt = date(2024, 6, 19).at(15, 0, 0, 0);
2226 /// assert_eq!(dt.round(Unit::Day)?, date(2024, 6, 20).at(0, 0, 0, 0));
2227 /// let dt = date(2024, 6, 19).at(10, 0, 0, 0);
2228 /// assert_eq!(dt.round(Unit::Day)?, date(2024, 6, 19).at(0, 0, 0, 0));
2229 ///
2230 /// # Ok::<(), Box<dyn std::error::Error>>(())
2231 /// ```
2232 ///
2233 /// # Example: changing the rounding mode
2234 ///
2235 /// The default rounding mode is [`RoundMode::HalfExpand`], which
2236 /// breaks ties by rounding away from zero. But other modes like
2237 /// [`RoundMode::Trunc`] can be used too:
2238 ///
2239 /// ```
2240 /// use jiff::{civil::{DateTimeRound, date}, RoundMode, 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 /// // The default will round up to the next day for any time past noon,
2245 /// // but using truncation rounding will always round down.
2246 /// assert_eq!(
2247 /// dt.round(
2248 /// DateTimeRound::new().smallest(Unit::Day).mode(RoundMode::Trunc),
2249 /// )?,
2250 /// date(2024, 6, 19).at(0, 0, 0, 0),
2251 /// );
2252 ///
2253 /// # Ok::<(), Box<dyn std::error::Error>>(())
2254 /// ```
2255 ///
2256 /// # Example: rounding to the nearest 5 minute increment
2257 ///
2258 /// ```
2259 /// use jiff::{civil::date, Unit};
2260 ///
2261 /// // rounds down
2262 /// let dt = date(2024, 6, 19).at(15, 27, 29, 999_999_999);
2263 /// assert_eq!(
2264 /// dt.round((Unit::Minute, 5))?,
2265 /// date(2024, 6, 19).at(15, 25, 0, 0),
2266 /// );
2267 /// // rounds up
2268 /// let dt = date(2024, 6, 19).at(15, 27, 30, 0);
2269 /// assert_eq!(
2270 /// dt.round((Unit::Minute, 5))?,
2271 /// date(2024, 6, 19).at(15, 30, 0, 0),
2272 /// );
2273 ///
2274 /// # Ok::<(), Box<dyn std::error::Error>>(())
2275 /// ```
2276 ///
2277 /// # Example: overflow error
2278 ///
2279 /// This example demonstrates that it's possible for this operation to
2280 /// result in an error from datetime arithmetic overflow.
2281 ///
2282 /// ```
2283 /// use jiff::{civil::DateTime, Unit};
2284 ///
2285 /// let dt = DateTime::MAX;
2286 /// assert!(dt.round(Unit::Day).is_err());
2287 /// ```
2288 ///
2289 /// This occurs because rounding to the nearest day for the maximum
2290 /// datetime would result in rounding up to the next day. But the next day
2291 /// is greater than the maximum, and so this returns an error.
2292 ///
2293 /// If one were to use a rounding mode like [`RoundMode::Trunc`] (which
2294 /// will never round up), always set a correct increment and always used
2295 /// units less than or equal to days, then this routine is guaranteed to
2296 /// never fail:
2297 ///
2298 /// ```
2299 /// use jiff::{civil::{DateTime, DateTimeRound, date}, RoundMode, Unit};
2300 ///
2301 /// let round = DateTimeRound::new()
2302 /// .smallest(Unit::Day)
2303 /// .mode(RoundMode::Trunc);
2304 /// assert_eq!(
2305 /// DateTime::MAX.round(round)?,
2306 /// date(9999, 12, 31).at(0, 0, 0, 0),
2307 /// );
2308 /// assert_eq!(
2309 /// DateTime::MIN.round(round)?,
2310 /// date(-9999, 1, 1).at(0, 0, 0, 0),
2311 /// );
2312 ///
2313 /// # Ok::<(), Box<dyn std::error::Error>>(())
2314 /// ```
2315 #[inline]
2316 pub fn round<R: Into<DateTimeRound>>(
2317 self,
2318 options: R,
2319 ) -> Result<DateTime, Error> {
2320 let options: DateTimeRound = options.into();
2321 options.round(self)
2322 }
2323
2324 /// Return an iterator of periodic datetimes determined by the given span.
2325 ///
2326 /// The given span may be negative, in which case, the iterator will move
2327 /// backwards through time. The iterator won't stop until either the span
2328 /// itself overflows, or it would otherwise exceed the minimum or maximum
2329 /// `DateTime` value.
2330 ///
2331 /// # Example: when to check a glucose monitor
2332 ///
2333 /// When my cat had diabetes, my veterinarian installed a glucose monitor
2334 /// and instructed me to scan it about every 5 hours. This example lists
2335 /// all of the times I need to scan it for the 2 days following its
2336 /// installation:
2337 ///
2338 /// ```
2339 /// use jiff::{civil::datetime, ToSpan};
2340 ///
2341 /// let start = datetime(2023, 7, 15, 16, 30, 0, 0);
2342 /// let end = start.checked_add(2.days())?;
2343 /// let mut scan_times = vec![];
2344 /// for dt in start.series(5.hours()).take_while(|&dt| dt <= end) {
2345 /// scan_times.push(dt);
2346 /// }
2347 /// assert_eq!(scan_times, vec![
2348 /// datetime(2023, 7, 15, 16, 30, 0, 0),
2349 /// datetime(2023, 7, 15, 21, 30, 0, 0),
2350 /// datetime(2023, 7, 16, 2, 30, 0, 0),
2351 /// datetime(2023, 7, 16, 7, 30, 0, 0),
2352 /// datetime(2023, 7, 16, 12, 30, 0, 0),
2353 /// datetime(2023, 7, 16, 17, 30, 0, 0),
2354 /// datetime(2023, 7, 16, 22, 30, 0, 0),
2355 /// datetime(2023, 7, 17, 3, 30, 0, 0),
2356 /// datetime(2023, 7, 17, 8, 30, 0, 0),
2357 /// datetime(2023, 7, 17, 13, 30, 0, 0),
2358 /// ]);
2359 ///
2360 /// # Ok::<(), Box<dyn std::error::Error>>(())
2361 /// ```
2362 #[inline]
2363 pub fn series(self, period: Span) -> DateTimeSeries {
2364 DateTimeSeries { start: self, period, step: 0 }
2365 }
2366
2367 /// Converts this datetime to a nanosecond timestamp assuming a Zulu time
2368 /// zone offset and where all days are exactly 24 hours long.
2369 #[inline]
2370 fn to_nanosecond(self) -> t::NoUnits128 {
2371 let day_nano = self.date().to_unix_epoch_day();
2372 let time_nano = self.time().to_nanosecond();
2373 (t::NoUnits128::rfrom(day_nano) * t::NANOS_PER_CIVIL_DAY) + time_nano
2374 }
2375
2376 #[inline]
2377 pub(crate) fn to_idatetime(&self) -> Composite<IDateTime> {
2378 let idate = self.date().to_idate();
2379 let itime = self.time().to_itime();
2380 idate.zip2(itime).map(|(date, time)| IDateTime { date, time })
2381 }
2382
2383 #[inline]
2384 pub(crate) fn from_idatetime(idt: Composite<IDateTime>) -> DateTime {
2385 let (idate, itime) = idt.map(|idt| (idt.date, idt.time)).unzip2();
2386 DateTime::from_parts(Date::from_idate(idate), Time::from_itime(itime))
2387 }
2388
2389 #[inline]
2390 pub(crate) const fn to_idatetime_const(&self) -> IDateTime {
2391 IDateTime {
2392 date: self.date.to_idate_const(),
2393 time: self.time.to_itime_const(),
2394 }
2395 }
2396}
2397
2398/// Parsing and formatting using a "printf"-style API.
2399impl DateTime {
2400 /// Parses a civil datetime in `input` matching the given `format`.
2401 ///
2402 /// The format string uses a "printf"-style API where conversion
2403 /// specifiers can be used as place holders to match components of
2404 /// a datetime. For details on the specifiers supported, see the
2405 /// [`fmt::strtime`] module documentation.
2406 ///
2407 /// # Errors
2408 ///
2409 /// This returns an error when parsing failed. This might happen because
2410 /// the format string itself was invalid, or because the input didn't match
2411 /// the format string.
2412 ///
2413 /// This also returns an error if there wasn't sufficient information to
2414 /// construct a civil datetime. For example, if an offset wasn't parsed.
2415 ///
2416 /// # Example
2417 ///
2418 /// This example shows how to parse a civil datetime:
2419 ///
2420 /// ```
2421 /// use jiff::civil::DateTime;
2422 ///
2423 /// let dt = DateTime::strptime("%F %H:%M", "2024-07-14 21:14")?;
2424 /// assert_eq!(dt.to_string(), "2024-07-14T21:14:00");
2425 ///
2426 /// # Ok::<(), Box<dyn std::error::Error>>(())
2427 /// ```
2428 #[inline]
2429 pub fn strptime(
2430 format: impl AsRef<[u8]>,
2431 input: impl AsRef<[u8]>,
2432 ) -> Result<DateTime, Error> {
2433 fmt::strtime::parse(format, input).and_then(|tm| tm.to_datetime())
2434 }
2435
2436 /// Formats this civil datetime according to the given `format`.
2437 ///
2438 /// The format string uses a "printf"-style API where conversion
2439 /// specifiers can be used as place holders to format components of
2440 /// a datetime. For details on the specifiers supported, see the
2441 /// [`fmt::strtime`] module documentation.
2442 ///
2443 /// # Errors and panics
2444 ///
2445 /// While this routine itself does not error or panic, using the value
2446 /// returned may result in a panic if formatting fails. See the
2447 /// documentation on [`fmt::strtime::Display`] for more information.
2448 ///
2449 /// To format in a way that surfaces errors without panicking, use either
2450 /// [`fmt::strtime::format`] or [`fmt::strtime::BrokenDownTime::format`].
2451 ///
2452 /// # Example
2453 ///
2454 /// This example shows how to format a civil datetime:
2455 ///
2456 /// ```
2457 /// use jiff::civil::date;
2458 ///
2459 /// let dt = date(2024, 7, 15).at(16, 24, 59, 0);
2460 /// let string = dt.strftime("%A, %B %e, %Y at %H:%M:%S").to_string();
2461 /// assert_eq!(string, "Monday, July 15, 2024 at 16:24:59");
2462 /// ```
2463 #[inline]
2464 pub fn strftime<'f, F: 'f + ?Sized + AsRef<[u8]>>(
2465 &self,
2466 format: &'f F,
2467 ) -> fmt::strtime::Display<'f> {
2468 fmt::strtime::Display { fmt: format.as_ref(), tm: (*self).into() }
2469 }
2470}
2471
2472impl Default for DateTime {
2473 #[inline]
2474 fn default() -> DateTime {
2475 DateTime::ZERO
2476 }
2477}
2478
2479/// Converts a `DateTime` into a human readable datetime string.
2480///
2481/// (This `Debug` representation currently emits the same string as the
2482/// `Display` representation, but this is not a guarantee.)
2483///
2484/// Options currently supported:
2485///
2486/// * [`std::fmt::Formatter::precision`] can be set to control the precision
2487/// of the fractional second component.
2488///
2489/// # Example
2490///
2491/// ```
2492/// use jiff::civil::date;
2493///
2494/// let dt = date(2024, 6, 15).at(7, 0, 0, 123_000_000);
2495/// assert_eq!(format!("{dt:.6?}"), "2024-06-15T07:00:00.123000");
2496/// // Precision values greater than 9 are clamped to 9.
2497/// assert_eq!(format!("{dt:.300?}"), "2024-06-15T07:00:00.123000000");
2498/// // A precision of 0 implies the entire fractional
2499/// // component is always truncated.
2500/// assert_eq!(format!("{dt:.0?}"), "2024-06-15T07:00:00");
2501///
2502/// # Ok::<(), Box<dyn std::error::Error>>(())
2503/// ```
2504impl core::fmt::Debug for DateTime {
2505 #[inline]
2506 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
2507 core::fmt::Display::fmt(self, f)
2508 }
2509}
2510
2511/// Converts a `DateTime` into an ISO 8601 compliant string.
2512///
2513/// # Formatting options supported
2514///
2515/// * [`std::fmt::Formatter::precision`] can be set to control the precision
2516/// of the fractional second component. When not set, the minimum precision
2517/// required to losslessly render the value is used.
2518///
2519/// # Example
2520///
2521/// This shows the default rendering:
2522///
2523/// ```
2524/// use jiff::civil::date;
2525///
2526/// // No fractional seconds:
2527/// let dt = date(2024, 6, 15).at(7, 0, 0, 0);
2528/// assert_eq!(format!("{dt}"), "2024-06-15T07:00:00");
2529///
2530/// // With fractional seconds:
2531/// let dt = date(2024, 6, 15).at(7, 0, 0, 123_000_000);
2532/// assert_eq!(format!("{dt}"), "2024-06-15T07:00:00.123");
2533///
2534/// # Ok::<(), Box<dyn std::error::Error>>(())
2535/// ```
2536///
2537/// # Example: setting the precision
2538///
2539/// ```
2540/// use jiff::civil::date;
2541///
2542/// let dt = date(2024, 6, 15).at(7, 0, 0, 123_000_000);
2543/// assert_eq!(format!("{dt:.6}"), "2024-06-15T07:00:00.123000");
2544/// // Precision values greater than 9 are clamped to 9.
2545/// assert_eq!(format!("{dt:.300}"), "2024-06-15T07:00:00.123000000");
2546/// // A precision of 0 implies the entire fractional
2547/// // component is always truncated.
2548/// assert_eq!(format!("{dt:.0}"), "2024-06-15T07:00:00");
2549///
2550/// # Ok::<(), Box<dyn std::error::Error>>(())
2551/// ```
2552impl core::fmt::Display for DateTime {
2553 #[inline]
2554 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
2555 use crate::fmt::StdFmtWrite;
2556
2557 let precision =
2558 f.precision().map(|p| u8::try_from(p).unwrap_or(u8::MAX));
2559 temporal::DateTimePrinter::new()
2560 .precision(precision)
2561 .print_datetime(self, StdFmtWrite(f))
2562 .map_err(|_| core::fmt::Error)
2563 }
2564}
2565
2566impl core::str::FromStr for DateTime {
2567 type Err = Error;
2568
2569 #[inline]
2570 fn from_str(string: &str) -> Result<DateTime, Error> {
2571 DEFAULT_DATETIME_PARSER.parse_datetime(string)
2572 }
2573}
2574
2575/// Converts a [`Date`] to a [`DateTime`] with the time set to midnight.
2576impl From<Date> for DateTime {
2577 #[inline]
2578 fn from(date: Date) -> DateTime {
2579 date.to_datetime(Time::midnight())
2580 }
2581}
2582
2583/// Converts a [`Zoned`] to a [`DateTime`].
2584impl From<Zoned> for DateTime {
2585 #[inline]
2586 fn from(zdt: Zoned) -> DateTime {
2587 zdt.datetime()
2588 }
2589}
2590
2591/// Converts a [`&Zoned`](Zoned) to a [`DateTime`].
2592impl<'a> From<&'a Zoned> for DateTime {
2593 #[inline]
2594 fn from(zdt: &'a Zoned) -> DateTime {
2595 zdt.datetime()
2596 }
2597}
2598
2599/// Adds a span of time to a datetime.
2600///
2601/// This uses checked arithmetic and panics on overflow. To handle overflow
2602/// without panics, use [`DateTime::checked_add`].
2603impl core::ops::Add<Span> for DateTime {
2604 type Output = DateTime;
2605
2606 #[inline]
2607 fn add(self, rhs: Span) -> DateTime {
2608 self.checked_add(rhs).expect("adding span to datetime overflowed")
2609 }
2610}
2611
2612/// Adds a span of time to a datetime in place.
2613///
2614/// This uses checked arithmetic and panics on overflow. To handle overflow
2615/// without panics, use [`DateTime::checked_add`].
2616impl core::ops::AddAssign<Span> for DateTime {
2617 #[inline]
2618 fn add_assign(&mut self, rhs: Span) {
2619 *self = *self + rhs
2620 }
2621}
2622
2623/// Subtracts a span of time from a datetime.
2624///
2625/// This uses checked arithmetic and panics on overflow. To handle overflow
2626/// without panics, use [`DateTime::checked_sub`].
2627impl core::ops::Sub<Span> for DateTime {
2628 type Output = DateTime;
2629
2630 #[inline]
2631 fn sub(self, rhs: Span) -> DateTime {
2632 self.checked_sub(rhs)
2633 .expect("subtracting span from datetime overflowed")
2634 }
2635}
2636
2637/// Subtracts a span of time from a datetime in place.
2638///
2639/// This uses checked arithmetic and panics on overflow. To handle overflow
2640/// without panics, use [`DateTime::checked_sub`].
2641impl core::ops::SubAssign<Span> for DateTime {
2642 #[inline]
2643 fn sub_assign(&mut self, rhs: Span) {
2644 *self = *self - rhs
2645 }
2646}
2647
2648/// Computes the span of time between two datetimes.
2649///
2650/// This will return a negative span when the datetime being subtracted is
2651/// greater.
2652///
2653/// Since this uses the default configuration for calculating a span between
2654/// two datetimes (no rounding and largest units is days), this will never
2655/// panic or fail in any way. It is guaranteed that the largest non-zero
2656/// unit in the `Span` returned will be days.
2657///
2658/// To configure the largest unit or enable rounding, use [`DateTime::since`].
2659///
2660/// If you need a [`SignedDuration`] representing the span between two civil
2661/// datetimes, then use [`DateTime::duration_since`].
2662impl core::ops::Sub for DateTime {
2663 type Output = Span;
2664
2665 #[inline]
2666 fn sub(self, rhs: DateTime) -> Span {
2667 self.since(rhs).expect("since never fails when given DateTime")
2668 }
2669}
2670
2671/// Adds a signed duration of time to a datetime.
2672///
2673/// This uses checked arithmetic and panics on overflow. To handle overflow
2674/// without panics, use [`DateTime::checked_add`].
2675impl core::ops::Add<SignedDuration> for DateTime {
2676 type Output = DateTime;
2677
2678 #[inline]
2679 fn add(self, rhs: SignedDuration) -> DateTime {
2680 self.checked_add(rhs)
2681 .expect("adding signed duration to datetime overflowed")
2682 }
2683}
2684
2685/// Adds a signed duration of time to a datetime in place.
2686///
2687/// This uses checked arithmetic and panics on overflow. To handle overflow
2688/// without panics, use [`DateTime::checked_add`].
2689impl core::ops::AddAssign<SignedDuration> for DateTime {
2690 #[inline]
2691 fn add_assign(&mut self, rhs: SignedDuration) {
2692 *self = *self + rhs
2693 }
2694}
2695
2696/// Subtracts a signed duration of time from a datetime.
2697///
2698/// This uses checked arithmetic and panics on overflow. To handle overflow
2699/// without panics, use [`DateTime::checked_sub`].
2700impl core::ops::Sub<SignedDuration> for DateTime {
2701 type Output = DateTime;
2702
2703 #[inline]
2704 fn sub(self, rhs: SignedDuration) -> DateTime {
2705 self.checked_sub(rhs)
2706 .expect("subtracting signed duration from datetime overflowed")
2707 }
2708}
2709
2710/// Subtracts a signed duration of time from a datetime in place.
2711///
2712/// This uses checked arithmetic and panics on overflow. To handle overflow
2713/// without panics, use [`DateTime::checked_sub`].
2714impl core::ops::SubAssign<SignedDuration> for DateTime {
2715 #[inline]
2716 fn sub_assign(&mut self, rhs: SignedDuration) {
2717 *self = *self - rhs
2718 }
2719}
2720
2721/// Adds an unsigned duration of time to a datetime.
2722///
2723/// This uses checked arithmetic and panics on overflow. To handle overflow
2724/// without panics, use [`DateTime::checked_add`].
2725impl core::ops::Add<UnsignedDuration> for DateTime {
2726 type Output = DateTime;
2727
2728 #[inline]
2729 fn add(self, rhs: UnsignedDuration) -> DateTime {
2730 self.checked_add(rhs)
2731 .expect("adding unsigned duration to datetime overflowed")
2732 }
2733}
2734
2735/// Adds an unsigned duration of time to a datetime in place.
2736///
2737/// This uses checked arithmetic and panics on overflow. To handle overflow
2738/// without panics, use [`DateTime::checked_add`].
2739impl core::ops::AddAssign<UnsignedDuration> for DateTime {
2740 #[inline]
2741 fn add_assign(&mut self, rhs: UnsignedDuration) {
2742 *self = *self + rhs
2743 }
2744}
2745
2746/// Subtracts an unsigned duration of time from a datetime.
2747///
2748/// This uses checked arithmetic and panics on overflow. To handle overflow
2749/// without panics, use [`DateTime::checked_sub`].
2750impl core::ops::Sub<UnsignedDuration> for DateTime {
2751 type Output = DateTime;
2752
2753 #[inline]
2754 fn sub(self, rhs: UnsignedDuration) -> DateTime {
2755 self.checked_sub(rhs)
2756 .expect("subtracting unsigned duration from datetime overflowed")
2757 }
2758}
2759
2760/// Subtracts an unsigned duration of time from a datetime in place.
2761///
2762/// This uses checked arithmetic and panics on overflow. To handle overflow
2763/// without panics, use [`DateTime::checked_sub`].
2764impl core::ops::SubAssign<UnsignedDuration> for DateTime {
2765 #[inline]
2766 fn sub_assign(&mut self, rhs: UnsignedDuration) {
2767 *self = *self - rhs
2768 }
2769}
2770
2771#[cfg(feature = "serde")]
2772impl serde_core::Serialize for DateTime {
2773 #[inline]
2774 fn serialize<S: serde_core::Serializer>(
2775 &self,
2776 serializer: S,
2777 ) -> Result<S::Ok, S::Error> {
2778 serializer.collect_str(self)
2779 }
2780}
2781
2782#[cfg(feature = "serde")]
2783impl<'de> serde_core::Deserialize<'de> for DateTime {
2784 #[inline]
2785 fn deserialize<D: serde_core::Deserializer<'de>>(
2786 deserializer: D,
2787 ) -> Result<DateTime, D::Error> {
2788 use serde_core::de;
2789
2790 struct DateTimeVisitor;
2791
2792 impl<'de> de::Visitor<'de> for DateTimeVisitor {
2793 type Value = DateTime;
2794
2795 fn expecting(
2796 &self,
2797 f: &mut core::fmt::Formatter,
2798 ) -> core::fmt::Result {
2799 f.write_str("a datetime string")
2800 }
2801
2802 #[inline]
2803 fn visit_bytes<E: de::Error>(
2804 self,
2805 value: &[u8],
2806 ) -> Result<DateTime, E> {
2807 DEFAULT_DATETIME_PARSER
2808 .parse_datetime(value)
2809 .map_err(de::Error::custom)
2810 }
2811
2812 #[inline]
2813 fn visit_str<E: de::Error>(
2814 self,
2815 value: &str,
2816 ) -> Result<DateTime, E> {
2817 self.visit_bytes(value.as_bytes())
2818 }
2819 }
2820
2821 deserializer.deserialize_str(DateTimeVisitor)
2822 }
2823}
2824
2825#[cfg(test)]
2826impl quickcheck::Arbitrary for DateTime {
2827 fn arbitrary(g: &mut quickcheck::Gen) -> DateTime {
2828 let date = Date::arbitrary(g);
2829 let time = Time::arbitrary(g);
2830 DateTime::from_parts(date, time)
2831 }
2832
2833 fn shrink(&self) -> alloc::boxed::Box<dyn Iterator<Item = DateTime>> {
2834 alloc::boxed::Box::new(
2835 (self.date(), self.time())
2836 .shrink()
2837 .map(|(date, time)| DateTime::from_parts(date, time)),
2838 )
2839 }
2840}
2841
2842/// An iterator over periodic datetimes, created by [`DateTime::series`].
2843///
2844/// It is exhausted when the next value would exceed the limits of a [`Span`]
2845/// or [`DateTime`] value.
2846///
2847/// This iterator is created by [`DateTime::series`].
2848#[derive(Clone, Debug)]
2849pub struct DateTimeSeries {
2850 start: DateTime,
2851 period: Span,
2852 step: i64,
2853}
2854
2855impl Iterator for DateTimeSeries {
2856 type Item = DateTime;
2857
2858 #[inline]
2859 fn next(&mut self) -> Option<DateTime> {
2860 let span = self.period.checked_mul(self.step).ok()?;
2861 self.step = self.step.checked_add(1)?;
2862 let date = self.start.checked_add(span).ok()?;
2863 Some(date)
2864 }
2865}
2866
2867impl core::iter::FusedIterator for DateTimeSeries {}
2868
2869/// Options for [`DateTime::checked_add`] and [`DateTime::checked_sub`].
2870///
2871/// This type provides a way to ergonomically add one of a few different
2872/// duration types to a [`DateTime`].
2873///
2874/// The main way to construct values of this type is with its `From` trait
2875/// implementations:
2876///
2877/// * `From<Span> for DateTimeArithmetic` adds (or subtracts) the given span to
2878/// the receiver datetime.
2879/// * `From<SignedDuration> for DateTimeArithmetic` adds (or subtracts)
2880/// the given signed duration to the receiver datetime.
2881/// * `From<std::time::Duration> for DateTimeArithmetic` adds (or subtracts)
2882/// the given unsigned duration to the receiver datetime.
2883///
2884/// # Example
2885///
2886/// ```
2887/// use std::time::Duration;
2888///
2889/// use jiff::{civil::date, SignedDuration, ToSpan};
2890///
2891/// let dt = date(2024, 2, 29).at(0, 0, 0, 0);
2892/// assert_eq!(
2893/// dt.checked_add(1.year())?,
2894/// date(2025, 2, 28).at(0, 0, 0, 0),
2895/// );
2896/// assert_eq!(
2897/// dt.checked_add(SignedDuration::from_hours(24))?,
2898/// date(2024, 3, 1).at(0, 0, 0, 0),
2899/// );
2900/// assert_eq!(
2901/// dt.checked_add(Duration::from_secs(24 * 60 * 60))?,
2902/// date(2024, 3, 1).at(0, 0, 0, 0),
2903/// );
2904///
2905/// # Ok::<(), Box<dyn std::error::Error>>(())
2906/// ```
2907#[derive(Clone, Copy, Debug)]
2908pub struct DateTimeArithmetic {
2909 duration: Duration,
2910}
2911
2912impl DateTimeArithmetic {
2913 #[inline]
2914 fn checked_add(self, dt: DateTime) -> Result<DateTime, Error> {
2915 match self.duration.to_signed()? {
2916 SDuration::Span(span) => dt.checked_add_span(span),
2917 SDuration::Absolute(sdur) => dt.checked_add_duration(sdur),
2918 }
2919 }
2920
2921 #[inline]
2922 fn checked_neg(self) -> Result<DateTimeArithmetic, Error> {
2923 let duration = self.duration.checked_neg()?;
2924 Ok(DateTimeArithmetic { duration })
2925 }
2926
2927 #[inline]
2928 fn is_negative(&self) -> bool {
2929 self.duration.is_negative()
2930 }
2931}
2932
2933impl From<Span> for DateTimeArithmetic {
2934 fn from(span: Span) -> DateTimeArithmetic {
2935 let duration = Duration::from(span);
2936 DateTimeArithmetic { duration }
2937 }
2938}
2939
2940impl From<SignedDuration> for DateTimeArithmetic {
2941 fn from(sdur: SignedDuration) -> DateTimeArithmetic {
2942 let duration = Duration::from(sdur);
2943 DateTimeArithmetic { duration }
2944 }
2945}
2946
2947impl From<UnsignedDuration> for DateTimeArithmetic {
2948 fn from(udur: UnsignedDuration) -> DateTimeArithmetic {
2949 let duration = Duration::from(udur);
2950 DateTimeArithmetic { duration }
2951 }
2952}
2953
2954impl<'a> From<&'a Span> for DateTimeArithmetic {
2955 fn from(span: &'a Span) -> DateTimeArithmetic {
2956 DateTimeArithmetic::from(*span)
2957 }
2958}
2959
2960impl<'a> From<&'a SignedDuration> for DateTimeArithmetic {
2961 fn from(sdur: &'a SignedDuration) -> DateTimeArithmetic {
2962 DateTimeArithmetic::from(*sdur)
2963 }
2964}
2965
2966impl<'a> From<&'a UnsignedDuration> for DateTimeArithmetic {
2967 fn from(udur: &'a UnsignedDuration) -> DateTimeArithmetic {
2968 DateTimeArithmetic::from(*udur)
2969 }
2970}
2971
2972/// Options for [`DateTime::since`] and [`DateTime::until`].
2973///
2974/// This type provides a way to configure the calculation of
2975/// spans between two [`DateTime`] values. In particular, both
2976/// `DateTime::since` and `DateTime::until` accept anything that implements
2977/// `Into<DateTimeDifference>`. There are a few key trait implementations that
2978/// make this convenient:
2979///
2980/// * `From<DateTime> for DateTimeDifference` will construct a configuration
2981/// consisting of just the datetime. So for example, `dt1.since(dt2)` returns
2982/// the span from `dt2` to `dt1`.
2983/// * `From<Date> for DateTimeDifference` will construct a configuration
2984/// consisting of just the datetime built from the date given at midnight on
2985/// that day.
2986/// * `From<(Unit, DateTime)>` is a convenient way to specify the largest units
2987/// that should be present on the span returned. By default, the largest units
2988/// are days. Using this trait implementation is equivalent to
2989/// `DateTimeDifference::new(datetime).largest(unit)`.
2990/// * `From<(Unit, Date)>` is like the one above, but with the time component
2991/// fixed to midnight.
2992///
2993/// One can also provide a `DateTimeDifference` value directly. Doing so
2994/// is necessary to use the rounding features of calculating a span. For
2995/// example, setting the smallest unit (defaults to [`Unit::Nanosecond`]), the
2996/// rounding mode (defaults to [`RoundMode::Trunc`]) and the rounding increment
2997/// (defaults to `1`). The defaults are selected such that no rounding occurs.
2998///
2999/// Rounding a span as part of calculating it is provided as a convenience.
3000/// Callers may choose to round the span as a distinct step via
3001/// [`Span::round`], but callers may need to provide a reference date
3002/// for rounding larger units. By coupling rounding with routines like
3003/// [`DateTime::since`], the reference date can be set automatically based on
3004/// the input to `DateTime::since`.
3005///
3006/// # Example
3007///
3008/// This example shows how to round a span between two datetimes to the nearest
3009/// half-hour, with ties breaking away from zero.
3010///
3011/// ```
3012/// use jiff::{civil::{DateTime, DateTimeDifference}, RoundMode, ToSpan, Unit};
3013///
3014/// let dt1 = "2024-03-15 08:14:00.123456789".parse::<DateTime>()?;
3015/// let dt2 = "2030-03-22 15:00".parse::<DateTime>()?;
3016/// let span = dt1.until(
3017/// DateTimeDifference::new(dt2)
3018/// .smallest(Unit::Minute)
3019/// .largest(Unit::Year)
3020/// .mode(RoundMode::HalfExpand)
3021/// .increment(30),
3022/// )?;
3023/// assert_eq!(span, 6.years().days(7).hours(7).fieldwise());
3024///
3025/// # Ok::<(), Box<dyn std::error::Error>>(())
3026/// ```
3027#[derive(Clone, Copy, Debug)]
3028pub struct DateTimeDifference {
3029 datetime: DateTime,
3030 round: SpanRound<'static>,
3031}
3032
3033impl DateTimeDifference {
3034 /// Create a new default configuration for computing the span between the
3035 /// given datetime and some other datetime (specified as the receiver in
3036 /// [`DateTime::since`] or [`DateTime::until`]).
3037 #[inline]
3038 pub fn new(datetime: DateTime) -> DateTimeDifference {
3039 // We use truncation rounding by default since it seems that's
3040 // what is generally expected when computing the difference between
3041 // datetimes.
3042 //
3043 // See: https://github.com/tc39/proposal-temporal/issues/1122
3044 let round = SpanRound::new().mode(RoundMode::Trunc);
3045 DateTimeDifference { datetime, round }
3046 }
3047
3048 /// Set the smallest units allowed in the span returned.
3049 ///
3050 /// When a largest unit is not specified and the smallest unit is days
3051 /// or greater, then the largest unit is automatically set to be equal to
3052 /// the smallest unit.
3053 ///
3054 /// # Errors
3055 ///
3056 /// The smallest units must be no greater than the largest units. If this
3057 /// is violated, then computing a span with this configuration will result
3058 /// in an error.
3059 ///
3060 /// # Example
3061 ///
3062 /// This shows how to round a span between two datetimes to the nearest
3063 /// number of weeks.
3064 ///
3065 /// ```
3066 /// use jiff::{
3067 /// civil::{DateTime, DateTimeDifference},
3068 /// RoundMode, ToSpan, Unit,
3069 /// };
3070 ///
3071 /// let dt1 = "2024-03-15 08:14".parse::<DateTime>()?;
3072 /// let dt2 = "2030-11-22 08:30".parse::<DateTime>()?;
3073 /// let span = dt1.until(
3074 /// DateTimeDifference::new(dt2)
3075 /// .smallest(Unit::Week)
3076 /// .largest(Unit::Week)
3077 /// .mode(RoundMode::HalfExpand),
3078 /// )?;
3079 /// assert_eq!(span, 349.weeks().fieldwise());
3080 ///
3081 /// # Ok::<(), Box<dyn std::error::Error>>(())
3082 /// ```
3083 #[inline]
3084 pub fn smallest(self, unit: Unit) -> DateTimeDifference {
3085 DateTimeDifference { round: self.round.smallest(unit), ..self }
3086 }
3087
3088 /// Set the largest units allowed in the span returned.
3089 ///
3090 /// When a largest unit is not specified and the smallest unit is days
3091 /// or greater, then the largest unit is automatically set to be equal to
3092 /// the smallest unit. Otherwise, when the largest unit is not specified,
3093 /// it is set to days.
3094 ///
3095 /// Once a largest unit is set, there is no way to change this rounding
3096 /// configuration back to using the "automatic" default. Instead, callers
3097 /// must create a new configuration.
3098 ///
3099 /// # Errors
3100 ///
3101 /// The largest units, when set, must be at least as big as the smallest
3102 /// units (which defaults to [`Unit::Nanosecond`]). If this is violated,
3103 /// then computing a span with this configuration will result in an error.
3104 ///
3105 /// # Example
3106 ///
3107 /// This shows how to round a span between two datetimes to units no
3108 /// bigger than seconds.
3109 ///
3110 /// ```
3111 /// use jiff::{civil::{DateTime, DateTimeDifference}, ToSpan, Unit};
3112 ///
3113 /// let dt1 = "2024-03-15 08:14".parse::<DateTime>()?;
3114 /// let dt2 = "2030-11-22 08:30".parse::<DateTime>()?;
3115 /// let span = dt1.until(
3116 /// DateTimeDifference::new(dt2).largest(Unit::Second),
3117 /// )?;
3118 /// assert_eq!(span, 211076160.seconds().fieldwise());
3119 ///
3120 /// # Ok::<(), Box<dyn std::error::Error>>(())
3121 /// ```
3122 #[inline]
3123 pub fn largest(self, unit: Unit) -> DateTimeDifference {
3124 DateTimeDifference { round: self.round.largest(unit), ..self }
3125 }
3126
3127 /// Set the rounding mode.
3128 ///
3129 /// This defaults to [`RoundMode::Trunc`] since it's plausible that
3130 /// rounding "up" in the context of computing the span between
3131 /// two datetimes could be surprising in a number of cases. The
3132 /// [`RoundMode::HalfExpand`] mode corresponds to typical rounding you
3133 /// might have learned about in school. But a variety of other rounding
3134 /// modes exist.
3135 ///
3136 /// # Example
3137 ///
3138 /// This shows how to always round "up" towards positive infinity.
3139 ///
3140 /// ```
3141 /// use jiff::{
3142 /// civil::{DateTime, DateTimeDifference},
3143 /// RoundMode, ToSpan, Unit,
3144 /// };
3145 ///
3146 /// let dt1 = "2024-03-15 08:10".parse::<DateTime>()?;
3147 /// let dt2 = "2024-03-15 08:11".parse::<DateTime>()?;
3148 /// let span = dt1.until(
3149 /// DateTimeDifference::new(dt2)
3150 /// .smallest(Unit::Hour)
3151 /// .mode(RoundMode::Ceil),
3152 /// )?;
3153 /// // Only one minute elapsed, but we asked to always round up!
3154 /// assert_eq!(span, 1.hour().fieldwise());
3155 ///
3156 /// // Since `Ceil` always rounds toward positive infinity, the behavior
3157 /// // flips for a negative span.
3158 /// let span = dt1.since(
3159 /// DateTimeDifference::new(dt2)
3160 /// .smallest(Unit::Hour)
3161 /// .mode(RoundMode::Ceil),
3162 /// )?;
3163 /// assert_eq!(span, 0.hour().fieldwise());
3164 ///
3165 /// # Ok::<(), Box<dyn std::error::Error>>(())
3166 /// ```
3167 #[inline]
3168 pub fn mode(self, mode: RoundMode) -> DateTimeDifference {
3169 DateTimeDifference { round: self.round.mode(mode), ..self }
3170 }
3171
3172 /// Set the rounding increment for the smallest unit.
3173 ///
3174 /// The default value is `1`. Other values permit rounding the smallest
3175 /// unit to the nearest integer increment specified. For example, if the
3176 /// smallest unit is set to [`Unit::Minute`], then a rounding increment of
3177 /// `30` would result in rounding in increments of a half hour. That is,
3178 /// the only minute value that could result would be `0` or `30`.
3179 ///
3180 /// # Errors
3181 ///
3182 /// When the smallest unit is less than days, the rounding increment must
3183 /// divide evenly into the next highest unit after the smallest unit
3184 /// configured (and must not be equivalent to it). For example, if the
3185 /// smallest unit is [`Unit::Nanosecond`], then *some* of the valid values
3186 /// for the rounding increment are `1`, `2`, `4`, `5`, `100` and `500`.
3187 /// Namely, any integer that divides evenly into `1,000` nanoseconds since
3188 /// there are `1,000` nanoseconds in the next highest unit (microseconds).
3189 ///
3190 /// The error will occur when computing the span, and not when setting
3191 /// the increment here.
3192 ///
3193 /// # Example
3194 ///
3195 /// This shows how to round the span between two datetimes to the nearest
3196 /// 5 minute increment.
3197 ///
3198 /// ```
3199 /// use jiff::{
3200 /// civil::{DateTime, DateTimeDifference},
3201 /// RoundMode, ToSpan, Unit,
3202 /// };
3203 ///
3204 /// let dt1 = "2024-03-15 08:19".parse::<DateTime>()?;
3205 /// let dt2 = "2024-03-15 12:52".parse::<DateTime>()?;
3206 /// let span = dt1.until(
3207 /// DateTimeDifference::new(dt2)
3208 /// .smallest(Unit::Minute)
3209 /// .increment(5)
3210 /// .mode(RoundMode::HalfExpand),
3211 /// )?;
3212 /// assert_eq!(span, 4.hour().minutes(35).fieldwise());
3213 ///
3214 /// # Ok::<(), Box<dyn std::error::Error>>(())
3215 /// ```
3216 #[inline]
3217 pub fn increment(self, increment: i64) -> DateTimeDifference {
3218 DateTimeDifference { round: self.round.increment(increment), ..self }
3219 }
3220
3221 /// Returns true if and only if this configuration could change the span
3222 /// via rounding.
3223 #[inline]
3224 fn rounding_may_change_span(&self) -> bool {
3225 self.round.rounding_may_change_span_ignore_largest()
3226 }
3227
3228 /// Returns the span of time from `dt1` to the datetime in this
3229 /// configuration. The biggest units allowed are determined by the
3230 /// `smallest` and `largest` settings, but defaults to `Unit::Day`.
3231 #[inline]
3232 fn until_with_largest_unit(&self, dt1: DateTime) -> Result<Span, Error> {
3233 let dt2 = self.datetime;
3234 let largest = self
3235 .round
3236 .get_largest()
3237 .unwrap_or_else(|| self.round.get_smallest().max(Unit::Day));
3238 if largest <= Unit::Day {
3239 let diff = dt2.to_nanosecond() - dt1.to_nanosecond();
3240 // Note that this can fail! If largest unit is nanoseconds and the
3241 // datetimes are far enough apart, a single i64 won't be able to
3242 // represent the time difference.
3243 //
3244 // This is only true for nanoseconds. A single i64 in units of
3245 // microseconds can represent the interval between all valid
3246 // datetimes. (At time of writing.)
3247 return Span::from_invariant_nanoseconds(largest, diff);
3248 }
3249
3250 let (d1, mut d2) = (dt1.date(), dt2.date());
3251 let (t1, t2) = (dt1.time(), dt2.time());
3252 let sign = t::sign(d2, d1);
3253 let mut time_diff = t1.until_nanoseconds(t2);
3254 if time_diff.signum() == -sign {
3255 // These unwraps will always succeed, but the argument for why is
3256 // subtle. The key here is that the only way, e.g., d2.tomorrow()
3257 // can fail is when d2 is the max date. But, if d2 is the max date,
3258 // then it's impossible for `sign < 0` since the max date is at
3259 // least as big as every other date. And thus, d2.tomorrow() is
3260 // never reached in cases where it would fail.
3261 if sign > C(0) {
3262 d2 = d2.yesterday().unwrap();
3263 } else if sign < C(0) {
3264 d2 = d2.tomorrow().unwrap();
3265 }
3266 time_diff +=
3267 t::SpanNanoseconds::rfrom(t::NANOS_PER_CIVIL_DAY) * sign;
3268 }
3269 let date_span = d1.until((largest, d2))?;
3270 Ok(Span::from_invariant_nanoseconds(largest, time_diff.rinto())
3271 // Unlike in the <=Unit::Day case, this always succeeds because
3272 // every unit except for nanoseconds (which is not used here) can
3273 // represent all possible spans of time between any two civil
3274 // datetimes.
3275 .expect("difference between time always fits in span")
3276 .years_ranged(date_span.get_years_ranged())
3277 .months_ranged(date_span.get_months_ranged())
3278 .weeks_ranged(date_span.get_weeks_ranged())
3279 .days_ranged(date_span.get_days_ranged()))
3280 }
3281}
3282
3283impl From<DateTime> for DateTimeDifference {
3284 #[inline]
3285 fn from(dt: DateTime) -> DateTimeDifference {
3286 DateTimeDifference::new(dt)
3287 }
3288}
3289
3290impl From<Date> for DateTimeDifference {
3291 #[inline]
3292 fn from(date: Date) -> DateTimeDifference {
3293 DateTimeDifference::from(DateTime::from(date))
3294 }
3295}
3296
3297impl From<Zoned> for DateTimeDifference {
3298 #[inline]
3299 fn from(zdt: Zoned) -> DateTimeDifference {
3300 DateTimeDifference::from(DateTime::from(zdt))
3301 }
3302}
3303
3304impl<'a> From<&'a Zoned> for DateTimeDifference {
3305 #[inline]
3306 fn from(zdt: &'a Zoned) -> DateTimeDifference {
3307 DateTimeDifference::from(zdt.datetime())
3308 }
3309}
3310
3311impl From<(Unit, DateTime)> for DateTimeDifference {
3312 #[inline]
3313 fn from((largest, dt): (Unit, DateTime)) -> DateTimeDifference {
3314 DateTimeDifference::from(dt).largest(largest)
3315 }
3316}
3317
3318impl From<(Unit, Date)> for DateTimeDifference {
3319 #[inline]
3320 fn from((largest, date): (Unit, Date)) -> DateTimeDifference {
3321 DateTimeDifference::from(date).largest(largest)
3322 }
3323}
3324
3325impl From<(Unit, Zoned)> for DateTimeDifference {
3326 #[inline]
3327 fn from((largest, zdt): (Unit, Zoned)) -> DateTimeDifference {
3328 DateTimeDifference::from((largest, DateTime::from(zdt)))
3329 }
3330}
3331
3332impl<'a> From<(Unit, &'a Zoned)> for DateTimeDifference {
3333 #[inline]
3334 fn from((largest, zdt): (Unit, &'a Zoned)) -> DateTimeDifference {
3335 DateTimeDifference::from((largest, zdt.datetime()))
3336 }
3337}
3338
3339/// Options for [`DateTime::round`].
3340///
3341/// This type provides a way to configure the rounding of a civil datetime. In
3342/// particular, `DateTime::round` accepts anything that implements the
3343/// `Into<DateTimeRound>` trait. There are some trait implementations that
3344/// therefore make calling `DateTime::round` in some common cases more
3345/// ergonomic:
3346///
3347/// * `From<Unit> for DateTimeRound` will construct a rounding
3348/// configuration that rounds to the unit given. Specifically,
3349/// `DateTimeRound::new().smallest(unit)`.
3350/// * `From<(Unit, i64)> for DateTimeRound` is like the one above, but also
3351/// specifies the rounding increment for [`DateTimeRound::increment`].
3352///
3353/// Note that in the default configuration, no rounding occurs.
3354///
3355/// # Example
3356///
3357/// This example shows how to round a datetime to the nearest second:
3358///
3359/// ```
3360/// use jiff::{civil::{DateTime, date}, Unit};
3361///
3362/// let dt: DateTime = "2024-06-20 16:24:59.5".parse()?;
3363/// assert_eq!(
3364/// dt.round(Unit::Second)?,
3365/// // The second rounds up and causes minutes to increase.
3366/// date(2024, 6, 20).at(16, 25, 0, 0),
3367/// );
3368///
3369/// # Ok::<(), Box<dyn std::error::Error>>(())
3370/// ```
3371///
3372/// The above makes use of the fact that `Unit` implements
3373/// `Into<DateTimeRound>`. If you want to change the rounding mode to, say,
3374/// truncation, then you'll need to construct a `DateTimeRound` explicitly
3375/// since there are no convenience `Into` trait implementations for
3376/// [`RoundMode`].
3377///
3378/// ```
3379/// use jiff::{civil::{DateTime, DateTimeRound, date}, RoundMode, Unit};
3380///
3381/// let dt: DateTime = "2024-06-20 16:24:59.5".parse()?;
3382/// assert_eq!(
3383/// dt.round(
3384/// DateTimeRound::new().smallest(Unit::Second).mode(RoundMode::Trunc),
3385/// )?,
3386/// // The second just gets truncated as if it wasn't there.
3387/// date(2024, 6, 20).at(16, 24, 59, 0),
3388/// );
3389///
3390/// # Ok::<(), Box<dyn std::error::Error>>(())
3391/// ```
3392#[derive(Clone, Copy, Debug)]
3393pub struct DateTimeRound {
3394 smallest: Unit,
3395 mode: RoundMode,
3396 increment: i64,
3397}
3398
3399impl DateTimeRound {
3400 /// Create a new default configuration for rounding a [`DateTime`].
3401 #[inline]
3402 pub fn new() -> DateTimeRound {
3403 DateTimeRound {
3404 smallest: Unit::Nanosecond,
3405 mode: RoundMode::HalfExpand,
3406 increment: 1,
3407 }
3408 }
3409
3410 /// Set the smallest units allowed in the datetime returned after rounding.
3411 ///
3412 /// Any units below the smallest configured unit will be used, along with
3413 /// the rounding increment and rounding mode, to determine the value of the
3414 /// smallest unit. For example, when rounding `2024-06-20T03:25:30` to the
3415 /// nearest minute, the `30` second unit will result in rounding the minute
3416 /// unit of `25` up to `26` and zeroing out everything below minutes.
3417 ///
3418 /// This defaults to [`Unit::Nanosecond`].
3419 ///
3420 /// # Errors
3421 ///
3422 /// The smallest units must be no greater than [`Unit::Day`]. And when the
3423 /// smallest unit is `Unit::Day`, the rounding increment must be equal to
3424 /// `1`. Otherwise an error will be returned from [`DateTime::round`].
3425 ///
3426 /// # Example
3427 ///
3428 /// ```
3429 /// use jiff::{civil::{DateTimeRound, date}, Unit};
3430 ///
3431 /// let dt = date(2024, 6, 20).at(3, 25, 30, 0);
3432 /// assert_eq!(
3433 /// dt.round(DateTimeRound::new().smallest(Unit::Minute))?,
3434 /// date(2024, 6, 20).at(3, 26, 0, 0),
3435 /// );
3436 /// // Or, utilize the `From<Unit> for DateTimeRound` impl:
3437 /// assert_eq!(
3438 /// dt.round(Unit::Minute)?,
3439 /// date(2024, 6, 20).at(3, 26, 0, 0),
3440 /// );
3441 ///
3442 /// # Ok::<(), Box<dyn std::error::Error>>(())
3443 /// ```
3444 #[inline]
3445 pub fn smallest(self, unit: Unit) -> DateTimeRound {
3446 DateTimeRound { smallest: unit, ..self }
3447 }
3448
3449 /// Set the rounding mode.
3450 ///
3451 /// This defaults to [`RoundMode::HalfExpand`], which rounds away from
3452 /// zero. It matches the kind of rounding you might have been taught in
3453 /// school.
3454 ///
3455 /// # Example
3456 ///
3457 /// This shows how to always round datetimes up towards positive infinity.
3458 ///
3459 /// ```
3460 /// use jiff::{civil::{DateTime, DateTimeRound, date}, RoundMode, Unit};
3461 ///
3462 /// let dt: DateTime = "2024-06-20 03:25:01".parse()?;
3463 /// assert_eq!(
3464 /// dt.round(
3465 /// DateTimeRound::new()
3466 /// .smallest(Unit::Minute)
3467 /// .mode(RoundMode::Ceil),
3468 /// )?,
3469 /// date(2024, 6, 20).at(3, 26, 0, 0),
3470 /// );
3471 ///
3472 /// # Ok::<(), Box<dyn std::error::Error>>(())
3473 /// ```
3474 #[inline]
3475 pub fn mode(self, mode: RoundMode) -> DateTimeRound {
3476 DateTimeRound { mode, ..self }
3477 }
3478
3479 /// Set the rounding increment for the smallest unit.
3480 ///
3481 /// The default value is `1`. Other values permit rounding the smallest
3482 /// unit to the nearest integer increment specified. For example, if the
3483 /// smallest unit is set to [`Unit::Minute`], then a rounding increment of
3484 /// `30` would result in rounding in increments of a half hour. That is,
3485 /// the only minute value that could result would be `0` or `30`.
3486 ///
3487 /// # Errors
3488 ///
3489 /// When the smallest unit is `Unit::Day`, then the rounding increment must
3490 /// be `1` or else [`DateTime::round`] will return an error.
3491 ///
3492 /// For other units, the rounding increment must divide evenly into the
3493 /// next highest unit above the smallest unit set. The rounding increment
3494 /// must also not be equal to the next highest unit. For example, if the
3495 /// smallest unit is [`Unit::Nanosecond`], then *some* of the valid values
3496 /// for the rounding increment are `1`, `2`, `4`, `5`, `100` and `500`.
3497 /// Namely, any integer that divides evenly into `1,000` nanoseconds since
3498 /// there are `1,000` nanoseconds in the next highest unit (microseconds).
3499 ///
3500 /// # Example
3501 ///
3502 /// This example shows how to round a datetime to the nearest 10 minute
3503 /// increment.
3504 ///
3505 /// ```
3506 /// use jiff::{civil::{DateTime, DateTimeRound, date}, RoundMode, Unit};
3507 ///
3508 /// let dt: DateTime = "2024-06-20 03:24:59".parse()?;
3509 /// assert_eq!(
3510 /// dt.round((Unit::Minute, 10))?,
3511 /// date(2024, 6, 20).at(3, 20, 0, 0),
3512 /// );
3513 ///
3514 /// # Ok::<(), Box<dyn std::error::Error>>(())
3515 /// ```
3516 #[inline]
3517 pub fn increment(self, increment: i64) -> DateTimeRound {
3518 DateTimeRound { increment, ..self }
3519 }
3520
3521 /// Does the actual rounding.
3522 ///
3523 /// A non-public configuration here is the length of a day. For civil
3524 /// datetimes, this should always be `NANOS_PER_CIVIL_DAY`. But this
3525 /// rounding routine is also used for `Zoned` rounding, and in that
3526 /// context, the length of a day can vary based on the time zone.
3527 pub(crate) fn round(&self, dt: DateTime) -> Result<DateTime, Error> {
3528 // ref: https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.round
3529
3530 let increment =
3531 increment::for_datetime(self.smallest, self.increment)?;
3532 // We permit rounding to any time unit and days, but nothing else.
3533 // We should support this, but Temporal doesn't. So for now, we're
3534 // sticking to what Temporal does because they're probably not doing
3535 // it for good reasons.
3536 match self.smallest {
3537 Unit::Year | Unit::Month | Unit::Week => {
3538 return Err(Error::from(
3539 crate::error::util::RoundingIncrementError::Unsupported {
3540 unit: self.smallest,
3541 },
3542 ));
3543 }
3544 // We don't do any rounding in this case, so just bail now.
3545 Unit::Nanosecond if increment == C(1) => {
3546 return Ok(dt);
3547 }
3548 _ => {}
3549 }
3550
3551 let time_nanos = dt.time().to_nanosecond();
3552 let sign = t::NoUnits128::rfrom(dt.date().year_ranged().signum());
3553 let time_rounded = self.mode.round_by_unit_in_nanoseconds(
3554 time_nanos,
3555 self.smallest,
3556 increment,
3557 );
3558 let days = sign * time_rounded.div_ceil(t::NANOS_PER_CIVIL_DAY);
3559 let time_nanos = time_rounded.rem_ceil(t::NANOS_PER_CIVIL_DAY);
3560 let time = Time::from_nanosecond(time_nanos.rinto());
3561
3562 let date_days = t::SpanDays::rfrom(dt.date().day_ranged());
3563 // OK because days is limited by the fact that the length of a day
3564 // can't be any smaller than 1 second, and the number of nanoseconds in
3565 // a civil day is capped.
3566 let days_len = (date_days - C(1)) + days;
3567 // OK because the first day of any month is always valid.
3568 let start = dt.date().first_of_month();
3569 // `days` should basically always be <= 1, and so `days_len` should
3570 // always be at most 1 greater (or less) than where we started. But
3571 // what if there is a time zone transition that makes 9999-12-31
3572 // shorter than 24 hours? And we are rounding 9999-12-31? Well, then
3573 // I guess this could overflow and fail. I suppose it could also fail
3574 // for really weird time zone data that made the length of a day really
3575 // short. But even then, you'd need to be close to the boundary of
3576 // supported datetimes.
3577 let end = start
3578 .checked_add(Span::new().days_ranged(days_len))
3579 .context(E::FailedAddDays)?;
3580 Ok(DateTime::from_parts(end, time))
3581 }
3582
3583 pub(crate) fn get_smallest(&self) -> Unit {
3584 self.smallest
3585 }
3586
3587 pub(crate) fn get_mode(&self) -> RoundMode {
3588 self.mode
3589 }
3590
3591 pub(crate) fn get_increment(&self) -> i64 {
3592 self.increment
3593 }
3594}
3595
3596impl Default for DateTimeRound {
3597 #[inline]
3598 fn default() -> DateTimeRound {
3599 DateTimeRound::new()
3600 }
3601}
3602
3603impl From<Unit> for DateTimeRound {
3604 #[inline]
3605 fn from(unit: Unit) -> DateTimeRound {
3606 DateTimeRound::default().smallest(unit)
3607 }
3608}
3609
3610impl From<(Unit, i64)> for DateTimeRound {
3611 #[inline]
3612 fn from((unit, increment): (Unit, i64)) -> DateTimeRound {
3613 DateTimeRound::from(unit).increment(increment)
3614 }
3615}
3616
3617/// A builder for setting the fields on a [`DateTime`].
3618///
3619/// This builder is constructed via [`DateTime::with`].
3620///
3621/// # Example
3622///
3623/// The builder ensures one can chain together the individual components of a
3624/// datetime without it failing at an intermediate step. For example, if you
3625/// had a date of `2024-10-31T00:00:00` and wanted to change both the day and
3626/// the month, and each setting was validated independent of the other, you
3627/// would need to be careful to set the day first and then the month. In some
3628/// cases, you would need to set the month first and then the day!
3629///
3630/// But with the builder, you can set values in any order:
3631///
3632/// ```
3633/// use jiff::civil::date;
3634///
3635/// let dt1 = date(2024, 10, 31).at(0, 0, 0, 0);
3636/// let dt2 = dt1.with().month(11).day(30).build()?;
3637/// assert_eq!(dt2, date(2024, 11, 30).at(0, 0, 0, 0));
3638///
3639/// let dt1 = date(2024, 4, 30).at(0, 0, 0, 0);
3640/// let dt2 = dt1.with().day(31).month(7).build()?;
3641/// assert_eq!(dt2, date(2024, 7, 31).at(0, 0, 0, 0));
3642///
3643/// # Ok::<(), Box<dyn std::error::Error>>(())
3644/// ```
3645#[derive(Clone, Copy, Debug)]
3646pub struct DateTimeWith {
3647 date_with: DateWith,
3648 time_with: TimeWith,
3649}
3650
3651impl DateTimeWith {
3652 #[inline]
3653 fn new(original: DateTime) -> DateTimeWith {
3654 DateTimeWith {
3655 date_with: original.date().with(),
3656 time_with: original.time().with(),
3657 }
3658 }
3659
3660 /// Create a new `DateTime` from the fields set on this configuration.
3661 ///
3662 /// An error occurs when the fields combine to an invalid datetime.
3663 ///
3664 /// For any fields not set on this configuration, the values are taken from
3665 /// the [`DateTime`] that originally created this configuration. When no
3666 /// values are set, this routine is guaranteed to succeed and will always
3667 /// return the original datetime without modification.
3668 ///
3669 /// # Example
3670 ///
3671 /// This creates a datetime corresponding to the last day in the year at
3672 /// noon:
3673 ///
3674 /// ```
3675 /// use jiff::civil::date;
3676 ///
3677 /// let dt = date(2023, 1, 1).at(12, 0, 0, 0);
3678 /// assert_eq!(
3679 /// dt.with().day_of_year_no_leap(365).build()?,
3680 /// date(2023, 12, 31).at(12, 0, 0, 0),
3681 /// );
3682 ///
3683 /// // It also works with leap years for the same input:
3684 /// let dt = date(2024, 1, 1).at(12, 0, 0, 0);
3685 /// assert_eq!(
3686 /// dt.with().day_of_year_no_leap(365).build()?,
3687 /// date(2024, 12, 31).at(12, 0, 0, 0),
3688 /// );
3689 ///
3690 /// # Ok::<(), Box<dyn std::error::Error>>(())
3691 /// ```
3692 ///
3693 /// # Example: error for invalid datetime
3694 ///
3695 /// If the fields combine to form an invalid date, then an error is
3696 /// returned:
3697 ///
3698 /// ```
3699 /// use jiff::civil::date;
3700 ///
3701 /// let dt = date(2024, 11, 30).at(15, 30, 0, 0);
3702 /// assert!(dt.with().day(31).build().is_err());
3703 ///
3704 /// let dt = date(2024, 2, 29).at(15, 30, 0, 0);
3705 /// assert!(dt.with().year(2023).build().is_err());
3706 /// ```
3707 #[inline]
3708 pub fn build(self) -> Result<DateTime, Error> {
3709 let date = self.date_with.build()?;
3710 let time = self.time_with.build()?;
3711 Ok(DateTime::from_parts(date, time))
3712 }
3713
3714 /// Set the year, month and day fields via the `Date` given.
3715 ///
3716 /// This overrides any previous year, month or day settings.
3717 ///
3718 /// # Example
3719 ///
3720 /// This shows how to create a new datetime with a different date:
3721 ///
3722 /// ```
3723 /// use jiff::civil::date;
3724 ///
3725 /// let dt1 = date(2005, 11, 5).at(15, 30, 0, 0);
3726 /// let dt2 = dt1.with().date(date(2017, 10, 31)).build()?;
3727 /// // The date changes but the time remains the same.
3728 /// assert_eq!(dt2, date(2017, 10, 31).at(15, 30, 0, 0));
3729 ///
3730 /// # Ok::<(), Box<dyn std::error::Error>>(())
3731 /// ```
3732 #[inline]
3733 pub fn date(self, date: Date) -> DateTimeWith {
3734 DateTimeWith { date_with: date.with(), ..self }
3735 }
3736
3737 /// Set the hour, minute, second, millisecond, microsecond and nanosecond
3738 /// fields via the `Time` given.
3739 ///
3740 /// This overrides any previous hour, minute, second, millisecond,
3741 /// microsecond, nanosecond or subsecond nanosecond settings.
3742 ///
3743 /// # Example
3744 ///
3745 /// This shows how to create a new datetime with a different time:
3746 ///
3747 /// ```
3748 /// use jiff::civil::{date, time};
3749 ///
3750 /// let dt1 = date(2005, 11, 5).at(15, 30, 0, 0);
3751 /// let dt2 = dt1.with().time(time(23, 59, 59, 123_456_789)).build()?;
3752 /// // The time changes but the date remains the same.
3753 /// assert_eq!(dt2, date(2005, 11, 5).at(23, 59, 59, 123_456_789));
3754 ///
3755 /// # Ok::<(), Box<dyn std::error::Error>>(())
3756 /// ```
3757 #[inline]
3758 pub fn time(self, time: Time) -> DateTimeWith {
3759 DateTimeWith { time_with: time.with(), ..self }
3760 }
3761
3762 /// Set the year field on a [`DateTime`].
3763 ///
3764 /// One can access this value via [`DateTime::year`].
3765 ///
3766 /// This overrides any previous year settings.
3767 ///
3768 /// # Errors
3769 ///
3770 /// This returns an error when [`DateTimeWith::build`] is called if the
3771 /// given year is outside the range `-9999..=9999`. This can also return an
3772 /// error if the resulting date is otherwise invalid.
3773 ///
3774 /// # Example
3775 ///
3776 /// This shows how to create a new datetime with a different year:
3777 ///
3778 /// ```
3779 /// use jiff::civil::date;
3780 ///
3781 /// let dt1 = date(2005, 11, 5).at(15, 30, 0, 0);
3782 /// assert_eq!(dt1.year(), 2005);
3783 /// let dt2 = dt1.with().year(2007).build()?;
3784 /// assert_eq!(dt2.year(), 2007);
3785 ///
3786 /// # Ok::<(), Box<dyn std::error::Error>>(())
3787 /// ```
3788 ///
3789 /// # Example: only changing the year can fail
3790 ///
3791 /// For example, while `2024-02-29T01:30:00` is valid,
3792 /// `2023-02-29T01:30:00` is not:
3793 ///
3794 /// ```
3795 /// use jiff::civil::date;
3796 ///
3797 /// let dt = date(2024, 2, 29).at(1, 30, 0, 0);
3798 /// assert!(dt.with().year(2023).build().is_err());
3799 /// ```
3800 #[inline]
3801 pub fn year(self, year: i16) -> DateTimeWith {
3802 DateTimeWith { date_with: self.date_with.year(year), ..self }
3803 }
3804
3805 /// Set year of a datetime via its era and its non-negative numeric
3806 /// component.
3807 ///
3808 /// One can access this value via [`DateTime::era_year`].
3809 ///
3810 /// # Errors
3811 ///
3812 /// This returns an error when [`DateTimeWith::build`] is called if the
3813 /// year is outside the range for the era specified. For [`Era::BCE`], the
3814 /// range is `1..=10000`. For [`Era::CE`], the range is `1..=9999`.
3815 ///
3816 /// # Example
3817 ///
3818 /// This shows that `CE` years are equivalent to the years used by this
3819 /// crate:
3820 ///
3821 /// ```
3822 /// use jiff::civil::{Era, date};
3823 ///
3824 /// let dt1 = date(2005, 11, 5).at(8, 0, 0, 0);
3825 /// assert_eq!(dt1.year(), 2005);
3826 /// let dt2 = dt1.with().era_year(2007, Era::CE).build()?;
3827 /// assert_eq!(dt2.year(), 2007);
3828 ///
3829 /// // CE years are always positive and can be at most 9999:
3830 /// assert!(dt1.with().era_year(-5, Era::CE).build().is_err());
3831 /// assert!(dt1.with().era_year(10_000, Era::CE).build().is_err());
3832 ///
3833 /// # Ok::<(), Box<dyn std::error::Error>>(())
3834 /// ```
3835 ///
3836 /// But `BCE` years always correspond to years less than or equal to `0`
3837 /// in this crate:
3838 ///
3839 /// ```
3840 /// use jiff::civil::{Era, date};
3841 ///
3842 /// let dt1 = date(-27, 7, 1).at(8, 22, 30, 0);
3843 /// assert_eq!(dt1.year(), -27);
3844 /// assert_eq!(dt1.era_year(), (28, Era::BCE));
3845 ///
3846 /// let dt2 = dt1.with().era_year(509, Era::BCE).build()?;
3847 /// assert_eq!(dt2.year(), -508);
3848 /// assert_eq!(dt2.era_year(), (509, Era::BCE));
3849 ///
3850 /// let dt2 = dt1.with().era_year(10_000, Era::BCE).build()?;
3851 /// assert_eq!(dt2.year(), -9_999);
3852 /// assert_eq!(dt2.era_year(), (10_000, Era::BCE));
3853 ///
3854 /// // BCE years are always positive and can be at most 10000:
3855 /// assert!(dt1.with().era_year(-5, Era::BCE).build().is_err());
3856 /// assert!(dt1.with().era_year(10_001, Era::BCE).build().is_err());
3857 ///
3858 /// # Ok::<(), Box<dyn std::error::Error>>(())
3859 /// ```
3860 ///
3861 /// # Example: overrides `DateTimeWith::year`
3862 ///
3863 /// Setting this option will override any previous `DateTimeWith::year`
3864 /// option:
3865 ///
3866 /// ```
3867 /// use jiff::civil::{Era, date};
3868 ///
3869 /// let dt1 = date(2024, 7, 2).at(10, 27, 10, 123);
3870 /// let dt2 = dt1.with().year(2000).era_year(1900, Era::CE).build()?;
3871 /// assert_eq!(dt2, date(1900, 7, 2).at(10, 27, 10, 123));
3872 ///
3873 /// # Ok::<(), Box<dyn std::error::Error>>(())
3874 /// ```
3875 ///
3876 /// Similarly, `DateTimeWith::year` will override any previous call to
3877 /// `DateTimeWith::era_year`:
3878 ///
3879 /// ```
3880 /// use jiff::civil::{Era, date};
3881 ///
3882 /// let dt1 = date(2024, 7, 2).at(19, 0, 1, 1);
3883 /// let dt2 = dt1.with().era_year(1900, Era::CE).year(2000).build()?;
3884 /// assert_eq!(dt2, date(2000, 7, 2).at(19, 0, 1, 1));
3885 ///
3886 /// # Ok::<(), Box<dyn std::error::Error>>(())
3887 /// ```
3888 #[inline]
3889 pub fn era_year(self, year: i16, era: Era) -> DateTimeWith {
3890 DateTimeWith { date_with: self.date_with.era_year(year, era), ..self }
3891 }
3892
3893 /// Set the month field on a [`DateTime`].
3894 ///
3895 /// One can access this value via [`DateTime::month`].
3896 ///
3897 /// This overrides any previous month settings.
3898 ///
3899 /// # Errors
3900 ///
3901 /// This returns an error when [`DateTimeWith::build`] is called if the
3902 /// given month is outside the range `1..=12`. This can also return an
3903 /// error if the resulting date is otherwise invalid.
3904 ///
3905 /// # Example
3906 ///
3907 /// This shows how to create a new datetime with a different month:
3908 ///
3909 /// ```
3910 /// use jiff::civil::date;
3911 ///
3912 /// let dt1 = date(2005, 11, 5).at(18, 3, 59, 123_456_789);
3913 /// assert_eq!(dt1.month(), 11);
3914 /// let dt2 = dt1.with().month(6).build()?;
3915 /// assert_eq!(dt2.month(), 6);
3916 ///
3917 /// # Ok::<(), Box<dyn std::error::Error>>(())
3918 /// ```
3919 ///
3920 /// # Example: only changing the month can fail
3921 ///
3922 /// For example, while `2024-10-31T00:00:00` is valid,
3923 /// `2024-11-31T00:00:00` is not:
3924 ///
3925 /// ```
3926 /// use jiff::civil::date;
3927 ///
3928 /// let dt = date(2024, 10, 31).at(0, 0, 0, 0);
3929 /// assert!(dt.with().month(11).build().is_err());
3930 /// ```
3931 #[inline]
3932 pub fn month(self, month: i8) -> DateTimeWith {
3933 DateTimeWith { date_with: self.date_with.month(month), ..self }
3934 }
3935
3936 /// Set the day field on a [`DateTime`].
3937 ///
3938 /// One can access this value via [`DateTime::day`].
3939 ///
3940 /// This overrides any previous day settings.
3941 ///
3942 /// # Errors
3943 ///
3944 /// This returns an error when [`DateTimeWith::build`] is called if the
3945 /// given given day is outside of allowable days for the corresponding year
3946 /// and month fields.
3947 ///
3948 /// # Example
3949 ///
3950 /// This shows some examples of setting the day, including a leap day:
3951 ///
3952 /// ```
3953 /// use jiff::civil::date;
3954 ///
3955 /// let dt1 = date(2024, 2, 5).at(21, 59, 1, 999);
3956 /// assert_eq!(dt1.day(), 5);
3957 /// let dt2 = dt1.with().day(10).build()?;
3958 /// assert_eq!(dt2.day(), 10);
3959 /// let dt3 = dt1.with().day(29).build()?;
3960 /// assert_eq!(dt3.day(), 29);
3961 ///
3962 /// # Ok::<(), Box<dyn std::error::Error>>(())
3963 /// ```
3964 ///
3965 /// # Example: changing only the day can fail
3966 ///
3967 /// This shows some examples that will fail:
3968 ///
3969 /// ```
3970 /// use jiff::civil::date;
3971 ///
3972 /// let dt1 = date(2023, 2, 5).at(22, 58, 58, 9_999);
3973 /// // 2023 is not a leap year
3974 /// assert!(dt1.with().day(29).build().is_err());
3975 ///
3976 /// // September has 30 days, not 31.
3977 /// let dt1 = date(2023, 9, 5).at(22, 58, 58, 9_999);
3978 /// assert!(dt1.with().day(31).build().is_err());
3979 /// ```
3980 #[inline]
3981 pub fn day(self, day: i8) -> DateTimeWith {
3982 DateTimeWith { date_with: self.date_with.day(day), ..self }
3983 }
3984
3985 /// Set the day field on a [`DateTime`] via the ordinal number of a day
3986 /// within a year.
3987 ///
3988 /// When used, any settings for month are ignored since the month is
3989 /// determined by the day of the year.
3990 ///
3991 /// The valid values for `day` are `1..=366`. Note though that `366` is
3992 /// only valid for leap years.
3993 ///
3994 /// This overrides any previous day settings.
3995 ///
3996 /// # Errors
3997 ///
3998 /// This returns an error when [`DateTimeWith::build`] is called if the
3999 /// given day is outside the allowed range of `1..=366`, or when a value of
4000 /// `366` is given for a non-leap year.
4001 ///
4002 /// # Example
4003 ///
4004 /// This demonstrates that if a year is a leap year, then `60` corresponds
4005 /// to February 29:
4006 ///
4007 /// ```
4008 /// use jiff::civil::date;
4009 ///
4010 /// let dt = date(2024, 1, 1).at(23, 59, 59, 999_999_999);
4011 /// assert_eq!(
4012 /// dt.with().day_of_year(60).build()?,
4013 /// date(2024, 2, 29).at(23, 59, 59, 999_999_999),
4014 /// );
4015 ///
4016 /// # Ok::<(), Box<dyn std::error::Error>>(())
4017 /// ```
4018 ///
4019 /// But for non-leap years, day 60 is March 1:
4020 ///
4021 /// ```
4022 /// use jiff::civil::date;
4023 ///
4024 /// let dt = date(2023, 1, 1).at(23, 59, 59, 999_999_999);
4025 /// assert_eq!(
4026 /// dt.with().day_of_year(60).build()?,
4027 /// date(2023, 3, 1).at(23, 59, 59, 999_999_999),
4028 /// );
4029 ///
4030 /// # Ok::<(), Box<dyn std::error::Error>>(())
4031 /// ```
4032 ///
4033 /// And using `366` for a non-leap year will result in an error, since
4034 /// non-leap years only have 365 days:
4035 ///
4036 /// ```
4037 /// use jiff::civil::date;
4038 ///
4039 /// let dt = date(2023, 1, 1).at(0, 0, 0, 0);
4040 /// assert!(dt.with().day_of_year(366).build().is_err());
4041 /// // The maximal year is not a leap year, so it returns an error too.
4042 /// let dt = date(9999, 1, 1).at(0, 0, 0, 0);
4043 /// assert!(dt.with().day_of_year(366).build().is_err());
4044 /// ```
4045 #[inline]
4046 pub fn day_of_year(self, day: i16) -> DateTimeWith {
4047 DateTimeWith { date_with: self.date_with.day_of_year(day), ..self }
4048 }
4049
4050 /// Set the day field on a [`DateTime`] via the ordinal number of a day
4051 /// within a year, but ignoring leap years.
4052 ///
4053 /// When used, any settings for month are ignored since the month is
4054 /// determined by the day of the year.
4055 ///
4056 /// The valid values for `day` are `1..=365`. The value `365` always
4057 /// corresponds to the last day of the year, even for leap years. It is
4058 /// impossible for this routine to return a datetime corresponding to
4059 /// February 29.
4060 ///
4061 /// This overrides any previous day settings.
4062 ///
4063 /// # Errors
4064 ///
4065 /// This returns an error when [`DateTimeWith::build`] is called if the
4066 /// given day is outside the allowed range of `1..=365`.
4067 ///
4068 /// # Example
4069 ///
4070 /// This demonstrates that `60` corresponds to March 1, regardless of
4071 /// whether the year is a leap year or not:
4072 ///
4073 /// ```
4074 /// use jiff::civil::date;
4075 ///
4076 /// let dt = date(2023, 1, 1).at(23, 59, 59, 999_999_999);
4077 /// assert_eq!(
4078 /// dt.with().day_of_year_no_leap(60).build()?,
4079 /// date(2023, 3, 1).at(23, 59, 59, 999_999_999),
4080 /// );
4081 ///
4082 /// let dt = date(2024, 1, 1).at(23, 59, 59, 999_999_999);
4083 /// assert_eq!(
4084 /// dt.with().day_of_year_no_leap(60).build()?,
4085 /// date(2024, 3, 1).at(23, 59, 59, 999_999_999),
4086 /// );
4087 ///
4088 /// # Ok::<(), Box<dyn std::error::Error>>(())
4089 /// ```
4090 ///
4091 /// And using `365` for any year will always yield the last day of the
4092 /// year:
4093 ///
4094 /// ```
4095 /// use jiff::civil::date;
4096 ///
4097 /// let dt = date(2023, 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 /// let dt = date(2024, 1, 1).at(23, 59, 59, 999_999_999);
4104 /// assert_eq!(
4105 /// dt.with().day_of_year_no_leap(365).build()?,
4106 /// dt.last_of_year(),
4107 /// );
4108 ///
4109 /// let dt = date(9999, 1, 1).at(23, 59, 59, 999_999_999);
4110 /// assert_eq!(
4111 /// dt.with().day_of_year_no_leap(365).build()?,
4112 /// dt.last_of_year(),
4113 /// );
4114 ///
4115 /// # Ok::<(), Box<dyn std::error::Error>>(())
4116 /// ```
4117 ///
4118 /// A value of `366` is out of bounds, even for leap years:
4119 ///
4120 /// ```
4121 /// use jiff::civil::date;
4122 ///
4123 /// let dt = date(2024, 1, 1).at(5, 30, 0, 0);
4124 /// assert!(dt.with().day_of_year_no_leap(366).build().is_err());
4125 /// ```
4126 #[inline]
4127 pub fn day_of_year_no_leap(self, day: i16) -> DateTimeWith {
4128 DateTimeWith {
4129 date_with: self.date_with.day_of_year_no_leap(day),
4130 ..self
4131 }
4132 }
4133
4134 /// Set the hour field on a [`DateTime`].
4135 ///
4136 /// One can access this value via [`DateTime::hour`].
4137 ///
4138 /// This overrides any previous hour settings.
4139 ///
4140 /// # Errors
4141 ///
4142 /// This returns an error when [`DateTimeWith::build`] is called if the
4143 /// given hour is outside the range `0..=23`.
4144 ///
4145 /// # Example
4146 ///
4147 /// ```
4148 /// use jiff::civil::time;
4149 ///
4150 /// let dt1 = time(15, 21, 59, 0).on(2010, 6, 1);
4151 /// assert_eq!(dt1.hour(), 15);
4152 /// let dt2 = dt1.with().hour(3).build()?;
4153 /// assert_eq!(dt2.hour(), 3);
4154 ///
4155 /// # Ok::<(), Box<dyn std::error::Error>>(())
4156 /// ```
4157 #[inline]
4158 pub fn hour(self, hour: i8) -> DateTimeWith {
4159 DateTimeWith { time_with: self.time_with.hour(hour), ..self }
4160 }
4161
4162 /// Set the minute field on a [`DateTime`].
4163 ///
4164 /// One can access this value via [`DateTime::minute`].
4165 ///
4166 /// This overrides any previous minute settings.
4167 ///
4168 /// # Errors
4169 ///
4170 /// This returns an error when [`DateTimeWith::build`] is called if the
4171 /// given minute is outside the range `0..=59`.
4172 ///
4173 /// # Example
4174 ///
4175 /// ```
4176 /// use jiff::civil::time;
4177 ///
4178 /// let dt1 = time(15, 21, 59, 0).on(2010, 6, 1);
4179 /// assert_eq!(dt1.minute(), 21);
4180 /// let dt2 = dt1.with().minute(3).build()?;
4181 /// assert_eq!(dt2.minute(), 3);
4182 ///
4183 /// # Ok::<(), Box<dyn std::error::Error>>(())
4184 /// ```
4185 #[inline]
4186 pub fn minute(self, minute: i8) -> DateTimeWith {
4187 DateTimeWith { time_with: self.time_with.minute(minute), ..self }
4188 }
4189
4190 /// Set the second field on a [`DateTime`].
4191 ///
4192 /// One can access this value via [`DateTime::second`].
4193 ///
4194 /// This overrides any previous second settings.
4195 ///
4196 /// # Errors
4197 ///
4198 /// This returns an error when [`DateTimeWith::build`] is called if the
4199 /// given second is outside the range `0..=59`.
4200 ///
4201 /// # Example
4202 ///
4203 /// ```
4204 /// use jiff::civil::time;
4205 ///
4206 /// let dt1 = time(15, 21, 59, 0).on(2010, 6, 1);
4207 /// assert_eq!(dt1.second(), 59);
4208 /// let dt2 = dt1.with().second(3).build()?;
4209 /// assert_eq!(dt2.second(), 3);
4210 ///
4211 /// # Ok::<(), Box<dyn std::error::Error>>(())
4212 /// ```
4213 #[inline]
4214 pub fn second(self, second: i8) -> DateTimeWith {
4215 DateTimeWith { time_with: self.time_with.second(second), ..self }
4216 }
4217
4218 /// Set the millisecond field on a [`DateTime`].
4219 ///
4220 /// One can access this value via [`DateTime::millisecond`].
4221 ///
4222 /// This overrides any previous millisecond settings.
4223 ///
4224 /// Note that this only sets the millisecond component. It does
4225 /// not change the microsecond or nanosecond components. To set
4226 /// the fractional second component to nanosecond precision, use
4227 /// [`DateTimeWith::subsec_nanosecond`].
4228 ///
4229 /// # Errors
4230 ///
4231 /// This returns an error when [`DateTimeWith::build`] is called if the
4232 /// given millisecond is outside the range `0..=999`, or if both this and
4233 /// [`DateTimeWith::subsec_nanosecond`] are set.
4234 ///
4235 /// # Example
4236 ///
4237 /// This shows the relationship between [`DateTime::millisecond`] and
4238 /// [`DateTime::subsec_nanosecond`]:
4239 ///
4240 /// ```
4241 /// use jiff::civil::time;
4242 ///
4243 /// let dt1 = time(15, 21, 35, 0).on(2010, 6, 1);
4244 /// let dt2 = dt1.with().millisecond(123).build()?;
4245 /// assert_eq!(dt2.subsec_nanosecond(), 123_000_000);
4246 ///
4247 /// # Ok::<(), Box<dyn std::error::Error>>(())
4248 /// ```
4249 #[inline]
4250 pub fn millisecond(self, millisecond: i16) -> DateTimeWith {
4251 DateTimeWith {
4252 time_with: self.time_with.millisecond(millisecond),
4253 ..self
4254 }
4255 }
4256
4257 /// Set the microsecond field on a [`DateTime`].
4258 ///
4259 /// One can access this value via [`DateTime::microsecond`].
4260 ///
4261 /// This overrides any previous microsecond settings.
4262 ///
4263 /// Note that this only sets the microsecond component. It does
4264 /// not change the millisecond or nanosecond components. To set
4265 /// the fractional second component to nanosecond precision, use
4266 /// [`DateTimeWith::subsec_nanosecond`].
4267 ///
4268 /// # Errors
4269 ///
4270 /// This returns an error when [`DateTimeWith::build`] is called if the
4271 /// given microsecond is outside the range `0..=999`, or if both this and
4272 /// [`DateTimeWith::subsec_nanosecond`] are set.
4273 ///
4274 /// # Example
4275 ///
4276 /// This shows the relationship between [`DateTime::microsecond`] and
4277 /// [`DateTime::subsec_nanosecond`]:
4278 ///
4279 /// ```
4280 /// use jiff::civil::time;
4281 ///
4282 /// let dt1 = time(15, 21, 35, 0).on(2010, 6, 1);
4283 /// let dt2 = dt1.with().microsecond(123).build()?;
4284 /// assert_eq!(dt2.subsec_nanosecond(), 123_000);
4285 ///
4286 /// # Ok::<(), Box<dyn std::error::Error>>(())
4287 /// ```
4288 #[inline]
4289 pub fn microsecond(self, microsecond: i16) -> DateTimeWith {
4290 DateTimeWith {
4291 time_with: self.time_with.microsecond(microsecond),
4292 ..self
4293 }
4294 }
4295
4296 /// Set the nanosecond field on a [`DateTime`].
4297 ///
4298 /// One can access this value via [`DateTime::nanosecond`].
4299 ///
4300 /// This overrides any previous nanosecond settings.
4301 ///
4302 /// Note that this only sets the nanosecond component. It does
4303 /// not change the millisecond or microsecond components. To set
4304 /// the fractional second component to nanosecond precision, use
4305 /// [`DateTimeWith::subsec_nanosecond`].
4306 ///
4307 /// # Errors
4308 ///
4309 /// This returns an error when [`DateTimeWith::build`] is called if the
4310 /// given nanosecond is outside the range `0..=999`, or if both this and
4311 /// [`DateTimeWith::subsec_nanosecond`] are set.
4312 ///
4313 /// # Example
4314 ///
4315 /// This shows the relationship between [`DateTime::nanosecond`] and
4316 /// [`DateTime::subsec_nanosecond`]:
4317 ///
4318 /// ```
4319 /// use jiff::civil::time;
4320 ///
4321 /// let dt1 = time(15, 21, 35, 0).on(2010, 6, 1);
4322 /// let dt2 = dt1.with().nanosecond(123).build()?;
4323 /// assert_eq!(dt2.subsec_nanosecond(), 123);
4324 ///
4325 /// # Ok::<(), Box<dyn std::error::Error>>(())
4326 /// ```
4327 #[inline]
4328 pub fn nanosecond(self, nanosecond: i16) -> DateTimeWith {
4329 DateTimeWith {
4330 time_with: self.time_with.nanosecond(nanosecond),
4331 ..self
4332 }
4333 }
4334
4335 /// Set the subsecond nanosecond field on a [`DateTime`].
4336 ///
4337 /// If you want to access this value on `DateTime`, then use
4338 /// [`DateTime::subsec_nanosecond`].
4339 ///
4340 /// This overrides any previous subsecond nanosecond settings.
4341 ///
4342 /// Note that this sets the entire fractional second component to
4343 /// nanosecond precision, and overrides any individual millisecond,
4344 /// microsecond or nanosecond settings. To set individual components,
4345 /// use [`DateTimeWith::millisecond`], [`DateTimeWith::microsecond`] or
4346 /// [`DateTimeWith::nanosecond`].
4347 ///
4348 /// # Errors
4349 ///
4350 /// This returns an error when [`DateTimeWith::build`] is called if the
4351 /// given subsecond nanosecond is outside the range `0..=999,999,999`,
4352 /// or if both this and one of [`DateTimeWith::millisecond`],
4353 /// [`DateTimeWith::microsecond`] or [`DateTimeWith::nanosecond`] are set.
4354 ///
4355 /// # Example
4356 ///
4357 /// This shows the relationship between constructing a `DateTime` value
4358 /// with subsecond nanoseconds and its individual subsecond fields:
4359 ///
4360 /// ```
4361 /// use jiff::civil::time;
4362 ///
4363 /// let dt1 = time(15, 21, 35, 0).on(2010, 6, 1);
4364 /// let dt2 = dt1.with().subsec_nanosecond(123_456_789).build()?;
4365 /// assert_eq!(dt2.millisecond(), 123);
4366 /// assert_eq!(dt2.microsecond(), 456);
4367 /// assert_eq!(dt2.nanosecond(), 789);
4368 ///
4369 /// # Ok::<(), Box<dyn std::error::Error>>(())
4370 /// ```
4371 #[inline]
4372 pub fn subsec_nanosecond(self, subsec_nanosecond: i32) -> DateTimeWith {
4373 DateTimeWith {
4374 time_with: self.time_with.subsec_nanosecond(subsec_nanosecond),
4375 ..self
4376 }
4377 }
4378}
4379
4380#[cfg(test)]
4381mod tests {
4382 use std::io::Cursor;
4383
4384 use crate::{
4385 civil::{date, time},
4386 span::span_eq,
4387 RoundMode, ToSpan, Unit,
4388 };
4389
4390 use super::*;
4391
4392 #[test]
4393 fn from_temporal_docs() {
4394 let dt = DateTime::from_parts(
4395 date(1995, 12, 7),
4396 time(3, 24, 30, 000_003_500),
4397 );
4398
4399 let got = dt.round(Unit::Hour).unwrap();
4400 let expected =
4401 DateTime::from_parts(date(1995, 12, 7), time(3, 0, 0, 0));
4402 assert_eq!(got, expected);
4403
4404 let got = dt.round((Unit::Minute, 30)).unwrap();
4405 let expected =
4406 DateTime::from_parts(date(1995, 12, 7), time(3, 30, 0, 0));
4407 assert_eq!(got, expected);
4408
4409 let got = dt
4410 .round(
4411 DateTimeRound::new()
4412 .smallest(Unit::Minute)
4413 .increment(30)
4414 .mode(RoundMode::Floor),
4415 )
4416 .unwrap();
4417 let expected =
4418 DateTime::from_parts(date(1995, 12, 7), time(3, 0, 0, 0));
4419 assert_eq!(got, expected);
4420 }
4421
4422 #[test]
4423 fn since() {
4424 let later = date(2024, 5, 9).at(2, 0, 0, 0);
4425 let earlier = date(2024, 5, 8).at(3, 0, 0, 0);
4426 span_eq!(later.since(earlier).unwrap(), 23.hours());
4427
4428 let later = date(2024, 5, 9).at(3, 0, 0, 0);
4429 let earlier = date(2024, 5, 8).at(2, 0, 0, 0);
4430 span_eq!(later.since(earlier).unwrap(), 1.days().hours(1));
4431
4432 let later = date(2024, 5, 9).at(2, 0, 0, 0);
4433 let earlier = date(2024, 5, 10).at(3, 0, 0, 0);
4434 span_eq!(later.since(earlier).unwrap(), -1.days().hours(1));
4435
4436 let later = date(2024, 5, 9).at(3, 0, 0, 0);
4437 let earlier = date(2024, 5, 10).at(2, 0, 0, 0);
4438 span_eq!(later.since(earlier).unwrap(), -23.hours());
4439 }
4440
4441 #[test]
4442 fn until() {
4443 let a = date(9999, 12, 30).at(3, 0, 0, 0);
4444 let b = date(9999, 12, 31).at(2, 0, 0, 0);
4445 span_eq!(a.until(b).unwrap(), 23.hours());
4446
4447 let a = date(-9999, 1, 2).at(2, 0, 0, 0);
4448 let b = date(-9999, 1, 1).at(3, 0, 0, 0);
4449 span_eq!(a.until(b).unwrap(), -23.hours());
4450
4451 let a = date(1995, 12, 7).at(3, 24, 30, 3500);
4452 let b = date(2019, 1, 31).at(15, 30, 0, 0);
4453 span_eq!(
4454 a.until(b).unwrap(),
4455 8456.days()
4456 .hours(12)
4457 .minutes(5)
4458 .seconds(29)
4459 .milliseconds(999)
4460 .microseconds(996)
4461 .nanoseconds(500)
4462 );
4463 span_eq!(
4464 a.until((Unit::Year, b)).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 b.until((Unit::Year, a)).unwrap(),
4477 -23.years()
4478 .months(1)
4479 .days(24)
4480 .hours(12)
4481 .minutes(5)
4482 .seconds(29)
4483 .milliseconds(999)
4484 .microseconds(996)
4485 .nanoseconds(500)
4486 );
4487 span_eq!(
4488 a.until((Unit::Nanosecond, b)).unwrap(),
4489 730641929999996500i64.nanoseconds(),
4490 );
4491
4492 let a = date(-9999, 1, 1).at(0, 0, 0, 0);
4493 let b = date(9999, 12, 31).at(23, 59, 59, 999_999_999);
4494 assert!(a.until((Unit::Nanosecond, b)).is_err());
4495 span_eq!(
4496 a.until((Unit::Microsecond, b)).unwrap(),
4497 Span::new()
4498 .microseconds(631_107_417_600_000_000i64 - 1)
4499 .nanoseconds(999),
4500 );
4501 }
4502
4503 #[test]
4504 fn until_month_lengths() {
4505 let jan1 = date(2020, 1, 1).at(0, 0, 0, 0);
4506 let feb1 = date(2020, 2, 1).at(0, 0, 0, 0);
4507 let mar1 = date(2020, 3, 1).at(0, 0, 0, 0);
4508
4509 span_eq!(jan1.until(feb1).unwrap(), 31.days());
4510 span_eq!(jan1.until((Unit::Month, feb1)).unwrap(), 1.month());
4511 span_eq!(feb1.until(mar1).unwrap(), 29.days());
4512 span_eq!(feb1.until((Unit::Month, mar1)).unwrap(), 1.month());
4513 span_eq!(jan1.until(mar1).unwrap(), 60.days());
4514 span_eq!(jan1.until((Unit::Month, mar1)).unwrap(), 2.months());
4515 }
4516
4517 #[test]
4518 fn datetime_size() {
4519 #[cfg(debug_assertions)]
4520 {
4521 assert_eq!(36, core::mem::size_of::<DateTime>());
4522 }
4523 #[cfg(not(debug_assertions))]
4524 {
4525 assert_eq!(12, core::mem::size_of::<DateTime>());
4526 }
4527 }
4528
4529 /// # `serde` deserializer compatibility test
4530 ///
4531 /// Serde YAML used to be unable to deserialize `jiff` types,
4532 /// as deserializing from bytes is not supported by the deserializer.
4533 ///
4534 /// - <https://github.com/BurntSushi/jiff/issues/138>
4535 /// - <https://github.com/BurntSushi/jiff/discussions/148>
4536 #[test]
4537 fn civil_datetime_deserialize_yaml() {
4538 let expected = datetime(2024, 10, 31, 16, 33, 53, 123456789);
4539
4540 let deserialized: DateTime =
4541 serde_yaml::from_str("2024-10-31 16:33:53.123456789").unwrap();
4542
4543 assert_eq!(deserialized, expected);
4544
4545 let deserialized: DateTime =
4546 serde_yaml::from_slice("2024-10-31 16:33:53.123456789".as_bytes())
4547 .unwrap();
4548
4549 assert_eq!(deserialized, expected);
4550
4551 let cursor = Cursor::new(b"2024-10-31 16:33:53.123456789");
4552 let deserialized: DateTime = serde_yaml::from_reader(cursor).unwrap();
4553
4554 assert_eq!(deserialized, expected);
4555 }
4556}