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/// Options currently supported:
2531///
2532/// * [`std::fmt::Formatter::precision`] can be set to control the precision
2533/// of the fractional second component.
2534///
2535/// # Example
2536///
2537/// ```
2538/// use jiff::civil::date;
2539///
2540/// let dt = date(2024, 6, 15).at(7, 0, 0, 123_000_000);
2541/// assert_eq!(format!("{dt:.6}"), "2024-06-15T07:00:00.123000");
2542/// // Precision values greater than 9 are clamped to 9.
2543/// assert_eq!(format!("{dt:.300}"), "2024-06-15T07:00:00.123000000");
2544/// // A precision of 0 implies the entire fractional
2545/// // component is always truncated.
2546/// assert_eq!(format!("{dt:.0}"), "2024-06-15T07:00:00");
2547///
2548/// # Ok::<(), Box<dyn std::error::Error>>(())
2549/// ```
2550impl core::fmt::Display for DateTime {
2551 #[inline]
2552 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
2553 use crate::fmt::StdFmtWrite;
2554
2555 let precision =
2556 f.precision().map(|p| u8::try_from(p).unwrap_or(u8::MAX));
2557 temporal::DateTimePrinter::new()
2558 .precision(precision)
2559 .print_datetime(self, StdFmtWrite(f))
2560 .map_err(|_| core::fmt::Error)
2561 }
2562}
2563
2564impl core::str::FromStr for DateTime {
2565 type Err = Error;
2566
2567 #[inline]
2568 fn from_str(string: &str) -> Result<DateTime, Error> {
2569 DEFAULT_DATETIME_PARSER.parse_datetime(string)
2570 }
2571}
2572
2573/// Converts a [`Date`] to a [`DateTime`] with the time set to midnight.
2574impl From<Date> for DateTime {
2575 #[inline]
2576 fn from(date: Date) -> DateTime {
2577 date.to_datetime(Time::midnight())
2578 }
2579}
2580
2581/// Converts a [`Zoned`] to a [`DateTime`].
2582impl From<Zoned> for DateTime {
2583 #[inline]
2584 fn from(zdt: Zoned) -> DateTime {
2585 zdt.datetime()
2586 }
2587}
2588
2589/// Converts a [`&Zoned`](Zoned) to a [`DateTime`].
2590impl<'a> From<&'a Zoned> for DateTime {
2591 #[inline]
2592 fn from(zdt: &'a Zoned) -> DateTime {
2593 zdt.datetime()
2594 }
2595}
2596
2597/// Adds a span of time to a datetime.
2598///
2599/// This uses checked arithmetic and panics on overflow. To handle overflow
2600/// without panics, use [`DateTime::checked_add`].
2601impl core::ops::Add<Span> for DateTime {
2602 type Output = DateTime;
2603
2604 #[inline]
2605 fn add(self, rhs: Span) -> DateTime {
2606 self.checked_add(rhs).expect("adding span to datetime overflowed")
2607 }
2608}
2609
2610/// Adds a span of time to a datetime in place.
2611///
2612/// This uses checked arithmetic and panics on overflow. To handle overflow
2613/// without panics, use [`DateTime::checked_add`].
2614impl core::ops::AddAssign<Span> for DateTime {
2615 #[inline]
2616 fn add_assign(&mut self, rhs: Span) {
2617 *self = *self + rhs
2618 }
2619}
2620
2621/// Subtracts a span of time from a datetime.
2622///
2623/// This uses checked arithmetic and panics on overflow. To handle overflow
2624/// without panics, use [`DateTime::checked_sub`].
2625impl core::ops::Sub<Span> for DateTime {
2626 type Output = DateTime;
2627
2628 #[inline]
2629 fn sub(self, rhs: Span) -> DateTime {
2630 self.checked_sub(rhs)
2631 .expect("subtracting span from datetime overflowed")
2632 }
2633}
2634
2635/// Subtracts a span of time from a datetime in place.
2636///
2637/// This uses checked arithmetic and panics on overflow. To handle overflow
2638/// without panics, use [`DateTime::checked_sub`].
2639impl core::ops::SubAssign<Span> for DateTime {
2640 #[inline]
2641 fn sub_assign(&mut self, rhs: Span) {
2642 *self = *self - rhs
2643 }
2644}
2645
2646/// Computes the span of time between two datetimes.
2647///
2648/// This will return a negative span when the datetime being subtracted is
2649/// greater.
2650///
2651/// Since this uses the default configuration for calculating a span between
2652/// two datetimes (no rounding and largest units is days), this will never
2653/// panic or fail in any way. It is guaranteed that the largest non-zero
2654/// unit in the `Span` returned will be days.
2655///
2656/// To configure the largest unit or enable rounding, use [`DateTime::since`].
2657///
2658/// If you need a [`SignedDuration`] representing the span between two civil
2659/// datetimes, then use [`DateTime::duration_since`].
2660impl core::ops::Sub for DateTime {
2661 type Output = Span;
2662
2663 #[inline]
2664 fn sub(self, rhs: DateTime) -> Span {
2665 self.since(rhs).expect("since never fails when given DateTime")
2666 }
2667}
2668
2669/// Adds a signed duration of time to a datetime.
2670///
2671/// This uses checked arithmetic and panics on overflow. To handle overflow
2672/// without panics, use [`DateTime::checked_add`].
2673impl core::ops::Add<SignedDuration> for DateTime {
2674 type Output = DateTime;
2675
2676 #[inline]
2677 fn add(self, rhs: SignedDuration) -> DateTime {
2678 self.checked_add(rhs)
2679 .expect("adding signed duration to datetime overflowed")
2680 }
2681}
2682
2683/// Adds a signed duration of time to a datetime in place.
2684///
2685/// This uses checked arithmetic and panics on overflow. To handle overflow
2686/// without panics, use [`DateTime::checked_add`].
2687impl core::ops::AddAssign<SignedDuration> for DateTime {
2688 #[inline]
2689 fn add_assign(&mut self, rhs: SignedDuration) {
2690 *self = *self + rhs
2691 }
2692}
2693
2694/// Subtracts a signed duration of time from a datetime.
2695///
2696/// This uses checked arithmetic and panics on overflow. To handle overflow
2697/// without panics, use [`DateTime::checked_sub`].
2698impl core::ops::Sub<SignedDuration> for DateTime {
2699 type Output = DateTime;
2700
2701 #[inline]
2702 fn sub(self, rhs: SignedDuration) -> DateTime {
2703 self.checked_sub(rhs)
2704 .expect("subtracting signed duration from datetime overflowed")
2705 }
2706}
2707
2708/// Subtracts a signed duration of time from a datetime in place.
2709///
2710/// This uses checked arithmetic and panics on overflow. To handle overflow
2711/// without panics, use [`DateTime::checked_sub`].
2712impl core::ops::SubAssign<SignedDuration> for DateTime {
2713 #[inline]
2714 fn sub_assign(&mut self, rhs: SignedDuration) {
2715 *self = *self - rhs
2716 }
2717}
2718
2719/// Adds an unsigned duration of time to a datetime.
2720///
2721/// This uses checked arithmetic and panics on overflow. To handle overflow
2722/// without panics, use [`DateTime::checked_add`].
2723impl core::ops::Add<UnsignedDuration> for DateTime {
2724 type Output = DateTime;
2725
2726 #[inline]
2727 fn add(self, rhs: UnsignedDuration) -> DateTime {
2728 self.checked_add(rhs)
2729 .expect("adding unsigned duration to datetime overflowed")
2730 }
2731}
2732
2733/// Adds an unsigned duration of time to a datetime in place.
2734///
2735/// This uses checked arithmetic and panics on overflow. To handle overflow
2736/// without panics, use [`DateTime::checked_add`].
2737impl core::ops::AddAssign<UnsignedDuration> for DateTime {
2738 #[inline]
2739 fn add_assign(&mut self, rhs: UnsignedDuration) {
2740 *self = *self + rhs
2741 }
2742}
2743
2744/// Subtracts an unsigned duration of time from a datetime.
2745///
2746/// This uses checked arithmetic and panics on overflow. To handle overflow
2747/// without panics, use [`DateTime::checked_sub`].
2748impl core::ops::Sub<UnsignedDuration> for DateTime {
2749 type Output = DateTime;
2750
2751 #[inline]
2752 fn sub(self, rhs: UnsignedDuration) -> DateTime {
2753 self.checked_sub(rhs)
2754 .expect("subtracting unsigned duration from datetime overflowed")
2755 }
2756}
2757
2758/// Subtracts an unsigned duration of time from a datetime in place.
2759///
2760/// This uses checked arithmetic and panics on overflow. To handle overflow
2761/// without panics, use [`DateTime::checked_sub`].
2762impl core::ops::SubAssign<UnsignedDuration> for DateTime {
2763 #[inline]
2764 fn sub_assign(&mut self, rhs: UnsignedDuration) {
2765 *self = *self - rhs
2766 }
2767}
2768
2769#[cfg(feature = "serde")]
2770impl serde::Serialize for DateTime {
2771 #[inline]
2772 fn serialize<S: serde::Serializer>(
2773 &self,
2774 serializer: S,
2775 ) -> Result<S::Ok, S::Error> {
2776 serializer.collect_str(self)
2777 }
2778}
2779
2780#[cfg(feature = "serde")]
2781impl<'de> serde::Deserialize<'de> for DateTime {
2782 #[inline]
2783 fn deserialize<D: serde::Deserializer<'de>>(
2784 deserializer: D,
2785 ) -> Result<DateTime, D::Error> {
2786 use serde::de;
2787
2788 struct DateTimeVisitor;
2789
2790 impl<'de> de::Visitor<'de> for DateTimeVisitor {
2791 type Value = DateTime;
2792
2793 fn expecting(
2794 &self,
2795 f: &mut core::fmt::Formatter,
2796 ) -> core::fmt::Result {
2797 f.write_str("a datetime string")
2798 }
2799
2800 #[inline]
2801 fn visit_bytes<E: de::Error>(
2802 self,
2803 value: &[u8],
2804 ) -> Result<DateTime, E> {
2805 DEFAULT_DATETIME_PARSER
2806 .parse_datetime(value)
2807 .map_err(de::Error::custom)
2808 }
2809
2810 #[inline]
2811 fn visit_str<E: de::Error>(
2812 self,
2813 value: &str,
2814 ) -> Result<DateTime, E> {
2815 self.visit_bytes(value.as_bytes())
2816 }
2817 }
2818
2819 deserializer.deserialize_str(DateTimeVisitor)
2820 }
2821}
2822
2823#[cfg(test)]
2824impl quickcheck::Arbitrary for DateTime {
2825 fn arbitrary(g: &mut quickcheck::Gen) -> DateTime {
2826 let date = Date::arbitrary(g);
2827 let time = Time::arbitrary(g);
2828 DateTime::from_parts(date, time)
2829 }
2830
2831 fn shrink(&self) -> alloc::boxed::Box<dyn Iterator<Item = DateTime>> {
2832 alloc::boxed::Box::new(
2833 (self.date(), self.time())
2834 .shrink()
2835 .map(|(date, time)| DateTime::from_parts(date, time)),
2836 )
2837 }
2838}
2839
2840/// An iterator over periodic datetimes, created by [`DateTime::series`].
2841///
2842/// It is exhausted when the next value would exceed a [`Span`] or [`DateTime`]
2843/// value.
2844#[derive(Clone, Debug)]
2845pub struct DateTimeSeries {
2846 start: DateTime,
2847 period: Span,
2848 step: i64,
2849}
2850
2851impl Iterator for DateTimeSeries {
2852 type Item = DateTime;
2853
2854 #[inline]
2855 fn next(&mut self) -> Option<DateTime> {
2856 let span = self.period.checked_mul(self.step).ok()?;
2857 self.step = self.step.checked_add(1)?;
2858 let date = self.start.checked_add(span).ok()?;
2859 Some(date)
2860 }
2861}
2862
2863/// Options for [`DateTime::checked_add`] and [`DateTime::checked_sub`].
2864///
2865/// This type provides a way to ergonomically add one of a few different
2866/// duration types to a [`DateTime`].
2867///
2868/// The main way to construct values of this type is with its `From` trait
2869/// implementations:
2870///
2871/// * `From<Span> for DateTimeArithmetic` adds (or subtracts) the given span to
2872/// the receiver datetime.
2873/// * `From<SignedDuration> for DateTimeArithmetic` adds (or subtracts)
2874/// the given signed duration to the receiver datetime.
2875/// * `From<std::time::Duration> for DateTimeArithmetic` adds (or subtracts)
2876/// the given unsigned duration to the receiver datetime.
2877///
2878/// # Example
2879///
2880/// ```
2881/// use std::time::Duration;
2882///
2883/// use jiff::{civil::date, SignedDuration, ToSpan};
2884///
2885/// let dt = date(2024, 2, 29).at(0, 0, 0, 0);
2886/// assert_eq!(
2887/// dt.checked_add(1.year())?,
2888/// date(2025, 2, 28).at(0, 0, 0, 0),
2889/// );
2890/// assert_eq!(
2891/// dt.checked_add(SignedDuration::from_hours(24))?,
2892/// date(2024, 3, 1).at(0, 0, 0, 0),
2893/// );
2894/// assert_eq!(
2895/// dt.checked_add(Duration::from_secs(24 * 60 * 60))?,
2896/// date(2024, 3, 1).at(0, 0, 0, 0),
2897/// );
2898///
2899/// # Ok::<(), Box<dyn std::error::Error>>(())
2900/// ```
2901#[derive(Clone, Copy, Debug)]
2902pub struct DateTimeArithmetic {
2903 duration: Duration,
2904}
2905
2906impl DateTimeArithmetic {
2907 #[inline]
2908 fn checked_add(self, dt: DateTime) -> Result<DateTime, Error> {
2909 match self.duration.to_signed()? {
2910 SDuration::Span(span) => dt.checked_add_span(span),
2911 SDuration::Absolute(sdur) => dt.checked_add_duration(sdur),
2912 }
2913 }
2914
2915 #[inline]
2916 fn checked_neg(self) -> Result<DateTimeArithmetic, Error> {
2917 let duration = self.duration.checked_neg()?;
2918 Ok(DateTimeArithmetic { duration })
2919 }
2920
2921 #[inline]
2922 fn is_negative(&self) -> bool {
2923 self.duration.is_negative()
2924 }
2925}
2926
2927impl From<Span> for DateTimeArithmetic {
2928 fn from(span: Span) -> DateTimeArithmetic {
2929 let duration = Duration::from(span);
2930 DateTimeArithmetic { duration }
2931 }
2932}
2933
2934impl From<SignedDuration> for DateTimeArithmetic {
2935 fn from(sdur: SignedDuration) -> DateTimeArithmetic {
2936 let duration = Duration::from(sdur);
2937 DateTimeArithmetic { duration }
2938 }
2939}
2940
2941impl From<UnsignedDuration> for DateTimeArithmetic {
2942 fn from(udur: UnsignedDuration) -> DateTimeArithmetic {
2943 let duration = Duration::from(udur);
2944 DateTimeArithmetic { duration }
2945 }
2946}
2947
2948impl<'a> From<&'a Span> for DateTimeArithmetic {
2949 fn from(span: &'a Span) -> DateTimeArithmetic {
2950 DateTimeArithmetic::from(*span)
2951 }
2952}
2953
2954impl<'a> From<&'a SignedDuration> for DateTimeArithmetic {
2955 fn from(sdur: &'a SignedDuration) -> DateTimeArithmetic {
2956 DateTimeArithmetic::from(*sdur)
2957 }
2958}
2959
2960impl<'a> From<&'a UnsignedDuration> for DateTimeArithmetic {
2961 fn from(udur: &'a UnsignedDuration) -> DateTimeArithmetic {
2962 DateTimeArithmetic::from(*udur)
2963 }
2964}
2965
2966/// Options for [`DateTime::since`] and [`DateTime::until`].
2967///
2968/// This type provides a way to configure the calculation of
2969/// spans between two [`DateTime`] values. In particular, both
2970/// `DateTime::since` and `DateTime::until` accept anything that implements
2971/// `Into<DateTimeDifference>`. There are a few key trait implementations that
2972/// make this convenient:
2973///
2974/// * `From<DateTime> for DateTimeDifference` will construct a configuration
2975/// consisting of just the datetime. So for example, `dt1.since(dt2)` returns
2976/// the span from `dt2` to `dt1`.
2977/// * `From<Date> for DateTimeDifference` will construct a configuration
2978/// consisting of just the datetime built from the date given at midnight on
2979/// that day.
2980/// * `From<(Unit, DateTime)>` is a convenient way to specify the largest units
2981/// that should be present on the span returned. By default, the largest units
2982/// are days. Using this trait implementation is equivalent to
2983/// `DateTimeDifference::new(datetime).largest(unit)`.
2984/// * `From<(Unit, Date)>` is like the one above, but with the time component
2985/// fixed to midnight.
2986///
2987/// One can also provide a `DateTimeDifference` value directly. Doing so
2988/// is necessary to use the rounding features of calculating a span. For
2989/// example, setting the smallest unit (defaults to [`Unit::Nanosecond`]), the
2990/// rounding mode (defaults to [`RoundMode::Trunc`]) and the rounding increment
2991/// (defaults to `1`). The defaults are selected such that no rounding occurs.
2992///
2993/// Rounding a span as part of calculating it is provided as a convenience.
2994/// Callers may choose to round the span as a distinct step via
2995/// [`Span::round`], but callers may need to provide a reference date
2996/// for rounding larger units. By coupling rounding with routines like
2997/// [`DateTime::since`], the reference date can be set automatically based on
2998/// the input to `DateTime::since`.
2999///
3000/// # Example
3001///
3002/// This example shows how to round a span between two datetimes to the nearest
3003/// half-hour, with ties breaking away from zero.
3004///
3005/// ```
3006/// use jiff::{civil::{DateTime, DateTimeDifference}, RoundMode, ToSpan, Unit};
3007///
3008/// let dt1 = "2024-03-15 08:14:00.123456789".parse::<DateTime>()?;
3009/// let dt2 = "2030-03-22 15:00".parse::<DateTime>()?;
3010/// let span = dt1.until(
3011/// DateTimeDifference::new(dt2)
3012/// .smallest(Unit::Minute)
3013/// .largest(Unit::Year)
3014/// .mode(RoundMode::HalfExpand)
3015/// .increment(30),
3016/// )?;
3017/// assert_eq!(span, 6.years().days(7).hours(7).fieldwise());
3018///
3019/// # Ok::<(), Box<dyn std::error::Error>>(())
3020/// ```
3021#[derive(Clone, Copy, Debug)]
3022pub struct DateTimeDifference {
3023 datetime: DateTime,
3024 round: SpanRound<'static>,
3025}
3026
3027impl DateTimeDifference {
3028 /// Create a new default configuration for computing the span between the
3029 /// given datetime and some other datetime (specified as the receiver in
3030 /// [`DateTime::since`] or [`DateTime::until`]).
3031 #[inline]
3032 pub fn new(datetime: DateTime) -> DateTimeDifference {
3033 // We use truncation rounding by default since it seems that's
3034 // what is generally expected when computing the difference between
3035 // datetimes.
3036 //
3037 // See: https://github.com/tc39/proposal-temporal/issues/1122
3038 let round = SpanRound::new().mode(RoundMode::Trunc);
3039 DateTimeDifference { datetime, round }
3040 }
3041
3042 /// Set the smallest units allowed in the span returned.
3043 ///
3044 /// When a largest unit is not specified and the smallest unit is days
3045 /// or greater, then the largest unit is automatically set to be equal to
3046 /// the smallest unit.
3047 ///
3048 /// # Errors
3049 ///
3050 /// The smallest units must be no greater than the largest units. If this
3051 /// is violated, then computing a span with this configuration will result
3052 /// in an error.
3053 ///
3054 /// # Example
3055 ///
3056 /// This shows how to round a span between two datetimes to the nearest
3057 /// number of weeks.
3058 ///
3059 /// ```
3060 /// use jiff::{
3061 /// civil::{DateTime, DateTimeDifference},
3062 /// RoundMode, ToSpan, Unit,
3063 /// };
3064 ///
3065 /// let dt1 = "2024-03-15 08:14".parse::<DateTime>()?;
3066 /// let dt2 = "2030-11-22 08:30".parse::<DateTime>()?;
3067 /// let span = dt1.until(
3068 /// DateTimeDifference::new(dt2)
3069 /// .smallest(Unit::Week)
3070 /// .largest(Unit::Week)
3071 /// .mode(RoundMode::HalfExpand),
3072 /// )?;
3073 /// assert_eq!(span, 349.weeks().fieldwise());
3074 ///
3075 /// # Ok::<(), Box<dyn std::error::Error>>(())
3076 /// ```
3077 #[inline]
3078 pub fn smallest(self, unit: Unit) -> DateTimeDifference {
3079 DateTimeDifference { round: self.round.smallest(unit), ..self }
3080 }
3081
3082 /// Set the largest units allowed in the span returned.
3083 ///
3084 /// When a largest unit is not specified and the smallest unit is days
3085 /// or greater, then the largest unit is automatically set to be equal to
3086 /// the smallest unit. Otherwise, when the largest unit is not specified,
3087 /// it is set to days.
3088 ///
3089 /// Once a largest unit is set, there is no way to change this rounding
3090 /// configuration back to using the "automatic" default. Instead, callers
3091 /// must create a new configuration.
3092 ///
3093 /// # Errors
3094 ///
3095 /// The largest units, when set, must be at least as big as the smallest
3096 /// units (which defaults to [`Unit::Nanosecond`]). If this is violated,
3097 /// then computing a span with this configuration will result in an error.
3098 ///
3099 /// # Example
3100 ///
3101 /// This shows how to round a span between two datetimes to units no
3102 /// bigger than seconds.
3103 ///
3104 /// ```
3105 /// use jiff::{civil::{DateTime, DateTimeDifference}, ToSpan, Unit};
3106 ///
3107 /// let dt1 = "2024-03-15 08:14".parse::<DateTime>()?;
3108 /// let dt2 = "2030-11-22 08:30".parse::<DateTime>()?;
3109 /// let span = dt1.until(
3110 /// DateTimeDifference::new(dt2).largest(Unit::Second),
3111 /// )?;
3112 /// assert_eq!(span, 211076160.seconds().fieldwise());
3113 ///
3114 /// # Ok::<(), Box<dyn std::error::Error>>(())
3115 /// ```
3116 #[inline]
3117 pub fn largest(self, unit: Unit) -> DateTimeDifference {
3118 DateTimeDifference { round: self.round.largest(unit), ..self }
3119 }
3120
3121 /// Set the rounding mode.
3122 ///
3123 /// This defaults to [`RoundMode::Trunc`] since it's plausible that
3124 /// rounding "up" in the context of computing the span between
3125 /// two datetimes could be surprising in a number of cases. The
3126 /// [`RoundMode::HalfExpand`] mode corresponds to typical rounding you
3127 /// might have learned about in school. But a variety of other rounding
3128 /// modes exist.
3129 ///
3130 /// # Example
3131 ///
3132 /// This shows how to always round "up" towards positive infinity.
3133 ///
3134 /// ```
3135 /// use jiff::{
3136 /// civil::{DateTime, DateTimeDifference},
3137 /// RoundMode, ToSpan, Unit,
3138 /// };
3139 ///
3140 /// let dt1 = "2024-03-15 08:10".parse::<DateTime>()?;
3141 /// let dt2 = "2024-03-15 08:11".parse::<DateTime>()?;
3142 /// let span = dt1.until(
3143 /// DateTimeDifference::new(dt2)
3144 /// .smallest(Unit::Hour)
3145 /// .mode(RoundMode::Ceil),
3146 /// )?;
3147 /// // Only one minute elapsed, but we asked to always round up!
3148 /// assert_eq!(span, 1.hour().fieldwise());
3149 ///
3150 /// // Since `Ceil` always rounds toward positive infinity, the behavior
3151 /// // flips for a negative span.
3152 /// let span = dt1.since(
3153 /// DateTimeDifference::new(dt2)
3154 /// .smallest(Unit::Hour)
3155 /// .mode(RoundMode::Ceil),
3156 /// )?;
3157 /// assert_eq!(span, 0.hour().fieldwise());
3158 ///
3159 /// # Ok::<(), Box<dyn std::error::Error>>(())
3160 /// ```
3161 #[inline]
3162 pub fn mode(self, mode: RoundMode) -> DateTimeDifference {
3163 DateTimeDifference { round: self.round.mode(mode), ..self }
3164 }
3165
3166 /// Set the rounding increment for the smallest unit.
3167 ///
3168 /// The default value is `1`. Other values permit rounding the smallest
3169 /// unit to the nearest integer increment specified. For example, if the
3170 /// smallest unit is set to [`Unit::Minute`], then a rounding increment of
3171 /// `30` would result in rounding in increments of a half hour. That is,
3172 /// the only minute value that could result would be `0` or `30`.
3173 ///
3174 /// # Errors
3175 ///
3176 /// When the smallest unit is less than days, the rounding increment must
3177 /// divide evenly into the next highest unit after the smallest unit
3178 /// configured (and must not be equivalent to it). For example, if the
3179 /// smallest unit is [`Unit::Nanosecond`], then *some* of the valid values
3180 /// for the rounding increment are `1`, `2`, `4`, `5`, `100` and `500`.
3181 /// Namely, any integer that divides evenly into `1,000` nanoseconds since
3182 /// there are `1,000` nanoseconds in the next highest unit (microseconds).
3183 ///
3184 /// The error will occur when computing the span, and not when setting
3185 /// the increment here.
3186 ///
3187 /// # Example
3188 ///
3189 /// This shows how to round the span between two datetimes to the nearest
3190 /// 5 minute increment.
3191 ///
3192 /// ```
3193 /// use jiff::{
3194 /// civil::{DateTime, DateTimeDifference},
3195 /// RoundMode, ToSpan, Unit,
3196 /// };
3197 ///
3198 /// let dt1 = "2024-03-15 08:19".parse::<DateTime>()?;
3199 /// let dt2 = "2024-03-15 12:52".parse::<DateTime>()?;
3200 /// let span = dt1.until(
3201 /// DateTimeDifference::new(dt2)
3202 /// .smallest(Unit::Minute)
3203 /// .increment(5)
3204 /// .mode(RoundMode::HalfExpand),
3205 /// )?;
3206 /// assert_eq!(span, 4.hour().minutes(35).fieldwise());
3207 ///
3208 /// # Ok::<(), Box<dyn std::error::Error>>(())
3209 /// ```
3210 #[inline]
3211 pub fn increment(self, increment: i64) -> DateTimeDifference {
3212 DateTimeDifference { round: self.round.increment(increment), ..self }
3213 }
3214
3215 /// Returns true if and only if this configuration could change the span
3216 /// via rounding.
3217 #[inline]
3218 fn rounding_may_change_span(&self) -> bool {
3219 self.round.rounding_may_change_span_ignore_largest()
3220 }
3221
3222 /// Returns the span of time from `dt1` to the datetime in this
3223 /// configuration. The biggest units allowed are determined by the
3224 /// `smallest` and `largest` settings, but defaults to `Unit::Day`.
3225 #[inline]
3226 fn until_with_largest_unit(&self, dt1: DateTime) -> Result<Span, Error> {
3227 let dt2 = self.datetime;
3228 let largest = self
3229 .round
3230 .get_largest()
3231 .unwrap_or_else(|| self.round.get_smallest().max(Unit::Day));
3232 if largest <= Unit::Day {
3233 let diff = dt2.to_nanosecond() - dt1.to_nanosecond();
3234 // Note that this can fail! If largest unit is nanoseconds and the
3235 // datetimes are far enough apart, a single i64 won't be able to
3236 // represent the time difference.
3237 //
3238 // This is only true for nanoseconds. A single i64 in units of
3239 // microseconds can represent the interval between all valid
3240 // datetimes. (At time of writing.)
3241 return Span::from_invariant_nanoseconds(largest, diff);
3242 }
3243
3244 let (d1, mut d2) = (dt1.date(), dt2.date());
3245 let (t1, t2) = (dt1.time(), dt2.time());
3246 let sign = t::sign(d2, d1);
3247 let mut time_diff = t1.until_nanoseconds(t2);
3248 if time_diff.signum() == -sign {
3249 // These unwraps will always succeed, but the argument for why is
3250 // subtle. The key here is that the only way, e.g., d2.tomorrow()
3251 // can fail is when d2 is the max date. But, if d2 is the max date,
3252 // then it's impossible for `sign < 0` since the max date is at
3253 // least as big as every other date. And thus, d2.tomorrow() is
3254 // never reached in cases where it would fail.
3255 if sign > C(0) {
3256 d2 = d2.yesterday().unwrap();
3257 } else if sign < C(0) {
3258 d2 = d2.tomorrow().unwrap();
3259 }
3260 time_diff +=
3261 t::SpanNanoseconds::rfrom(t::NANOS_PER_CIVIL_DAY) * sign;
3262 }
3263 let date_span = d1.until((largest, d2))?;
3264 Ok(Span::from_invariant_nanoseconds(largest, time_diff.rinto())
3265 // Unlike in the <=Unit::Day case, this always succeeds because
3266 // every unit except for nanoseconds (which is not used here) can
3267 // represent all possible spans of time between any two civil
3268 // datetimes.
3269 .expect("difference between time always fits in span")
3270 .years_ranged(date_span.get_years_ranged())
3271 .months_ranged(date_span.get_months_ranged())
3272 .weeks_ranged(date_span.get_weeks_ranged())
3273 .days_ranged(date_span.get_days_ranged()))
3274 }
3275}
3276
3277impl From<DateTime> for DateTimeDifference {
3278 #[inline]
3279 fn from(dt: DateTime) -> DateTimeDifference {
3280 DateTimeDifference::new(dt)
3281 }
3282}
3283
3284impl From<Date> for DateTimeDifference {
3285 #[inline]
3286 fn from(date: Date) -> DateTimeDifference {
3287 DateTimeDifference::from(DateTime::from(date))
3288 }
3289}
3290
3291impl From<Zoned> for DateTimeDifference {
3292 #[inline]
3293 fn from(zdt: Zoned) -> DateTimeDifference {
3294 DateTimeDifference::from(DateTime::from(zdt))
3295 }
3296}
3297
3298impl<'a> From<&'a Zoned> for DateTimeDifference {
3299 #[inline]
3300 fn from(zdt: &'a Zoned) -> DateTimeDifference {
3301 DateTimeDifference::from(zdt.datetime())
3302 }
3303}
3304
3305impl From<(Unit, DateTime)> for DateTimeDifference {
3306 #[inline]
3307 fn from((largest, dt): (Unit, DateTime)) -> DateTimeDifference {
3308 DateTimeDifference::from(dt).largest(largest)
3309 }
3310}
3311
3312impl From<(Unit, Date)> for DateTimeDifference {
3313 #[inline]
3314 fn from((largest, date): (Unit, Date)) -> DateTimeDifference {
3315 DateTimeDifference::from(date).largest(largest)
3316 }
3317}
3318
3319impl From<(Unit, Zoned)> for DateTimeDifference {
3320 #[inline]
3321 fn from((largest, zdt): (Unit, Zoned)) -> DateTimeDifference {
3322 DateTimeDifference::from((largest, DateTime::from(zdt)))
3323 }
3324}
3325
3326impl<'a> From<(Unit, &'a Zoned)> for DateTimeDifference {
3327 #[inline]
3328 fn from((largest, zdt): (Unit, &'a Zoned)) -> DateTimeDifference {
3329 DateTimeDifference::from((largest, zdt.datetime()))
3330 }
3331}
3332
3333/// Options for [`DateTime::round`].
3334///
3335/// This type provides a way to configure the rounding of a civil datetime. In
3336/// particular, `DateTime::round` accepts anything that implements the
3337/// `Into<DateTimeRound>` trait. There are some trait implementations that
3338/// therefore make calling `DateTime::round` in some common cases more
3339/// ergonomic:
3340///
3341/// * `From<Unit> for DateTimeRound` will construct a rounding
3342/// configuration that rounds to the unit given. Specifically,
3343/// `DateTimeRound::new().smallest(unit)`.
3344/// * `From<(Unit, i64)> for DateTimeRound` is like the one above, but also
3345/// specifies the rounding increment for [`DateTimeRound::increment`].
3346///
3347/// Note that in the default configuration, no rounding occurs.
3348///
3349/// # Example
3350///
3351/// This example shows how to round a datetime to the nearest second:
3352///
3353/// ```
3354/// use jiff::{civil::{DateTime, date}, Unit};
3355///
3356/// let dt: DateTime = "2024-06-20 16:24:59.5".parse()?;
3357/// assert_eq!(
3358/// dt.round(Unit::Second)?,
3359/// // The second rounds up and causes minutes to increase.
3360/// date(2024, 6, 20).at(16, 25, 0, 0),
3361/// );
3362///
3363/// # Ok::<(), Box<dyn std::error::Error>>(())
3364/// ```
3365///
3366/// The above makes use of the fact that `Unit` implements
3367/// `Into<DateTimeRound>`. If you want to change the rounding mode to, say,
3368/// truncation, then you'll need to construct a `DateTimeRound` explicitly
3369/// since there are no convenience `Into` trait implementations for
3370/// [`RoundMode`].
3371///
3372/// ```
3373/// use jiff::{civil::{DateTime, DateTimeRound, date}, RoundMode, Unit};
3374///
3375/// let dt: DateTime = "2024-06-20 16:24:59.5".parse()?;
3376/// assert_eq!(
3377/// dt.round(
3378/// DateTimeRound::new().smallest(Unit::Second).mode(RoundMode::Trunc),
3379/// )?,
3380/// // The second just gets truncated as if it wasn't there.
3381/// date(2024, 6, 20).at(16, 24, 59, 0),
3382/// );
3383///
3384/// # Ok::<(), Box<dyn std::error::Error>>(())
3385/// ```
3386#[derive(Clone, Copy, Debug)]
3387pub struct DateTimeRound {
3388 smallest: Unit,
3389 mode: RoundMode,
3390 increment: i64,
3391}
3392
3393impl DateTimeRound {
3394 /// Create a new default configuration for rounding a [`DateTime`].
3395 #[inline]
3396 pub fn new() -> DateTimeRound {
3397 DateTimeRound {
3398 smallest: Unit::Nanosecond,
3399 mode: RoundMode::HalfExpand,
3400 increment: 1,
3401 }
3402 }
3403
3404 /// Set the smallest units allowed in the datetime returned after rounding.
3405 ///
3406 /// Any units below the smallest configured unit will be used, along with
3407 /// the rounding increment and rounding mode, to determine the value of the
3408 /// smallest unit. For example, when rounding `2024-06-20T03:25:30` to the
3409 /// nearest minute, the `30` second unit will result in rounding the minute
3410 /// unit of `25` up to `26` and zeroing out everything below minutes.
3411 ///
3412 /// This defaults to [`Unit::Nanosecond`].
3413 ///
3414 /// # Errors
3415 ///
3416 /// The smallest units must be no greater than [`Unit::Day`]. And when the
3417 /// smallest unit is `Unit::Day`, the rounding increment must be equal to
3418 /// `1`. Otherwise an error will be returned from [`DateTime::round`].
3419 ///
3420 /// # Example
3421 ///
3422 /// ```
3423 /// use jiff::{civil::{DateTimeRound, date}, Unit};
3424 ///
3425 /// let dt = date(2024, 6, 20).at(3, 25, 30, 0);
3426 /// assert_eq!(
3427 /// dt.round(DateTimeRound::new().smallest(Unit::Minute))?,
3428 /// date(2024, 6, 20).at(3, 26, 0, 0),
3429 /// );
3430 /// // Or, utilize the `From<Unit> for DateTimeRound` impl:
3431 /// assert_eq!(
3432 /// dt.round(Unit::Minute)?,
3433 /// date(2024, 6, 20).at(3, 26, 0, 0),
3434 /// );
3435 ///
3436 /// # Ok::<(), Box<dyn std::error::Error>>(())
3437 /// ```
3438 #[inline]
3439 pub fn smallest(self, unit: Unit) -> DateTimeRound {
3440 DateTimeRound { smallest: unit, ..self }
3441 }
3442
3443 /// Set the rounding mode.
3444 ///
3445 /// This defaults to [`RoundMode::HalfExpand`], which rounds away from
3446 /// zero. It matches the kind of rounding you might have been taught in
3447 /// school.
3448 ///
3449 /// # Example
3450 ///
3451 /// This shows how to always round datetimes up towards positive infinity.
3452 ///
3453 /// ```
3454 /// use jiff::{civil::{DateTime, DateTimeRound, date}, RoundMode, Unit};
3455 ///
3456 /// let dt: DateTime = "2024-06-20 03:25:01".parse()?;
3457 /// assert_eq!(
3458 /// dt.round(
3459 /// DateTimeRound::new()
3460 /// .smallest(Unit::Minute)
3461 /// .mode(RoundMode::Ceil),
3462 /// )?,
3463 /// date(2024, 6, 20).at(3, 26, 0, 0),
3464 /// );
3465 ///
3466 /// # Ok::<(), Box<dyn std::error::Error>>(())
3467 /// ```
3468 #[inline]
3469 pub fn mode(self, mode: RoundMode) -> DateTimeRound {
3470 DateTimeRound { mode, ..self }
3471 }
3472
3473 /// Set the rounding increment for the smallest unit.
3474 ///
3475 /// The default value is `1`. Other values permit rounding the smallest
3476 /// unit to the nearest integer increment specified. For example, if the
3477 /// smallest unit is set to [`Unit::Minute`], then a rounding increment of
3478 /// `30` would result in rounding in increments of a half hour. That is,
3479 /// the only minute value that could result would be `0` or `30`.
3480 ///
3481 /// # Errors
3482 ///
3483 /// When the smallest unit is `Unit::Day`, then the rounding increment must
3484 /// be `1` or else [`DateTime::round`] will return an error.
3485 ///
3486 /// For other units, the rounding increment must divide evenly into the
3487 /// next highest unit above the smallest unit set. The rounding increment
3488 /// must also not be equal to the next highest unit. For example, if the
3489 /// smallest unit is [`Unit::Nanosecond`], then *some* of the valid values
3490 /// for the rounding increment are `1`, `2`, `4`, `5`, `100` and `500`.
3491 /// Namely, any integer that divides evenly into `1,000` nanoseconds since
3492 /// there are `1,000` nanoseconds in the next highest unit (microseconds).
3493 ///
3494 /// # Example
3495 ///
3496 /// This example shows how to round a datetime to the nearest 10 minute
3497 /// increment.
3498 ///
3499 /// ```
3500 /// use jiff::{civil::{DateTime, DateTimeRound, date}, RoundMode, Unit};
3501 ///
3502 /// let dt: DateTime = "2024-06-20 03:24:59".parse()?;
3503 /// assert_eq!(
3504 /// dt.round((Unit::Minute, 10))?,
3505 /// date(2024, 6, 20).at(3, 20, 0, 0),
3506 /// );
3507 ///
3508 /// # Ok::<(), Box<dyn std::error::Error>>(())
3509 /// ```
3510 #[inline]
3511 pub fn increment(self, increment: i64) -> DateTimeRound {
3512 DateTimeRound { increment, ..self }
3513 }
3514
3515 /// Does the actual rounding.
3516 ///
3517 /// A non-public configuration here is the length of a day. For civil
3518 /// datetimes, this should always be `NANOS_PER_CIVIL_DAY`. But this
3519 /// rounding routine is also used for `Zoned` rounding, and in that
3520 /// context, the length of a day can vary based on the time zone.
3521 pub(crate) fn round(&self, dt: DateTime) -> Result<DateTime, Error> {
3522 // ref: https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.round
3523
3524 let increment =
3525 increment::for_datetime(self.smallest, self.increment)?;
3526 // We permit rounding to any time unit and days, but nothing else.
3527 // We should support this, but Temporal doesn't. So for now, we're
3528 // sticking to what Temporal does because they're probably not doing
3529 // it for good reasons.
3530 match self.smallest {
3531 Unit::Year | Unit::Month | Unit::Week => {
3532 return Err(err!(
3533 "rounding datetimes does not support {unit}",
3534 unit = self.smallest.plural()
3535 ));
3536 }
3537 // We don't do any rounding in this case, so just bail now.
3538 Unit::Nanosecond if increment == C(1) => {
3539 return Ok(dt);
3540 }
3541 _ => {}
3542 }
3543
3544 let time_nanos = dt.time().to_nanosecond();
3545 let sign = t::NoUnits128::rfrom(dt.date().year_ranged().signum());
3546 let time_rounded = self.mode.round_by_unit_in_nanoseconds(
3547 time_nanos,
3548 self.smallest,
3549 increment,
3550 );
3551 let days = sign * time_rounded.div_ceil(t::NANOS_PER_CIVIL_DAY);
3552 let time_nanos = time_rounded.rem_ceil(t::NANOS_PER_CIVIL_DAY);
3553 let time = Time::from_nanosecond(time_nanos.rinto());
3554
3555 let date_days = t::SpanDays::rfrom(dt.date().day_ranged());
3556 // OK because days is limited by the fact that the length of a day
3557 // can't be any smaller than 1 second, and the number of nanoseconds in
3558 // a civil day is capped.
3559 let days_len = (date_days - C(1)) + days;
3560 // OK because the first day of any month is always valid.
3561 let start = dt.date().first_of_month();
3562 // `days` should basically always be <= 1, and so `days_len` should
3563 // always be at most 1 greater (or less) than where we started. But
3564 // what if there is a time zone transition that makes 9999-12-31
3565 // shorter than 24 hours? And we are rounding 9999-12-31? Well, then
3566 // I guess this could overflow and fail. I suppose it could also fail
3567 // for really weird time zone data that made the length of a day really
3568 // short. But even then, you'd need to be close to the boundary of
3569 // supported datetimes.
3570 let end = start
3571 .checked_add(Span::new().days_ranged(days_len))
3572 .with_context(|| {
3573 err!("adding {days_len} days to {start} failed")
3574 })?;
3575 Ok(DateTime::from_parts(end, time))
3576 }
3577
3578 pub(crate) fn get_smallest(&self) -> Unit {
3579 self.smallest
3580 }
3581
3582 pub(crate) fn get_mode(&self) -> RoundMode {
3583 self.mode
3584 }
3585
3586 pub(crate) fn get_increment(&self) -> i64 {
3587 self.increment
3588 }
3589}
3590
3591impl Default for DateTimeRound {
3592 #[inline]
3593 fn default() -> DateTimeRound {
3594 DateTimeRound::new()
3595 }
3596}
3597
3598impl From<Unit> for DateTimeRound {
3599 #[inline]
3600 fn from(unit: Unit) -> DateTimeRound {
3601 DateTimeRound::default().smallest(unit)
3602 }
3603}
3604
3605impl From<(Unit, i64)> for DateTimeRound {
3606 #[inline]
3607 fn from((unit, increment): (Unit, i64)) -> DateTimeRound {
3608 DateTimeRound::from(unit).increment(increment)
3609 }
3610}
3611
3612/// A builder for setting the fields on a [`DateTime`].
3613///
3614/// This builder is constructed via [`DateTime::with`].
3615///
3616/// # Example
3617///
3618/// The builder ensures one can chain together the individual components of a
3619/// datetime without it failing at an intermediate step. For example, if you
3620/// had a date of `2024-10-31T00:00:00` and wanted to change both the day and
3621/// the month, and each setting was validated independent of the other, you
3622/// would need to be careful to set the day first and then the month. In some
3623/// cases, you would need to set the month first and then the day!
3624///
3625/// But with the builder, you can set values in any order:
3626///
3627/// ```
3628/// use jiff::civil::date;
3629///
3630/// let dt1 = date(2024, 10, 31).at(0, 0, 0, 0);
3631/// let dt2 = dt1.with().month(11).day(30).build()?;
3632/// assert_eq!(dt2, date(2024, 11, 30).at(0, 0, 0, 0));
3633///
3634/// let dt1 = date(2024, 4, 30).at(0, 0, 0, 0);
3635/// let dt2 = dt1.with().day(31).month(7).build()?;
3636/// assert_eq!(dt2, date(2024, 7, 31).at(0, 0, 0, 0));
3637///
3638/// # Ok::<(), Box<dyn std::error::Error>>(())
3639/// ```
3640#[derive(Clone, Copy, Debug)]
3641pub struct DateTimeWith {
3642 date_with: DateWith,
3643 time_with: TimeWith,
3644}
3645
3646impl DateTimeWith {
3647 #[inline]
3648 fn new(original: DateTime) -> DateTimeWith {
3649 DateTimeWith {
3650 date_with: original.date().with(),
3651 time_with: original.time().with(),
3652 }
3653 }
3654
3655 /// Create a new `DateTime` from the fields set on this configuration.
3656 ///
3657 /// An error occurs when the fields combine to an invalid datetime.
3658 ///
3659 /// For any fields not set on this configuration, the values are taken from
3660 /// the [`DateTime`] that originally created this configuration. When no
3661 /// values are set, this routine is guaranteed to succeed and will always
3662 /// return the original datetime without modification.
3663 ///
3664 /// # Example
3665 ///
3666 /// This creates a datetime corresponding to the last day in the year at
3667 /// noon:
3668 ///
3669 /// ```
3670 /// use jiff::civil::date;
3671 ///
3672 /// let dt = date(2023, 1, 1).at(12, 0, 0, 0);
3673 /// assert_eq!(
3674 /// dt.with().day_of_year_no_leap(365).build()?,
3675 /// date(2023, 12, 31).at(12, 0, 0, 0),
3676 /// );
3677 ///
3678 /// // It also works with leap years for the same input:
3679 /// let dt = date(2024, 1, 1).at(12, 0, 0, 0);
3680 /// assert_eq!(
3681 /// dt.with().day_of_year_no_leap(365).build()?,
3682 /// date(2024, 12, 31).at(12, 0, 0, 0),
3683 /// );
3684 ///
3685 /// # Ok::<(), Box<dyn std::error::Error>>(())
3686 /// ```
3687 ///
3688 /// # Example: error for invalid datetime
3689 ///
3690 /// If the fields combine to form an invalid date, then an error is
3691 /// returned:
3692 ///
3693 /// ```
3694 /// use jiff::civil::date;
3695 ///
3696 /// let dt = date(2024, 11, 30).at(15, 30, 0, 0);
3697 /// assert!(dt.with().day(31).build().is_err());
3698 ///
3699 /// let dt = date(2024, 2, 29).at(15, 30, 0, 0);
3700 /// assert!(dt.with().year(2023).build().is_err());
3701 /// ```
3702 #[inline]
3703 pub fn build(self) -> Result<DateTime, Error> {
3704 let date = self.date_with.build()?;
3705 let time = self.time_with.build()?;
3706 Ok(DateTime::from_parts(date, time))
3707 }
3708
3709 /// Set the year, month and day fields via the `Date` given.
3710 ///
3711 /// This overrides any previous year, month or day settings.
3712 ///
3713 /// # Example
3714 ///
3715 /// This shows how to create a new datetime with a different date:
3716 ///
3717 /// ```
3718 /// use jiff::civil::date;
3719 ///
3720 /// let dt1 = date(2005, 11, 5).at(15, 30, 0, 0);
3721 /// let dt2 = dt1.with().date(date(2017, 10, 31)).build()?;
3722 /// // The date changes but the time remains the same.
3723 /// assert_eq!(dt2, date(2017, 10, 31).at(15, 30, 0, 0));
3724 ///
3725 /// # Ok::<(), Box<dyn std::error::Error>>(())
3726 /// ```
3727 #[inline]
3728 pub fn date(self, date: Date) -> DateTimeWith {
3729 DateTimeWith { date_with: date.with(), ..self }
3730 }
3731
3732 /// Set the hour, minute, second, millisecond, microsecond and nanosecond
3733 /// fields via the `Time` given.
3734 ///
3735 /// This overrides any previous hour, minute, second, millisecond,
3736 /// microsecond, nanosecond or subsecond nanosecond settings.
3737 ///
3738 /// # Example
3739 ///
3740 /// This shows how to create a new datetime with a different time:
3741 ///
3742 /// ```
3743 /// use jiff::civil::{date, time};
3744 ///
3745 /// let dt1 = date(2005, 11, 5).at(15, 30, 0, 0);
3746 /// let dt2 = dt1.with().time(time(23, 59, 59, 123_456_789)).build()?;
3747 /// // The time changes but the date remains the same.
3748 /// assert_eq!(dt2, date(2005, 11, 5).at(23, 59, 59, 123_456_789));
3749 ///
3750 /// # Ok::<(), Box<dyn std::error::Error>>(())
3751 /// ```
3752 #[inline]
3753 pub fn time(self, time: Time) -> DateTimeWith {
3754 DateTimeWith { time_with: time.with(), ..self }
3755 }
3756
3757 /// Set the year field on a [`DateTime`].
3758 ///
3759 /// One can access this value via [`DateTime::year`].
3760 ///
3761 /// This overrides any previous year settings.
3762 ///
3763 /// # Errors
3764 ///
3765 /// This returns an error when [`DateTimeWith::build`] is called if the
3766 /// given year is outside the range `-9999..=9999`. This can also return an
3767 /// error if the resulting date is otherwise invalid.
3768 ///
3769 /// # Example
3770 ///
3771 /// This shows how to create a new datetime with a different year:
3772 ///
3773 /// ```
3774 /// use jiff::civil::date;
3775 ///
3776 /// let dt1 = date(2005, 11, 5).at(15, 30, 0, 0);
3777 /// assert_eq!(dt1.year(), 2005);
3778 /// let dt2 = dt1.with().year(2007).build()?;
3779 /// assert_eq!(dt2.year(), 2007);
3780 ///
3781 /// # Ok::<(), Box<dyn std::error::Error>>(())
3782 /// ```
3783 ///
3784 /// # Example: only changing the year can fail
3785 ///
3786 /// For example, while `2024-02-29T01:30:00` is valid,
3787 /// `2023-02-29T01:30:00` is not:
3788 ///
3789 /// ```
3790 /// use jiff::civil::date;
3791 ///
3792 /// let dt = date(2024, 2, 29).at(1, 30, 0, 0);
3793 /// assert!(dt.with().year(2023).build().is_err());
3794 /// ```
3795 #[inline]
3796 pub fn year(self, year: i16) -> DateTimeWith {
3797 DateTimeWith { date_with: self.date_with.year(year), ..self }
3798 }
3799
3800 /// Set year of a datetime via its era and its non-negative numeric
3801 /// component.
3802 ///
3803 /// One can access this value via [`DateTime::era_year`].
3804 ///
3805 /// # Errors
3806 ///
3807 /// This returns an error when [`DateTimeWith::build`] is called if the
3808 /// year is outside the range for the era specified. For [`Era::BCE`], the
3809 /// range is `1..=10000`. For [`Era::CE`], the range is `1..=9999`.
3810 ///
3811 /// # Example
3812 ///
3813 /// This shows that `CE` years are equivalent to the years used by this
3814 /// crate:
3815 ///
3816 /// ```
3817 /// use jiff::civil::{Era, date};
3818 ///
3819 /// let dt1 = date(2005, 11, 5).at(8, 0, 0, 0);
3820 /// assert_eq!(dt1.year(), 2005);
3821 /// let dt2 = dt1.with().era_year(2007, Era::CE).build()?;
3822 /// assert_eq!(dt2.year(), 2007);
3823 ///
3824 /// // CE years are always positive and can be at most 9999:
3825 /// assert!(dt1.with().era_year(-5, Era::CE).build().is_err());
3826 /// assert!(dt1.with().era_year(10_000, Era::CE).build().is_err());
3827 ///
3828 /// # Ok::<(), Box<dyn std::error::Error>>(())
3829 /// ```
3830 ///
3831 /// But `BCE` years always correspond to years less than or equal to `0`
3832 /// in this crate:
3833 ///
3834 /// ```
3835 /// use jiff::civil::{Era, date};
3836 ///
3837 /// let dt1 = date(-27, 7, 1).at(8, 22, 30, 0);
3838 /// assert_eq!(dt1.year(), -27);
3839 /// assert_eq!(dt1.era_year(), (28, Era::BCE));
3840 ///
3841 /// let dt2 = dt1.with().era_year(509, Era::BCE).build()?;
3842 /// assert_eq!(dt2.year(), -508);
3843 /// assert_eq!(dt2.era_year(), (509, Era::BCE));
3844 ///
3845 /// let dt2 = dt1.with().era_year(10_000, Era::BCE).build()?;
3846 /// assert_eq!(dt2.year(), -9_999);
3847 /// assert_eq!(dt2.era_year(), (10_000, Era::BCE));
3848 ///
3849 /// // BCE years are always positive and can be at most 10000:
3850 /// assert!(dt1.with().era_year(-5, Era::BCE).build().is_err());
3851 /// assert!(dt1.with().era_year(10_001, Era::BCE).build().is_err());
3852 ///
3853 /// # Ok::<(), Box<dyn std::error::Error>>(())
3854 /// ```
3855 ///
3856 /// # Example: overrides `DateTimeWith::year`
3857 ///
3858 /// Setting this option will override any previous `DateTimeWith::year`
3859 /// option:
3860 ///
3861 /// ```
3862 /// use jiff::civil::{Era, date};
3863 ///
3864 /// let dt1 = date(2024, 7, 2).at(10, 27, 10, 123);
3865 /// let dt2 = dt1.with().year(2000).era_year(1900, Era::CE).build()?;
3866 /// assert_eq!(dt2, date(1900, 7, 2).at(10, 27, 10, 123));
3867 ///
3868 /// # Ok::<(), Box<dyn std::error::Error>>(())
3869 /// ```
3870 ///
3871 /// Similarly, `DateTimeWith::year` will override any previous call to
3872 /// `DateTimeWith::era_year`:
3873 ///
3874 /// ```
3875 /// use jiff::civil::{Era, date};
3876 ///
3877 /// let dt1 = date(2024, 7, 2).at(19, 0, 1, 1);
3878 /// let dt2 = dt1.with().era_year(1900, Era::CE).year(2000).build()?;
3879 /// assert_eq!(dt2, date(2000, 7, 2).at(19, 0, 1, 1));
3880 ///
3881 /// # Ok::<(), Box<dyn std::error::Error>>(())
3882 /// ```
3883 #[inline]
3884 pub fn era_year(self, year: i16, era: Era) -> DateTimeWith {
3885 DateTimeWith { date_with: self.date_with.era_year(year, era), ..self }
3886 }
3887
3888 /// Set the month field on a [`DateTime`].
3889 ///
3890 /// One can access this value via [`DateTime::month`].
3891 ///
3892 /// This overrides any previous month settings.
3893 ///
3894 /// # Errors
3895 ///
3896 /// This returns an error when [`DateTimeWith::build`] is called if the
3897 /// given month is outside the range `1..=12`. This can also return an
3898 /// error if the resulting date is otherwise invalid.
3899 ///
3900 /// # Example
3901 ///
3902 /// This shows how to create a new datetime with a different month:
3903 ///
3904 /// ```
3905 /// use jiff::civil::date;
3906 ///
3907 /// let dt1 = date(2005, 11, 5).at(18, 3, 59, 123_456_789);
3908 /// assert_eq!(dt1.month(), 11);
3909 /// let dt2 = dt1.with().month(6).build()?;
3910 /// assert_eq!(dt2.month(), 6);
3911 ///
3912 /// # Ok::<(), Box<dyn std::error::Error>>(())
3913 /// ```
3914 ///
3915 /// # Example: only changing the month can fail
3916 ///
3917 /// For example, while `2024-10-31T00:00:00` is valid,
3918 /// `2024-11-31T00:00:00` is not:
3919 ///
3920 /// ```
3921 /// use jiff::civil::date;
3922 ///
3923 /// let dt = date(2024, 10, 31).at(0, 0, 0, 0);
3924 /// assert!(dt.with().month(11).build().is_err());
3925 /// ```
3926 #[inline]
3927 pub fn month(self, month: i8) -> DateTimeWith {
3928 DateTimeWith { date_with: self.date_with.month(month), ..self }
3929 }
3930
3931 /// Set the day field on a [`DateTime`].
3932 ///
3933 /// One can access this value via [`DateTime::day`].
3934 ///
3935 /// This overrides any previous day settings.
3936 ///
3937 /// # Errors
3938 ///
3939 /// This returns an error when [`DateTimeWith::build`] is called if the
3940 /// given given day is outside of allowable days for the corresponding year
3941 /// and month fields.
3942 ///
3943 /// # Example
3944 ///
3945 /// This shows some examples of setting the day, including a leap day:
3946 ///
3947 /// ```
3948 /// use jiff::civil::date;
3949 ///
3950 /// let dt1 = date(2024, 2, 5).at(21, 59, 1, 999);
3951 /// assert_eq!(dt1.day(), 5);
3952 /// let dt2 = dt1.with().day(10).build()?;
3953 /// assert_eq!(dt2.day(), 10);
3954 /// let dt3 = dt1.with().day(29).build()?;
3955 /// assert_eq!(dt3.day(), 29);
3956 ///
3957 /// # Ok::<(), Box<dyn std::error::Error>>(())
3958 /// ```
3959 ///
3960 /// # Example: changing only the day can fail
3961 ///
3962 /// This shows some examples that will fail:
3963 ///
3964 /// ```
3965 /// use jiff::civil::date;
3966 ///
3967 /// let dt1 = date(2023, 2, 5).at(22, 58, 58, 9_999);
3968 /// // 2023 is not a leap year
3969 /// assert!(dt1.with().day(29).build().is_err());
3970 ///
3971 /// // September has 30 days, not 31.
3972 /// let dt1 = date(2023, 9, 5).at(22, 58, 58, 9_999);
3973 /// assert!(dt1.with().day(31).build().is_err());
3974 /// ```
3975 #[inline]
3976 pub fn day(self, day: i8) -> DateTimeWith {
3977 DateTimeWith { date_with: self.date_with.day(day), ..self }
3978 }
3979
3980 /// Set the day field on a [`DateTime`] via the ordinal number of a day
3981 /// within a year.
3982 ///
3983 /// When used, any settings for month are ignored since the month is
3984 /// determined by the day of the year.
3985 ///
3986 /// The valid values for `day` are `1..=366`. Note though that `366` is
3987 /// only valid for leap years.
3988 ///
3989 /// This overrides any previous day settings.
3990 ///
3991 /// # Errors
3992 ///
3993 /// This returns an error when [`DateTimeWith::build`] is called if the
3994 /// given day is outside the allowed range of `1..=366`, or when a value of
3995 /// `366` is given for a non-leap year.
3996 ///
3997 /// # Example
3998 ///
3999 /// This demonstrates that if a year is a leap year, then `60` corresponds
4000 /// to February 29:
4001 ///
4002 /// ```
4003 /// use jiff::civil::date;
4004 ///
4005 /// let dt = date(2024, 1, 1).at(23, 59, 59, 999_999_999);
4006 /// assert_eq!(
4007 /// dt.with().day_of_year(60).build()?,
4008 /// date(2024, 2, 29).at(23, 59, 59, 999_999_999),
4009 /// );
4010 ///
4011 /// # Ok::<(), Box<dyn std::error::Error>>(())
4012 /// ```
4013 ///
4014 /// But for non-leap years, day 60 is March 1:
4015 ///
4016 /// ```
4017 /// use jiff::civil::date;
4018 ///
4019 /// let dt = date(2023, 1, 1).at(23, 59, 59, 999_999_999);
4020 /// assert_eq!(
4021 /// dt.with().day_of_year(60).build()?,
4022 /// date(2023, 3, 1).at(23, 59, 59, 999_999_999),
4023 /// );
4024 ///
4025 /// # Ok::<(), Box<dyn std::error::Error>>(())
4026 /// ```
4027 ///
4028 /// And using `366` for a non-leap year will result in an error, since
4029 /// non-leap years only have 365 days:
4030 ///
4031 /// ```
4032 /// use jiff::civil::date;
4033 ///
4034 /// let dt = date(2023, 1, 1).at(0, 0, 0, 0);
4035 /// assert!(dt.with().day_of_year(366).build().is_err());
4036 /// // The maximal year is not a leap year, so it returns an error too.
4037 /// let dt = date(9999, 1, 1).at(0, 0, 0, 0);
4038 /// assert!(dt.with().day_of_year(366).build().is_err());
4039 /// ```
4040 #[inline]
4041 pub fn day_of_year(self, day: i16) -> DateTimeWith {
4042 DateTimeWith { date_with: self.date_with.day_of_year(day), ..self }
4043 }
4044
4045 /// Set the day field on a [`DateTime`] via the ordinal number of a day
4046 /// within a year, but ignoring leap years.
4047 ///
4048 /// When used, any settings for month are ignored since the month is
4049 /// determined by the day of the year.
4050 ///
4051 /// The valid values for `day` are `1..=365`. The value `365` always
4052 /// corresponds to the last day of the year, even for leap years. It is
4053 /// impossible for this routine to return a datetime corresponding to
4054 /// February 29.
4055 ///
4056 /// This overrides any previous day settings.
4057 ///
4058 /// # Errors
4059 ///
4060 /// This returns an error when [`DateTimeWith::build`] is called if the
4061 /// given day is outside the allowed range of `1..=365`.
4062 ///
4063 /// # Example
4064 ///
4065 /// This demonstrates that `60` corresponds to March 1, regardless of
4066 /// whether the year is a leap year or not:
4067 ///
4068 /// ```
4069 /// use jiff::civil::date;
4070 ///
4071 /// let dt = date(2023, 1, 1).at(23, 59, 59, 999_999_999);
4072 /// assert_eq!(
4073 /// dt.with().day_of_year_no_leap(60).build()?,
4074 /// date(2023, 3, 1).at(23, 59, 59, 999_999_999),
4075 /// );
4076 ///
4077 /// let dt = date(2024, 1, 1).at(23, 59, 59, 999_999_999);
4078 /// assert_eq!(
4079 /// dt.with().day_of_year_no_leap(60).build()?,
4080 /// date(2024, 3, 1).at(23, 59, 59, 999_999_999),
4081 /// );
4082 ///
4083 /// # Ok::<(), Box<dyn std::error::Error>>(())
4084 /// ```
4085 ///
4086 /// And using `365` for any year will always yield the last day of the
4087 /// year:
4088 ///
4089 /// ```
4090 /// use jiff::civil::date;
4091 ///
4092 /// let dt = date(2023, 1, 1).at(23, 59, 59, 999_999_999);
4093 /// assert_eq!(
4094 /// dt.with().day_of_year_no_leap(365).build()?,
4095 /// dt.last_of_year(),
4096 /// );
4097 ///
4098 /// let dt = date(2024, 1, 1).at(23, 59, 59, 999_999_999);
4099 /// assert_eq!(
4100 /// dt.with().day_of_year_no_leap(365).build()?,
4101 /// dt.last_of_year(),
4102 /// );
4103 ///
4104 /// let dt = date(9999, 1, 1).at(23, 59, 59, 999_999_999);
4105 /// assert_eq!(
4106 /// dt.with().day_of_year_no_leap(365).build()?,
4107 /// dt.last_of_year(),
4108 /// );
4109 ///
4110 /// # Ok::<(), Box<dyn std::error::Error>>(())
4111 /// ```
4112 ///
4113 /// A value of `366` is out of bounds, even for leap years:
4114 ///
4115 /// ```
4116 /// use jiff::civil::date;
4117 ///
4118 /// let dt = date(2024, 1, 1).at(5, 30, 0, 0);
4119 /// assert!(dt.with().day_of_year_no_leap(366).build().is_err());
4120 /// ```
4121 #[inline]
4122 pub fn day_of_year_no_leap(self, day: i16) -> DateTimeWith {
4123 DateTimeWith {
4124 date_with: self.date_with.day_of_year_no_leap(day),
4125 ..self
4126 }
4127 }
4128
4129 /// Set the hour field on a [`DateTime`].
4130 ///
4131 /// One can access this value via [`DateTime::hour`].
4132 ///
4133 /// This overrides any previous hour settings.
4134 ///
4135 /// # Errors
4136 ///
4137 /// This returns an error when [`DateTimeWith::build`] is called if the
4138 /// given hour is outside the range `0..=23`.
4139 ///
4140 /// # Example
4141 ///
4142 /// ```
4143 /// use jiff::civil::time;
4144 ///
4145 /// let dt1 = time(15, 21, 59, 0).on(2010, 6, 1);
4146 /// assert_eq!(dt1.hour(), 15);
4147 /// let dt2 = dt1.with().hour(3).build()?;
4148 /// assert_eq!(dt2.hour(), 3);
4149 ///
4150 /// # Ok::<(), Box<dyn std::error::Error>>(())
4151 /// ```
4152 #[inline]
4153 pub fn hour(self, hour: i8) -> DateTimeWith {
4154 DateTimeWith { time_with: self.time_with.hour(hour), ..self }
4155 }
4156
4157 /// Set the minute field on a [`DateTime`].
4158 ///
4159 /// One can access this value via [`DateTime::minute`].
4160 ///
4161 /// This overrides any previous minute settings.
4162 ///
4163 /// # Errors
4164 ///
4165 /// This returns an error when [`DateTimeWith::build`] is called if the
4166 /// given minute is outside the range `0..=59`.
4167 ///
4168 /// # Example
4169 ///
4170 /// ```
4171 /// use jiff::civil::time;
4172 ///
4173 /// let dt1 = time(15, 21, 59, 0).on(2010, 6, 1);
4174 /// assert_eq!(dt1.minute(), 21);
4175 /// let dt2 = dt1.with().minute(3).build()?;
4176 /// assert_eq!(dt2.minute(), 3);
4177 ///
4178 /// # Ok::<(), Box<dyn std::error::Error>>(())
4179 /// ```
4180 #[inline]
4181 pub fn minute(self, minute: i8) -> DateTimeWith {
4182 DateTimeWith { time_with: self.time_with.minute(minute), ..self }
4183 }
4184
4185 /// Set the second field on a [`DateTime`].
4186 ///
4187 /// One can access this value via [`DateTime::second`].
4188 ///
4189 /// This overrides any previous second settings.
4190 ///
4191 /// # Errors
4192 ///
4193 /// This returns an error when [`DateTimeWith::build`] is called if the
4194 /// given second is outside the range `0..=59`.
4195 ///
4196 /// # Example
4197 ///
4198 /// ```
4199 /// use jiff::civil::time;
4200 ///
4201 /// let dt1 = time(15, 21, 59, 0).on(2010, 6, 1);
4202 /// assert_eq!(dt1.second(), 59);
4203 /// let dt2 = dt1.with().second(3).build()?;
4204 /// assert_eq!(dt2.second(), 3);
4205 ///
4206 /// # Ok::<(), Box<dyn std::error::Error>>(())
4207 /// ```
4208 #[inline]
4209 pub fn second(self, second: i8) -> DateTimeWith {
4210 DateTimeWith { time_with: self.time_with.second(second), ..self }
4211 }
4212
4213 /// Set the millisecond field on a [`DateTime`].
4214 ///
4215 /// One can access this value via [`DateTime::millisecond`].
4216 ///
4217 /// This overrides any previous millisecond settings.
4218 ///
4219 /// Note that this only sets the millisecond component. It does
4220 /// not change the microsecond or nanosecond components. To set
4221 /// the fractional second component to nanosecond precision, use
4222 /// [`DateTimeWith::subsec_nanosecond`].
4223 ///
4224 /// # Errors
4225 ///
4226 /// This returns an error when [`DateTimeWith::build`] is called if the
4227 /// given millisecond is outside the range `0..=999`, or if both this and
4228 /// [`DateTimeWith::subsec_nanosecond`] are set.
4229 ///
4230 /// # Example
4231 ///
4232 /// This shows the relationship between [`DateTime::millisecond`] and
4233 /// [`DateTime::subsec_nanosecond`]:
4234 ///
4235 /// ```
4236 /// use jiff::civil::time;
4237 ///
4238 /// let dt1 = time(15, 21, 35, 0).on(2010, 6, 1);
4239 /// let dt2 = dt1.with().millisecond(123).build()?;
4240 /// assert_eq!(dt2.subsec_nanosecond(), 123_000_000);
4241 ///
4242 /// # Ok::<(), Box<dyn std::error::Error>>(())
4243 /// ```
4244 #[inline]
4245 pub fn millisecond(self, millisecond: i16) -> DateTimeWith {
4246 DateTimeWith {
4247 time_with: self.time_with.millisecond(millisecond),
4248 ..self
4249 }
4250 }
4251
4252 /// Set the microsecond field on a [`DateTime`].
4253 ///
4254 /// One can access this value via [`DateTime::microsecond`].
4255 ///
4256 /// This overrides any previous microsecond settings.
4257 ///
4258 /// Note that this only sets the microsecond component. It does
4259 /// not change the millisecond or nanosecond components. To set
4260 /// the fractional second component to nanosecond precision, use
4261 /// [`DateTimeWith::subsec_nanosecond`].
4262 ///
4263 /// # Errors
4264 ///
4265 /// This returns an error when [`DateTimeWith::build`] is called if the
4266 /// given microsecond is outside the range `0..=999`, or if both this and
4267 /// [`DateTimeWith::subsec_nanosecond`] are set.
4268 ///
4269 /// # Example
4270 ///
4271 /// This shows the relationship between [`DateTime::microsecond`] and
4272 /// [`DateTime::subsec_nanosecond`]:
4273 ///
4274 /// ```
4275 /// use jiff::civil::time;
4276 ///
4277 /// let dt1 = time(15, 21, 35, 0).on(2010, 6, 1);
4278 /// let dt2 = dt1.with().microsecond(123).build()?;
4279 /// assert_eq!(dt2.subsec_nanosecond(), 123_000);
4280 ///
4281 /// # Ok::<(), Box<dyn std::error::Error>>(())
4282 /// ```
4283 #[inline]
4284 pub fn microsecond(self, microsecond: i16) -> DateTimeWith {
4285 DateTimeWith {
4286 time_with: self.time_with.microsecond(microsecond),
4287 ..self
4288 }
4289 }
4290
4291 /// Set the nanosecond field on a [`DateTime`].
4292 ///
4293 /// One can access this value via [`DateTime::nanosecond`].
4294 ///
4295 /// This overrides any previous nanosecond settings.
4296 ///
4297 /// Note that this only sets the nanosecond component. It does
4298 /// not change the millisecond or microsecond components. To set
4299 /// the fractional second component to nanosecond precision, use
4300 /// [`DateTimeWith::subsec_nanosecond`].
4301 ///
4302 /// # Errors
4303 ///
4304 /// This returns an error when [`DateTimeWith::build`] is called if the
4305 /// given nanosecond is outside the range `0..=999`, or if both this and
4306 /// [`DateTimeWith::subsec_nanosecond`] are set.
4307 ///
4308 /// # Example
4309 ///
4310 /// This shows the relationship between [`DateTime::nanosecond`] and
4311 /// [`DateTime::subsec_nanosecond`]:
4312 ///
4313 /// ```
4314 /// use jiff::civil::time;
4315 ///
4316 /// let dt1 = time(15, 21, 35, 0).on(2010, 6, 1);
4317 /// let dt2 = dt1.with().nanosecond(123).build()?;
4318 /// assert_eq!(dt2.subsec_nanosecond(), 123);
4319 ///
4320 /// # Ok::<(), Box<dyn std::error::Error>>(())
4321 /// ```
4322 #[inline]
4323 pub fn nanosecond(self, nanosecond: i16) -> DateTimeWith {
4324 DateTimeWith {
4325 time_with: self.time_with.nanosecond(nanosecond),
4326 ..self
4327 }
4328 }
4329
4330 /// Set the subsecond nanosecond field on a [`DateTime`].
4331 ///
4332 /// If you want to access this value on `DateTime`, then use
4333 /// [`DateTime::subsec_nanosecond`].
4334 ///
4335 /// This overrides any previous subsecond nanosecond settings.
4336 ///
4337 /// Note that this sets the entire fractional second component to
4338 /// nanosecond precision, and overrides any individual millisecond,
4339 /// microsecond or nanosecond settings. To set individual components,
4340 /// use [`DateTimeWith::millisecond`], [`DateTimeWith::microsecond`] or
4341 /// [`DateTimeWith::nanosecond`].
4342 ///
4343 /// # Errors
4344 ///
4345 /// This returns an error when [`DateTimeWith::build`] is called if the
4346 /// given subsecond nanosecond is outside the range `0..=999,999,999`,
4347 /// or if both this and one of [`DateTimeWith::millisecond`],
4348 /// [`DateTimeWith::microsecond`] or [`DateTimeWith::nanosecond`] are set.
4349 ///
4350 /// # Example
4351 ///
4352 /// This shows the relationship between constructing a `DateTime` value
4353 /// with subsecond nanoseconds and its individual subsecond fields:
4354 ///
4355 /// ```
4356 /// use jiff::civil::time;
4357 ///
4358 /// let dt1 = time(15, 21, 35, 0).on(2010, 6, 1);
4359 /// let dt2 = dt1.with().subsec_nanosecond(123_456_789).build()?;
4360 /// assert_eq!(dt2.millisecond(), 123);
4361 /// assert_eq!(dt2.microsecond(), 456);
4362 /// assert_eq!(dt2.nanosecond(), 789);
4363 ///
4364 /// # Ok::<(), Box<dyn std::error::Error>>(())
4365 /// ```
4366 #[inline]
4367 pub fn subsec_nanosecond(self, subsec_nanosecond: i32) -> DateTimeWith {
4368 DateTimeWith {
4369 time_with: self.time_with.subsec_nanosecond(subsec_nanosecond),
4370 ..self
4371 }
4372 }
4373}
4374
4375#[cfg(test)]
4376mod tests {
4377 use std::io::Cursor;
4378
4379 use crate::{
4380 civil::{date, time},
4381 span::span_eq,
4382 RoundMode, ToSpan, Unit,
4383 };
4384
4385 use super::*;
4386
4387 #[test]
4388 fn from_temporal_docs() {
4389 let dt = DateTime::from_parts(
4390 date(1995, 12, 7),
4391 time(3, 24, 30, 000_003_500),
4392 );
4393
4394 let got = dt.round(Unit::Hour).unwrap();
4395 let expected =
4396 DateTime::from_parts(date(1995, 12, 7), time(3, 0, 0, 0));
4397 assert_eq!(got, expected);
4398
4399 let got = dt.round((Unit::Minute, 30)).unwrap();
4400 let expected =
4401 DateTime::from_parts(date(1995, 12, 7), time(3, 30, 0, 0));
4402 assert_eq!(got, expected);
4403
4404 let got = dt
4405 .round(
4406 DateTimeRound::new()
4407 .smallest(Unit::Minute)
4408 .increment(30)
4409 .mode(RoundMode::Floor),
4410 )
4411 .unwrap();
4412 let expected =
4413 DateTime::from_parts(date(1995, 12, 7), time(3, 0, 0, 0));
4414 assert_eq!(got, expected);
4415 }
4416
4417 #[test]
4418 fn since() {
4419 let later = date(2024, 5, 9).at(2, 0, 0, 0);
4420 let earlier = date(2024, 5, 8).at(3, 0, 0, 0);
4421 span_eq!(later.since(earlier).unwrap(), 23.hours());
4422
4423 let later = date(2024, 5, 9).at(3, 0, 0, 0);
4424 let earlier = date(2024, 5, 8).at(2, 0, 0, 0);
4425 span_eq!(later.since(earlier).unwrap(), 1.days().hours(1));
4426
4427 let later = date(2024, 5, 9).at(2, 0, 0, 0);
4428 let earlier = date(2024, 5, 10).at(3, 0, 0, 0);
4429 span_eq!(later.since(earlier).unwrap(), -1.days().hours(1));
4430
4431 let later = date(2024, 5, 9).at(3, 0, 0, 0);
4432 let earlier = date(2024, 5, 10).at(2, 0, 0, 0);
4433 span_eq!(later.since(earlier).unwrap(), -23.hours());
4434 }
4435
4436 #[test]
4437 fn until() {
4438 let a = date(9999, 12, 30).at(3, 0, 0, 0);
4439 let b = date(9999, 12, 31).at(2, 0, 0, 0);
4440 span_eq!(a.until(b).unwrap(), 23.hours());
4441
4442 let a = date(-9999, 1, 2).at(2, 0, 0, 0);
4443 let b = date(-9999, 1, 1).at(3, 0, 0, 0);
4444 span_eq!(a.until(b).unwrap(), -23.hours());
4445
4446 let a = date(1995, 12, 7).at(3, 24, 30, 3500);
4447 let b = date(2019, 1, 31).at(15, 30, 0, 0);
4448 span_eq!(
4449 a.until(b).unwrap(),
4450 8456.days()
4451 .hours(12)
4452 .minutes(5)
4453 .seconds(29)
4454 .milliseconds(999)
4455 .microseconds(996)
4456 .nanoseconds(500)
4457 );
4458 span_eq!(
4459 a.until((Unit::Year, b)).unwrap(),
4460 23.years()
4461 .months(1)
4462 .days(24)
4463 .hours(12)
4464 .minutes(5)
4465 .seconds(29)
4466 .milliseconds(999)
4467 .microseconds(996)
4468 .nanoseconds(500)
4469 );
4470 span_eq!(
4471 b.until((Unit::Year, a)).unwrap(),
4472 -23.years()
4473 .months(1)
4474 .days(24)
4475 .hours(12)
4476 .minutes(5)
4477 .seconds(29)
4478 .milliseconds(999)
4479 .microseconds(996)
4480 .nanoseconds(500)
4481 );
4482 span_eq!(
4483 a.until((Unit::Nanosecond, b)).unwrap(),
4484 730641929999996500i64.nanoseconds(),
4485 );
4486
4487 let a = date(-9999, 1, 1).at(0, 0, 0, 0);
4488 let b = date(9999, 12, 31).at(23, 59, 59, 999_999_999);
4489 assert!(a.until((Unit::Nanosecond, b)).is_err());
4490 span_eq!(
4491 a.until((Unit::Microsecond, b)).unwrap(),
4492 Span::new()
4493 .microseconds(631_107_417_600_000_000i64 - 1)
4494 .nanoseconds(999),
4495 );
4496 }
4497
4498 #[test]
4499 fn until_month_lengths() {
4500 let jan1 = date(2020, 1, 1).at(0, 0, 0, 0);
4501 let feb1 = date(2020, 2, 1).at(0, 0, 0, 0);
4502 let mar1 = date(2020, 3, 1).at(0, 0, 0, 0);
4503
4504 span_eq!(jan1.until(feb1).unwrap(), 31.days());
4505 span_eq!(jan1.until((Unit::Month, feb1)).unwrap(), 1.month());
4506 span_eq!(feb1.until(mar1).unwrap(), 29.days());
4507 span_eq!(feb1.until((Unit::Month, mar1)).unwrap(), 1.month());
4508 span_eq!(jan1.until(mar1).unwrap(), 60.days());
4509 span_eq!(jan1.until((Unit::Month, mar1)).unwrap(), 2.months());
4510 }
4511
4512 #[test]
4513 fn datetime_size() {
4514 #[cfg(debug_assertions)]
4515 {
4516 assert_eq!(36, core::mem::size_of::<DateTime>());
4517 }
4518 #[cfg(not(debug_assertions))]
4519 {
4520 assert_eq!(12, core::mem::size_of::<DateTime>());
4521 }
4522 }
4523
4524 /// # `serde` deserializer compatibility test
4525 ///
4526 /// Serde YAML used to be unable to deserialize `jiff` types,
4527 /// as deserializing from bytes is not supported by the deserializer.
4528 ///
4529 /// - <https://github.com/BurntSushi/jiff/issues/138>
4530 /// - <https://github.com/BurntSushi/jiff/discussions/148>
4531 #[test]
4532 fn civil_datetime_deserialize_yaml() {
4533 let expected = datetime(2024, 10, 31, 16, 33, 53, 123456789);
4534
4535 let deserialized: DateTime =
4536 serde_yaml::from_str("2024-10-31 16:33:53.123456789").unwrap();
4537
4538 assert_eq!(deserialized, expected);
4539
4540 let deserialized: DateTime =
4541 serde_yaml::from_slice("2024-10-31 16:33:53.123456789".as_bytes())
4542 .unwrap();
4543
4544 assert_eq!(deserialized, expected);
4545
4546 let cursor = Cursor::new(b"2024-10-31 16:33:53.123456789");
4547 let deserialized: DateTime = serde_yaml::from_reader(cursor).unwrap();
4548
4549 assert_eq!(deserialized, expected);
4550 }
4551}