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