1//! The [`OffsetDateTime`] struct and its associated `impl`s.
2
3#[cfg(feature = "std")]
4use core::cmp::Ordering;
5#[cfg(feature = "std")]
6use core::convert::From;
7use core::fmt;
8use core::hash::Hash;
9use core::ops::{Add, AddAssign, Sub, SubAssign};
10use core::time::Duration as StdDuration;
11#[cfg(feature = "formatting")]
12use std::io;
13#[cfg(feature = "std")]
14use std::time::SystemTime;
15
16use crate::date_time::offset_kind;
17#[cfg(feature = "formatting")]
18use crate::formatting::Formattable;
19#[cfg(feature = "parsing")]
20use crate::parsing::Parsable;
21use crate::{error, Date, DateTime, Duration, Month, PrimitiveDateTime, Time, UtcOffset, Weekday};
22
23/// The actual type doing all the work.
24type Inner = DateTime<offset_kind::Fixed>;
25
26/// A [`PrimitiveDateTime`] with a [`UtcOffset`].
27///
28/// All comparisons are performed using the UTC time.
29#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
30pub struct OffsetDateTime(pub(crate) Inner);
31
32impl OffsetDateTime {
33 /// Midnight, 1 January, 1970 (UTC).
34 ///
35 /// ```rust
36 /// # use time::OffsetDateTime;
37 /// # use time_macros::datetime;
38 /// assert_eq!(OffsetDateTime::UNIX_EPOCH, datetime!(1970-01-01 0:00 UTC),);
39 /// ```
40 pub const UNIX_EPOCH: Self = Self(Inner::UNIX_EPOCH);
41
42 // region: now
43 /// Create a new `OffsetDateTime` with the current date and time in UTC.
44 ///
45 /// ```rust
46 /// # use time::OffsetDateTime;
47 /// # use time_macros::offset;
48 /// assert!(OffsetDateTime::now_utc().year() >= 2019);
49 /// assert_eq!(OffsetDateTime::now_utc().offset(), offset!(UTC));
50 /// ```
51 #[cfg(feature = "std")]
52 pub fn now_utc() -> Self {
53 Self(Inner::now_utc())
54 }
55
56 /// Attempt to create a new `OffsetDateTime` with the current date and time in the local offset.
57 /// If the offset cannot be determined, an error is returned.
58 ///
59 /// ```rust
60 /// # use time::OffsetDateTime;
61 /// # if false {
62 /// assert!(OffsetDateTime::now_local().is_ok());
63 /// # }
64 /// ```
65 #[cfg(feature = "local-offset")]
66 pub fn now_local() -> Result<Self, error::IndeterminateOffset> {
67 Inner::now_local().map(Self)
68 }
69 // endregion now
70
71 /// Convert the `OffsetDateTime` from the current [`UtcOffset`] to the provided [`UtcOffset`].
72 ///
73 /// ```rust
74 /// # use time_macros::{datetime, offset};
75 /// assert_eq!(
76 /// datetime!(2000-01-01 0:00 UTC)
77 /// .to_offset(offset!(-1))
78 /// .year(),
79 /// 1999,
80 /// );
81 ///
82 /// // Let's see what time Sydney's new year's celebration is in New York and Los Angeles.
83 ///
84 /// // Construct midnight on new year's in Sydney.
85 /// let sydney = datetime!(2000-01-01 0:00 +11);
86 /// let new_york = sydney.to_offset(offset!(-5));
87 /// let los_angeles = sydney.to_offset(offset!(-8));
88 /// assert_eq!(sydney.hour(), 0);
89 /// assert_eq!(new_york.hour(), 8);
90 /// assert_eq!(los_angeles.hour(), 5);
91 /// ```
92 ///
93 /// # Panics
94 ///
95 /// This method panics if the local date-time in the new offset is outside the supported range.
96 pub const fn to_offset(self, offset: UtcOffset) -> Self {
97 Self(self.0.to_offset(offset))
98 }
99
100 /// Convert the `OffsetDateTime` from the current [`UtcOffset`] to the provided [`UtcOffset`],
101 /// returning `None` if the date-time in the resulting offset is invalid.
102 ///
103 /// ```rust
104 /// # use time::PrimitiveDateTime;
105 /// # use time_macros::{datetime, offset};
106 /// assert_eq!(
107 /// datetime!(2000-01-01 0:00 UTC)
108 /// .checked_to_offset(offset!(-1))
109 /// .unwrap()
110 /// .year(),
111 /// 1999,
112 /// );
113 /// assert_eq!(
114 /// PrimitiveDateTime::MAX
115 /// .assume_utc()
116 /// .checked_to_offset(offset!(+1)),
117 /// None,
118 /// );
119 /// ```
120 pub const fn checked_to_offset(self, offset: UtcOffset) -> Option<Self> {
121 Some(Self(const_try_opt!(self.0.checked_to_offset(offset))))
122 }
123
124 // region: constructors
125 /// Create an `OffsetDateTime` from the provided Unix timestamp. Calling `.offset()` on the
126 /// resulting value is guaranteed to return UTC.
127 ///
128 /// ```rust
129 /// # use time::OffsetDateTime;
130 /// # use time_macros::datetime;
131 /// assert_eq!(
132 /// OffsetDateTime::from_unix_timestamp(0),
133 /// Ok(OffsetDateTime::UNIX_EPOCH),
134 /// );
135 /// assert_eq!(
136 /// OffsetDateTime::from_unix_timestamp(1_546_300_800),
137 /// Ok(datetime!(2019-01-01 0:00 UTC)),
138 /// );
139 /// ```
140 ///
141 /// If you have a timestamp-nanosecond pair, you can use something along the lines of the
142 /// following:
143 ///
144 /// ```rust
145 /// # use time::{Duration, OffsetDateTime, ext::NumericalDuration};
146 /// let (timestamp, nanos) = (1, 500_000_000);
147 /// assert_eq!(
148 /// OffsetDateTime::from_unix_timestamp(timestamp)? + Duration::nanoseconds(nanos),
149 /// OffsetDateTime::UNIX_EPOCH + 1.5.seconds()
150 /// );
151 /// # Ok::<_, time::Error>(())
152 /// ```
153 pub const fn from_unix_timestamp(timestamp: i64) -> Result<Self, error::ComponentRange> {
154 Ok(Self(const_try!(Inner::from_unix_timestamp(timestamp))))
155 }
156
157 /// Construct an `OffsetDateTime` from the provided Unix timestamp (in nanoseconds). Calling
158 /// `.offset()` on the resulting value is guaranteed to return UTC.
159 ///
160 /// ```rust
161 /// # use time::OffsetDateTime;
162 /// # use time_macros::datetime;
163 /// assert_eq!(
164 /// OffsetDateTime::from_unix_timestamp_nanos(0),
165 /// Ok(OffsetDateTime::UNIX_EPOCH),
166 /// );
167 /// assert_eq!(
168 /// OffsetDateTime::from_unix_timestamp_nanos(1_546_300_800_000_000_000),
169 /// Ok(datetime!(2019-01-01 0:00 UTC)),
170 /// );
171 /// ```
172 pub const fn from_unix_timestamp_nanos(timestamp: i128) -> Result<Self, error::ComponentRange> {
173 Ok(Self(const_try!(Inner::from_unix_timestamp_nanos(
174 timestamp
175 ))))
176 }
177 // endregion constructors
178
179 // region: getters
180 /// Get the [`UtcOffset`].
181 ///
182 /// ```rust
183 /// # use time_macros::{datetime, offset};
184 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).offset(), offset!(UTC));
185 /// assert_eq!(datetime!(2019-01-01 0:00 +1).offset(), offset!(+1));
186 /// ```
187 pub const fn offset(self) -> UtcOffset {
188 self.0.offset()
189 }
190
191 /// Get the [Unix timestamp](https://en.wikipedia.org/wiki/Unix_time).
192 ///
193 /// ```rust
194 /// # use time_macros::datetime;
195 /// assert_eq!(datetime!(1970-01-01 0:00 UTC).unix_timestamp(), 0);
196 /// assert_eq!(datetime!(1970-01-01 0:00 -1).unix_timestamp(), 3_600);
197 /// ```
198 pub const fn unix_timestamp(self) -> i64 {
199 self.0.unix_timestamp()
200 }
201
202 /// Get the Unix timestamp in nanoseconds.
203 ///
204 /// ```rust
205 /// use time_macros::datetime;
206 /// assert_eq!(datetime!(1970-01-01 0:00 UTC).unix_timestamp_nanos(), 0);
207 /// assert_eq!(
208 /// datetime!(1970-01-01 0:00 -1).unix_timestamp_nanos(),
209 /// 3_600_000_000_000,
210 /// );
211 /// ```
212 pub const fn unix_timestamp_nanos(self) -> i128 {
213 self.0.unix_timestamp_nanos()
214 }
215
216 /// Get the [`Date`] in the stored offset.
217 ///
218 /// ```rust
219 /// # use time_macros::{date, datetime, offset};
220 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).date(), date!(2019-01-01));
221 /// assert_eq!(
222 /// datetime!(2019-01-01 0:00 UTC)
223 /// .to_offset(offset!(-1))
224 /// .date(),
225 /// date!(2018-12-31),
226 /// );
227 /// ```
228 pub const fn date(self) -> Date {
229 self.0.date()
230 }
231
232 /// Get the [`Time`] in the stored offset.
233 ///
234 /// ```rust
235 /// # use time_macros::{datetime, offset, time};
236 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).time(), time!(0:00));
237 /// assert_eq!(
238 /// datetime!(2019-01-01 0:00 UTC)
239 /// .to_offset(offset!(-1))
240 /// .time(),
241 /// time!(23:00)
242 /// );
243 /// ```
244 pub const fn time(self) -> Time {
245 self.0.time()
246 }
247
248 // region: date getters
249 /// Get the year of the date in the stored offset.
250 ///
251 /// ```rust
252 /// # use time_macros::{datetime, offset};
253 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).year(), 2019);
254 /// assert_eq!(
255 /// datetime!(2019-12-31 23:00 UTC)
256 /// .to_offset(offset!(+1))
257 /// .year(),
258 /// 2020,
259 /// );
260 /// assert_eq!(datetime!(2020-01-01 0:00 UTC).year(), 2020);
261 /// ```
262 pub const fn year(self) -> i32 {
263 self.0.year()
264 }
265
266 /// Get the month of the date in the stored offset.
267 ///
268 /// ```rust
269 /// # use time::Month;
270 /// # use time_macros::{datetime, offset};
271 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).month(), Month::January);
272 /// assert_eq!(
273 /// datetime!(2019-12-31 23:00 UTC)
274 /// .to_offset(offset!(+1))
275 /// .month(),
276 /// Month::January,
277 /// );
278 /// ```
279 pub const fn month(self) -> Month {
280 self.0.month()
281 }
282
283 /// Get the day of the date in the stored offset.
284 ///
285 /// The returned value will always be in the range `1..=31`.
286 ///
287 /// ```rust
288 /// # use time_macros::{datetime, offset};
289 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).day(), 1);
290 /// assert_eq!(
291 /// datetime!(2019-12-31 23:00 UTC)
292 /// .to_offset(offset!(+1))
293 /// .day(),
294 /// 1,
295 /// );
296 /// ```
297 pub const fn day(self) -> u8 {
298 self.0.day()
299 }
300
301 /// Get the day of the year of the date in the stored offset.
302 ///
303 /// The returned value will always be in the range `1..=366`.
304 ///
305 /// ```rust
306 /// # use time_macros::{datetime, offset};
307 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).ordinal(), 1);
308 /// assert_eq!(
309 /// datetime!(2019-12-31 23:00 UTC)
310 /// .to_offset(offset!(+1))
311 /// .ordinal(),
312 /// 1,
313 /// );
314 /// ```
315 pub const fn ordinal(self) -> u16 {
316 self.0.ordinal()
317 }
318
319 /// Get the ISO week number of the date in the stored offset.
320 ///
321 /// The returned value will always be in the range `1..=53`.
322 ///
323 /// ```rust
324 /// # use time_macros::datetime;
325 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).iso_week(), 1);
326 /// assert_eq!(datetime!(2020-01-01 0:00 UTC).iso_week(), 1);
327 /// assert_eq!(datetime!(2020-12-31 0:00 UTC).iso_week(), 53);
328 /// assert_eq!(datetime!(2021-01-01 0:00 UTC).iso_week(), 53);
329 /// ```
330 pub const fn iso_week(self) -> u8 {
331 self.0.iso_week()
332 }
333
334 /// Get the week number where week 1 begins on the first Sunday.
335 ///
336 /// The returned value will always be in the range `0..=53`.
337 ///
338 /// ```rust
339 /// # use time_macros::datetime;
340 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).sunday_based_week(), 0);
341 /// assert_eq!(datetime!(2020-01-01 0:00 UTC).sunday_based_week(), 0);
342 /// assert_eq!(datetime!(2020-12-31 0:00 UTC).sunday_based_week(), 52);
343 /// assert_eq!(datetime!(2021-01-01 0:00 UTC).sunday_based_week(), 0);
344 /// ```
345 pub const fn sunday_based_week(self) -> u8 {
346 self.0.sunday_based_week()
347 }
348
349 /// Get the week number where week 1 begins on the first Monday.
350 ///
351 /// The returned value will always be in the range `0..=53`.
352 ///
353 /// ```rust
354 /// # use time_macros::datetime;
355 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).monday_based_week(), 0);
356 /// assert_eq!(datetime!(2020-01-01 0:00 UTC).monday_based_week(), 0);
357 /// assert_eq!(datetime!(2020-12-31 0:00 UTC).monday_based_week(), 52);
358 /// assert_eq!(datetime!(2021-01-01 0:00 UTC).monday_based_week(), 0);
359 /// ```
360 pub const fn monday_based_week(self) -> u8 {
361 self.0.monday_based_week()
362 }
363
364 /// Get the year, month, and day.
365 ///
366 /// ```rust
367 /// # use time::Month;
368 /// # use time_macros::datetime;
369 /// assert_eq!(
370 /// datetime!(2019-01-01 0:00 UTC).to_calendar_date(),
371 /// (2019, Month::January, 1)
372 /// );
373 /// ```
374 pub const fn to_calendar_date(self) -> (i32, Month, u8) {
375 self.0.to_calendar_date()
376 }
377
378 /// Get the year and ordinal day number.
379 ///
380 /// ```rust
381 /// # use time_macros::datetime;
382 /// assert_eq!(
383 /// datetime!(2019-01-01 0:00 UTC).to_ordinal_date(),
384 /// (2019, 1)
385 /// );
386 /// ```
387 pub const fn to_ordinal_date(self) -> (i32, u16) {
388 self.0.to_ordinal_date()
389 }
390
391 /// Get the ISO 8601 year, week number, and weekday.
392 ///
393 /// ```rust
394 /// # use time::Weekday::*;
395 /// # use time_macros::datetime;
396 /// assert_eq!(
397 /// datetime!(2019-01-01 0:00 UTC).to_iso_week_date(),
398 /// (2019, 1, Tuesday)
399 /// );
400 /// assert_eq!(
401 /// datetime!(2019-10-04 0:00 UTC).to_iso_week_date(),
402 /// (2019, 40, Friday)
403 /// );
404 /// assert_eq!(
405 /// datetime!(2020-01-01 0:00 UTC).to_iso_week_date(),
406 /// (2020, 1, Wednesday)
407 /// );
408 /// assert_eq!(
409 /// datetime!(2020-12-31 0:00 UTC).to_iso_week_date(),
410 /// (2020, 53, Thursday)
411 /// );
412 /// assert_eq!(
413 /// datetime!(2021-01-01 0:00 UTC).to_iso_week_date(),
414 /// (2020, 53, Friday)
415 /// );
416 /// ```
417 pub const fn to_iso_week_date(self) -> (i32, u8, Weekday) {
418 self.0.to_iso_week_date()
419 }
420
421 /// Get the weekday of the date in the stored offset.
422 ///
423 /// ```rust
424 /// # use time::Weekday::*;
425 /// # use time_macros::datetime;
426 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).weekday(), Tuesday);
427 /// assert_eq!(datetime!(2019-02-01 0:00 UTC).weekday(), Friday);
428 /// assert_eq!(datetime!(2019-03-01 0:00 UTC).weekday(), Friday);
429 /// ```
430 pub const fn weekday(self) -> Weekday {
431 self.0.weekday()
432 }
433
434 /// Get the Julian day for the date. The time is not taken into account for this calculation.
435 ///
436 /// The algorithm to perform this conversion is derived from one provided by Peter Baum; it is
437 /// freely available [here](https://www.researchgate.net/publication/316558298_Date_Algorithms).
438 ///
439 /// ```rust
440 /// # use time_macros::datetime;
441 /// assert_eq!(datetime!(-4713-11-24 0:00 UTC).to_julian_day(), 0);
442 /// assert_eq!(datetime!(2000-01-01 0:00 UTC).to_julian_day(), 2_451_545);
443 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).to_julian_day(), 2_458_485);
444 /// assert_eq!(datetime!(2019-12-31 0:00 UTC).to_julian_day(), 2_458_849);
445 /// ```
446 pub const fn to_julian_day(self) -> i32 {
447 self.0.to_julian_day()
448 }
449 // endregion date getters
450
451 // region: time getters
452 /// Get the clock hour, minute, and second.
453 ///
454 /// ```rust
455 /// # use time_macros::datetime;
456 /// assert_eq!(datetime!(2020-01-01 0:00:00 UTC).to_hms(), (0, 0, 0));
457 /// assert_eq!(datetime!(2020-01-01 23:59:59 UTC).to_hms(), (23, 59, 59));
458 /// ```
459 pub const fn to_hms(self) -> (u8, u8, u8) {
460 self.0.as_hms()
461 }
462
463 /// Get the clock hour, minute, second, and millisecond.
464 ///
465 /// ```rust
466 /// # use time_macros::datetime;
467 /// assert_eq!(
468 /// datetime!(2020-01-01 0:00:00 UTC).to_hms_milli(),
469 /// (0, 0, 0, 0)
470 /// );
471 /// assert_eq!(
472 /// datetime!(2020-01-01 23:59:59.999 UTC).to_hms_milli(),
473 /// (23, 59, 59, 999)
474 /// );
475 /// ```
476 pub const fn to_hms_milli(self) -> (u8, u8, u8, u16) {
477 self.0.as_hms_milli()
478 }
479
480 /// Get the clock hour, minute, second, and microsecond.
481 ///
482 /// ```rust
483 /// # use time_macros::datetime;
484 /// assert_eq!(
485 /// datetime!(2020-01-01 0:00:00 UTC).to_hms_micro(),
486 /// (0, 0, 0, 0)
487 /// );
488 /// assert_eq!(
489 /// datetime!(2020-01-01 23:59:59.999_999 UTC).to_hms_micro(),
490 /// (23, 59, 59, 999_999)
491 /// );
492 /// ```
493 pub const fn to_hms_micro(self) -> (u8, u8, u8, u32) {
494 self.0.as_hms_micro()
495 }
496
497 /// Get the clock hour, minute, second, and nanosecond.
498 ///
499 /// ```rust
500 /// # use time_macros::datetime;
501 /// assert_eq!(
502 /// datetime!(2020-01-01 0:00:00 UTC).to_hms_nano(),
503 /// (0, 0, 0, 0)
504 /// );
505 /// assert_eq!(
506 /// datetime!(2020-01-01 23:59:59.999_999_999 UTC).to_hms_nano(),
507 /// (23, 59, 59, 999_999_999)
508 /// );
509 /// ```
510 pub const fn to_hms_nano(self) -> (u8, u8, u8, u32) {
511 self.0.as_hms_nano()
512 }
513
514 /// Get the clock hour in the stored offset.
515 ///
516 /// The returned value will always be in the range `0..24`.
517 ///
518 /// ```rust
519 /// # use time_macros::{datetime, offset};
520 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).hour(), 0);
521 /// assert_eq!(
522 /// datetime!(2019-01-01 23:59:59 UTC)
523 /// .to_offset(offset!(-2))
524 /// .hour(),
525 /// 21,
526 /// );
527 /// ```
528 pub const fn hour(self) -> u8 {
529 self.0.hour()
530 }
531
532 /// Get the minute within the hour in the stored offset.
533 ///
534 /// The returned value will always be in the range `0..60`.
535 ///
536 /// ```rust
537 /// # use time_macros::{datetime, offset};
538 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).minute(), 0);
539 /// assert_eq!(
540 /// datetime!(2019-01-01 23:59:59 UTC)
541 /// .to_offset(offset!(+0:30))
542 /// .minute(),
543 /// 29,
544 /// );
545 /// ```
546 pub const fn minute(self) -> u8 {
547 self.0.minute()
548 }
549
550 /// Get the second within the minute in the stored offset.
551 ///
552 /// The returned value will always be in the range `0..60`.
553 ///
554 /// ```rust
555 /// # use time_macros::{datetime, offset};
556 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).second(), 0);
557 /// assert_eq!(
558 /// datetime!(2019-01-01 23:59:59 UTC)
559 /// .to_offset(offset!(+0:00:30))
560 /// .second(),
561 /// 29,
562 /// );
563 /// ```
564 pub const fn second(self) -> u8 {
565 self.0.second()
566 }
567
568 // Because a `UtcOffset` is limited in resolution to one second, any subsecond value will not
569 // change when adjusting for the offset.
570
571 /// Get the milliseconds within the second in the stored offset.
572 ///
573 /// The returned value will always be in the range `0..1_000`.
574 ///
575 /// ```rust
576 /// # use time_macros::datetime;
577 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).millisecond(), 0);
578 /// assert_eq!(datetime!(2019-01-01 23:59:59.999 UTC).millisecond(), 999);
579 /// ```
580 pub const fn millisecond(self) -> u16 {
581 self.0.millisecond()
582 }
583
584 /// Get the microseconds within the second in the stored offset.
585 ///
586 /// The returned value will always be in the range `0..1_000_000`.
587 ///
588 /// ```rust
589 /// # use time_macros::datetime;
590 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).microsecond(), 0);
591 /// assert_eq!(
592 /// datetime!(2019-01-01 23:59:59.999_999 UTC).microsecond(),
593 /// 999_999,
594 /// );
595 /// ```
596 pub const fn microsecond(self) -> u32 {
597 self.0.microsecond()
598 }
599
600 /// Get the nanoseconds within the second in the stored offset.
601 ///
602 /// The returned value will always be in the range `0..1_000_000_000`.
603 ///
604 /// ```rust
605 /// # use time_macros::datetime;
606 /// assert_eq!(datetime!(2019-01-01 0:00 UTC).nanosecond(), 0);
607 /// assert_eq!(
608 /// datetime!(2019-01-01 23:59:59.999_999_999 UTC).nanosecond(),
609 /// 999_999_999,
610 /// );
611 /// ```
612 pub const fn nanosecond(self) -> u32 {
613 self.0.nanosecond()
614 }
615 // endregion time getters
616 // endregion getters
617
618 // region: checked arithmetic
619 /// Computes `self + duration`, returning `None` if an overflow occurred.
620 ///
621 /// ```
622 /// # use time::{Date, ext::NumericalDuration};
623 /// # use time_macros::{datetime, offset};
624 /// let datetime = Date::MIN.midnight().assume_offset(offset!(+10));
625 /// assert_eq!(datetime.checked_add((-2).days()), None);
626 ///
627 /// let datetime = Date::MAX.midnight().assume_offset(offset!(+10));
628 /// assert_eq!(datetime.checked_add(2.days()), None);
629 ///
630 /// assert_eq!(
631 /// datetime!(2019 - 11 - 25 15:30 +10).checked_add(27.hours()),
632 /// Some(datetime!(2019 - 11 - 26 18:30 +10))
633 /// );
634 /// ```
635 pub const fn checked_add(self, duration: Duration) -> Option<Self> {
636 Some(Self(const_try_opt!(self.0.checked_add(duration))))
637 }
638
639 /// Computes `self - duration`, returning `None` if an overflow occurred.
640 ///
641 /// ```
642 /// # use time::{Date, ext::NumericalDuration};
643 /// # use time_macros::{datetime, offset};
644 /// let datetime = Date::MIN.midnight().assume_offset(offset!(+10));
645 /// assert_eq!(datetime.checked_sub(2.days()), None);
646 ///
647 /// let datetime = Date::MAX.midnight().assume_offset(offset!(+10));
648 /// assert_eq!(datetime.checked_sub((-2).days()), None);
649 ///
650 /// assert_eq!(
651 /// datetime!(2019 - 11 - 25 15:30 +10).checked_sub(27.hours()),
652 /// Some(datetime!(2019 - 11 - 24 12:30 +10))
653 /// );
654 /// ```
655 pub const fn checked_sub(self, duration: Duration) -> Option<Self> {
656 Some(Self(const_try_opt!(self.0.checked_sub(duration))))
657 }
658 // endregion: checked arithmetic
659
660 // region: saturating arithmetic
661 /// Computes `self + duration`, saturating value on overflow.
662 ///
663 /// ```
664 /// # use time::ext::NumericalDuration;
665 /// # use time_macros::datetime;
666 /// assert_eq!(
667 #[cfg_attr(
668 feature = "large-dates",
669 doc = " datetime!(-999999-01-01 0:00 +10).saturating_add((-2).days()),"
670 )]
671 #[cfg_attr(feature = "large-dates", doc = " datetime!(-999999-01-01 0:00 +10)")]
672 #[cfg_attr(
673 not(feature = "large-dates"),
674 doc = " datetime!(-9999-01-01 0:00 +10).saturating_add((-2).days()),"
675 )]
676 #[cfg_attr(
677 not(feature = "large-dates"),
678 doc = " datetime!(-9999-01-01 0:00 +10)"
679 )]
680 /// );
681 ///
682 /// assert_eq!(
683 #[cfg_attr(
684 feature = "large-dates",
685 doc = " datetime!(+999999-12-31 23:59:59.999_999_999 +10).saturating_add(2.days()),"
686 )]
687 #[cfg_attr(
688 feature = "large-dates",
689 doc = " datetime!(+999999-12-31 23:59:59.999_999_999 +10)"
690 )]
691 #[cfg_attr(
692 not(feature = "large-dates"),
693 doc = " datetime!(+9999-12-31 23:59:59.999_999_999 +10).saturating_add(2.days()),"
694 )]
695 #[cfg_attr(
696 not(feature = "large-dates"),
697 doc = " datetime!(+9999-12-31 23:59:59.999_999_999 +10)"
698 )]
699 /// );
700 ///
701 /// assert_eq!(
702 /// datetime!(2019 - 11 - 25 15:30 +10).saturating_add(27.hours()),
703 /// datetime!(2019 - 11 - 26 18:30 +10)
704 /// );
705 /// ```
706 pub const fn saturating_add(self, duration: Duration) -> Self {
707 Self(self.0.saturating_add(duration))
708 }
709
710 /// Computes `self - duration`, saturating value on overflow.
711 ///
712 /// ```
713 /// # use time::ext::NumericalDuration;
714 /// # use time_macros::datetime;
715 /// assert_eq!(
716 #[cfg_attr(
717 feature = "large-dates",
718 doc = " datetime!(-999999-01-01 0:00 +10).saturating_sub(2.days()),"
719 )]
720 #[cfg_attr(feature = "large-dates", doc = " datetime!(-999999-01-01 0:00 +10)")]
721 #[cfg_attr(
722 not(feature = "large-dates"),
723 doc = " datetime!(-9999-01-01 0:00 +10).saturating_sub(2.days()),"
724 )]
725 #[cfg_attr(
726 not(feature = "large-dates"),
727 doc = " datetime!(-9999-01-01 0:00 +10)"
728 )]
729 /// );
730 ///
731 /// assert_eq!(
732 #[cfg_attr(
733 feature = "large-dates",
734 doc = " datetime!(+999999-12-31 23:59:59.999_999_999 +10).saturating_sub((-2).days()),"
735 )]
736 #[cfg_attr(
737 feature = "large-dates",
738 doc = " datetime!(+999999-12-31 23:59:59.999_999_999 +10)"
739 )]
740 #[cfg_attr(
741 not(feature = "large-dates"),
742 doc = " datetime!(+9999-12-31 23:59:59.999_999_999 +10).saturating_sub((-2).days()),"
743 )]
744 #[cfg_attr(
745 not(feature = "large-dates"),
746 doc = " datetime!(+9999-12-31 23:59:59.999_999_999 +10)"
747 )]
748 /// );
749 ///
750 /// assert_eq!(
751 /// datetime!(2019 - 11 - 25 15:30 +10).saturating_sub(27.hours()),
752 /// datetime!(2019 - 11 - 24 12:30 +10)
753 /// );
754 /// ```
755 pub const fn saturating_sub(self, duration: Duration) -> Self {
756 Self(self.0.saturating_sub(duration))
757 }
758 // endregion: saturating arithmetic
759}
760
761// region: replacement
762/// Methods that replace part of the `OffsetDateTime`.
763impl OffsetDateTime {
764 /// Replace the time, which is assumed to be in the stored offset. The date and offset
765 /// components are unchanged.
766 ///
767 /// ```rust
768 /// # use time_macros::{datetime, time};
769 /// assert_eq!(
770 /// datetime!(2020-01-01 5:00 UTC).replace_time(time!(12:00)),
771 /// datetime!(2020-01-01 12:00 UTC)
772 /// );
773 /// assert_eq!(
774 /// datetime!(2020-01-01 12:00 -5).replace_time(time!(7:00)),
775 /// datetime!(2020-01-01 7:00 -5)
776 /// );
777 /// assert_eq!(
778 /// datetime!(2020-01-01 0:00 +1).replace_time(time!(12:00)),
779 /// datetime!(2020-01-01 12:00 +1)
780 /// );
781 /// ```
782 #[must_use = "This method does not mutate the original `OffsetDateTime`."]
783 pub const fn replace_time(self, time: Time) -> Self {
784 Self(self.0.replace_time(time))
785 }
786
787 /// Replace the date, which is assumed to be in the stored offset. The time and offset
788 /// components are unchanged.
789 ///
790 /// ```rust
791 /// # use time_macros::{datetime, date};
792 /// assert_eq!(
793 /// datetime!(2020-01-01 12:00 UTC).replace_date(date!(2020-01-30)),
794 /// datetime!(2020-01-30 12:00 UTC)
795 /// );
796 /// assert_eq!(
797 /// datetime!(2020-01-01 0:00 +1).replace_date(date!(2020-01-30)),
798 /// datetime!(2020-01-30 0:00 +1)
799 /// );
800 /// ```
801 #[must_use = "This method does not mutate the original `OffsetDateTime`."]
802 pub const fn replace_date(self, date: Date) -> Self {
803 Self(self.0.replace_date(date))
804 }
805
806 /// Replace the date and time, which are assumed to be in the stored offset. The offset
807 /// component remains unchanged.
808 ///
809 /// ```rust
810 /// # use time_macros::datetime;
811 /// assert_eq!(
812 /// datetime!(2020-01-01 12:00 UTC).replace_date_time(datetime!(2020-01-30 16:00)),
813 /// datetime!(2020-01-30 16:00 UTC)
814 /// );
815 /// assert_eq!(
816 /// datetime!(2020-01-01 12:00 +1).replace_date_time(datetime!(2020-01-30 0:00)),
817 /// datetime!(2020-01-30 0:00 +1)
818 /// );
819 /// ```
820 #[must_use = "This method does not mutate the original `OffsetDateTime`."]
821 pub const fn replace_date_time(self, date_time: PrimitiveDateTime) -> Self {
822 Self(self.0.replace_date_time(date_time.0))
823 }
824
825 /// Replace the offset. The date and time components remain unchanged.
826 ///
827 /// ```rust
828 /// # use time_macros::{datetime, offset};
829 /// assert_eq!(
830 /// datetime!(2020-01-01 0:00 UTC).replace_offset(offset!(-5)),
831 /// datetime!(2020-01-01 0:00 -5)
832 /// );
833 /// ```
834 #[must_use = "This method does not mutate the original `OffsetDateTime`."]
835 pub const fn replace_offset(self, offset: UtcOffset) -> Self {
836 Self(self.0.replace_offset(offset))
837 }
838
839 /// Replace the year. The month and day will be unchanged.
840 ///
841 /// ```rust
842 /// # use time_macros::datetime;
843 /// assert_eq!(
844 /// datetime!(2022 - 02 - 18 12:00 +01).replace_year(2019),
845 /// Ok(datetime!(2019 - 02 - 18 12:00 +01))
846 /// );
847 /// assert!(datetime!(2022 - 02 - 18 12:00 +01).replace_year(-1_000_000_000).is_err()); // -1_000_000_000 isn't a valid year
848 /// assert!(datetime!(2022 - 02 - 18 12:00 +01).replace_year(1_000_000_000).is_err()); // 1_000_000_000 isn't a valid year
849 /// ```
850 pub const fn replace_year(self, year: i32) -> Result<Self, error::ComponentRange> {
851 Ok(Self(const_try!(self.0.replace_year(year))))
852 }
853
854 /// Replace the month of the year.
855 ///
856 /// ```rust
857 /// # use time_macros::datetime;
858 /// # use time::Month;
859 /// assert_eq!(
860 /// datetime!(2022 - 02 - 18 12:00 +01).replace_month(Month::January),
861 /// Ok(datetime!(2022 - 01 - 18 12:00 +01))
862 /// );
863 /// assert!(datetime!(2022 - 01 - 30 12:00 +01).replace_month(Month::February).is_err()); // 30 isn't a valid day in February
864 /// ```
865 pub const fn replace_month(self, month: Month) -> Result<Self, error::ComponentRange> {
866 Ok(Self(const_try!(self.0.replace_month(month))))
867 }
868
869 /// Replace the day of the month.
870 ///
871 /// ```rust
872 /// # use time_macros::datetime;
873 /// assert_eq!(
874 /// datetime!(2022 - 02 - 18 12:00 +01).replace_day(1),
875 /// Ok(datetime!(2022 - 02 - 01 12:00 +01))
876 /// );
877 /// assert!(datetime!(2022 - 02 - 18 12:00 +01).replace_day(0).is_err()); // 00 isn't a valid day
878 /// assert!(datetime!(2022 - 02 - 18 12:00 +01).replace_day(30).is_err()); // 30 isn't a valid day in February
879 /// ```
880 pub const fn replace_day(self, day: u8) -> Result<Self, error::ComponentRange> {
881 Ok(Self(const_try!(self.0.replace_day(day))))
882 }
883
884 /// Replace the clock hour.
885 ///
886 /// ```rust
887 /// # use time_macros::datetime;
888 /// assert_eq!(
889 /// datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_hour(7),
890 /// Ok(datetime!(2022 - 02 - 18 07:02:03.004_005_006 +01))
891 /// );
892 /// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_hour(24).is_err()); // 24 isn't a valid hour
893 /// ```
894 pub const fn replace_hour(self, hour: u8) -> Result<Self, error::ComponentRange> {
895 Ok(Self(const_try!(self.0.replace_hour(hour))))
896 }
897
898 /// Replace the minutes within the hour.
899 ///
900 /// ```rust
901 /// # use time_macros::datetime;
902 /// assert_eq!(
903 /// datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_minute(7),
904 /// Ok(datetime!(2022 - 02 - 18 01:07:03.004_005_006 +01))
905 /// );
906 /// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_minute(60).is_err()); // 60 isn't a valid minute
907 /// ```
908 pub const fn replace_minute(self, minute: u8) -> Result<Self, error::ComponentRange> {
909 Ok(Self(const_try!(self.0.replace_minute(minute))))
910 }
911
912 /// Replace the seconds within the minute.
913 ///
914 /// ```rust
915 /// # use time_macros::datetime;
916 /// assert_eq!(
917 /// datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_second(7),
918 /// Ok(datetime!(2022 - 02 - 18 01:02:07.004_005_006 +01))
919 /// );
920 /// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_second(60).is_err()); // 60 isn't a valid second
921 /// ```
922 pub const fn replace_second(self, second: u8) -> Result<Self, error::ComponentRange> {
923 Ok(Self(const_try!(self.0.replace_second(second))))
924 }
925
926 /// Replace the milliseconds within the second.
927 ///
928 /// ```rust
929 /// # use time_macros::datetime;
930 /// assert_eq!(
931 /// datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_millisecond(7),
932 /// Ok(datetime!(2022 - 02 - 18 01:02:03.007 +01))
933 /// );
934 /// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_millisecond(1_000).is_err()); // 1_000 isn't a valid millisecond
935 /// ```
936 pub const fn replace_millisecond(
937 self,
938 millisecond: u16,
939 ) -> Result<Self, error::ComponentRange> {
940 Ok(Self(const_try!(self.0.replace_millisecond(millisecond))))
941 }
942
943 /// Replace the microseconds within the second.
944 ///
945 /// ```rust
946 /// # use time_macros::datetime;
947 /// assert_eq!(
948 /// datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_microsecond(7_008),
949 /// Ok(datetime!(2022 - 02 - 18 01:02:03.007_008 +01))
950 /// );
951 /// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_microsecond(1_000_000).is_err()); // 1_000_000 isn't a valid microsecond
952 /// ```
953 pub const fn replace_microsecond(
954 self,
955 microsecond: u32,
956 ) -> Result<Self, error::ComponentRange> {
957 Ok(Self(const_try!(self.0.replace_microsecond(microsecond))))
958 }
959
960 /// Replace the nanoseconds within the second.
961 ///
962 /// ```rust
963 /// # use time_macros::datetime;
964 /// assert_eq!(
965 /// datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_nanosecond(7_008_009),
966 /// Ok(datetime!(2022 - 02 - 18 01:02:03.007_008_009 +01))
967 /// );
968 /// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_nanosecond(1_000_000_000).is_err()); // 1_000_000_000 isn't a valid nanosecond
969 /// ```
970 pub const fn replace_nanosecond(self, nanosecond: u32) -> Result<Self, error::ComponentRange> {
971 Ok(Self(const_try!(self.0.replace_nanosecond(nanosecond))))
972 }
973}
974// endregion replacement
975
976// region: formatting & parsing
977#[cfg(feature = "formatting")]
978impl OffsetDateTime {
979 /// Format the `OffsetDateTime` using the provided [format
980 /// description](crate::format_description).
981 pub fn format_into(
982 self,
983 output: &mut impl io::Write,
984 format: &(impl Formattable + ?Sized),
985 ) -> Result<usize, error::Format> {
986 self.0.format_into(output, format)
987 }
988
989 /// Format the `OffsetDateTime` using the provided [format
990 /// description](crate::format_description).
991 ///
992 /// ```rust
993 /// # use time::format_description;
994 /// # use time_macros::datetime;
995 /// let format = format_description::parse(
996 /// "[year]-[month]-[day] [hour]:[minute]:[second] [offset_hour \
997 /// sign:mandatory]:[offset_minute]:[offset_second]",
998 /// )?;
999 /// assert_eq!(
1000 /// datetime!(2020-01-02 03:04:05 +06:07:08).format(&format)?,
1001 /// "2020-01-02 03:04:05 +06:07:08"
1002 /// );
1003 /// # Ok::<_, time::Error>(())
1004 /// ```
1005 pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result<String, error::Format> {
1006 self.0.format(format)
1007 }
1008}
1009
1010#[cfg(feature = "parsing")]
1011impl OffsetDateTime {
1012 /// Parse an `OffsetDateTime` from the input using the provided [format
1013 /// description](crate::format_description).
1014 ///
1015 /// ```rust
1016 /// # use time::OffsetDateTime;
1017 /// # use time_macros::{datetime, format_description};
1018 /// let format = format_description!(
1019 /// "[year]-[month]-[day] [hour]:[minute]:[second] [offset_hour \
1020 /// sign:mandatory]:[offset_minute]:[offset_second]"
1021 /// );
1022 /// assert_eq!(
1023 /// OffsetDateTime::parse("2020-01-02 03:04:05 +06:07:08", &format)?,
1024 /// datetime!(2020-01-02 03:04:05 +06:07:08)
1025 /// );
1026 /// # Ok::<_, time::Error>(())
1027 /// ```
1028 pub fn parse(
1029 input: &str,
1030 description: &(impl Parsable + ?Sized),
1031 ) -> Result<Self, error::Parse> {
1032 Inner::parse(input, description).map(Self)
1033 }
1034}
1035
1036impl fmt::Display for OffsetDateTime {
1037 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1038 self.0.fmt(f)
1039 }
1040}
1041
1042impl fmt::Debug for OffsetDateTime {
1043 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1044 fmt::Display::fmt(self, f)
1045 }
1046}
1047// endregion formatting & parsing
1048
1049// region: trait impls
1050impl Add<Duration> for OffsetDateTime {
1051 type Output = Self;
1052
1053 fn add(self, rhs: Duration) -> Self::Output {
1054 Self(self.0.add(rhs))
1055 }
1056}
1057
1058impl Add<StdDuration> for OffsetDateTime {
1059 type Output = Self;
1060
1061 fn add(self, rhs: StdDuration) -> Self::Output {
1062 Self(self.0.add(rhs))
1063 }
1064}
1065
1066impl AddAssign<Duration> for OffsetDateTime {
1067 fn add_assign(&mut self, rhs: Duration) {
1068 self.0.add_assign(rhs);
1069 }
1070}
1071
1072impl AddAssign<StdDuration> for OffsetDateTime {
1073 fn add_assign(&mut self, rhs: StdDuration) {
1074 self.0.add_assign(rhs);
1075 }
1076}
1077
1078impl Sub<Duration> for OffsetDateTime {
1079 type Output = Self;
1080
1081 fn sub(self, rhs: Duration) -> Self::Output {
1082 Self(self.0.sub(rhs))
1083 }
1084}
1085
1086impl Sub<StdDuration> for OffsetDateTime {
1087 type Output = Self;
1088
1089 fn sub(self, rhs: StdDuration) -> Self::Output {
1090 Self(self.0.sub(rhs))
1091 }
1092}
1093
1094impl SubAssign<Duration> for OffsetDateTime {
1095 fn sub_assign(&mut self, rhs: Duration) {
1096 self.0.sub_assign(rhs);
1097 }
1098}
1099
1100impl SubAssign<StdDuration> for OffsetDateTime {
1101 fn sub_assign(&mut self, rhs: StdDuration) {
1102 self.0.sub_assign(rhs);
1103 }
1104}
1105
1106impl Sub for OffsetDateTime {
1107 type Output = Duration;
1108
1109 fn sub(self, rhs: Self) -> Self::Output {
1110 self.0.sub(rhs.0)
1111 }
1112}
1113
1114#[cfg(feature = "std")]
1115impl Sub<SystemTime> for OffsetDateTime {
1116 type Output = Duration;
1117
1118 fn sub(self, rhs: SystemTime) -> Self::Output {
1119 self.0.sub(rhs)
1120 }
1121}
1122
1123#[cfg(feature = "std")]
1124impl Sub<OffsetDateTime> for SystemTime {
1125 type Output = Duration;
1126
1127 fn sub(self, rhs: OffsetDateTime) -> Self::Output {
1128 self.sub(rhs.0)
1129 }
1130}
1131
1132#[cfg(feature = "std")]
1133impl PartialEq<SystemTime> for OffsetDateTime {
1134 fn eq(&self, rhs: &SystemTime) -> bool {
1135 self.0.eq(rhs)
1136 }
1137}
1138
1139#[cfg(feature = "std")]
1140impl PartialEq<OffsetDateTime> for SystemTime {
1141 fn eq(&self, rhs: &OffsetDateTime) -> bool {
1142 self.eq(&rhs.0)
1143 }
1144}
1145
1146#[cfg(feature = "std")]
1147impl PartialOrd<SystemTime> for OffsetDateTime {
1148 fn partial_cmp(&self, other: &SystemTime) -> Option<Ordering> {
1149 self.0.partial_cmp(other)
1150 }
1151}
1152
1153#[cfg(feature = "std")]
1154impl PartialOrd<OffsetDateTime> for SystemTime {
1155 fn partial_cmp(&self, other: &OffsetDateTime) -> Option<Ordering> {
1156 self.partial_cmp(&other.0)
1157 }
1158}
1159
1160#[cfg(feature = "std")]
1161impl From<SystemTime> for OffsetDateTime {
1162 fn from(system_time: SystemTime) -> Self {
1163 Self(Inner::from(system_time))
1164 }
1165}
1166
1167#[cfg(feature = "std")]
1168impl From<OffsetDateTime> for SystemTime {
1169 fn from(datetime: OffsetDateTime) -> Self {
1170 datetime.0.into()
1171 }
1172}
1173
1174#[cfg(all(
1175 target_family = "wasm",
1176 not(any(target_os = "emscripten", target_os = "wasi")),
1177 feature = "wasm-bindgen"
1178))]
1179impl From<js_sys::Date> for OffsetDateTime {
1180 fn from(js_date: js_sys::Date) -> Self {
1181 Self(Inner::from(js_date))
1182 }
1183}
1184
1185#[cfg(all(
1186 target_family = "wasm",
1187 not(any(target_os = "emscripten", target_os = "wasi")),
1188 feature = "wasm-bindgen"
1189))]
1190impl From<OffsetDateTime> for js_sys::Date {
1191 fn from(datetime: OffsetDateTime) -> Self {
1192 datetime.0.into()
1193 }
1194}
1195
1196// endregion trait impls
1197