1// This is a part of Chrono.
2// See README.md and LICENSE.txt for details.
3
4//! ISO 8601 date and time with time zone.
5
6#[cfg(all(not(feature = "std"), feature = "alloc"))]
7use alloc::string::String;
8use core::borrow::Borrow;
9use core::cmp::Ordering;
10use core::fmt::Write;
11use core::ops::{Add, AddAssign, Sub, SubAssign};
12use core::time::Duration;
13use core::{fmt, hash, str};
14#[cfg(feature = "std")]
15use std::time::{SystemTime, UNIX_EPOCH};
16
17#[cfg(all(feature = "unstable-locales", feature = "alloc"))]
18use crate::format::Locale;
19use crate::format::{
20 parse, parse_and_remainder, parse_rfc3339, Fixed, Item, ParseError, ParseResult, Parsed,
21 StrftimeItems, TOO_LONG,
22};
23#[cfg(feature = "alloc")]
24use crate::format::{write_rfc2822, write_rfc3339, DelayedFormat, SecondsFormat};
25use crate::naive::{Days, IsoWeek, NaiveDate, NaiveDateTime, NaiveTime};
26#[cfg(feature = "clock")]
27use crate::offset::Local;
28use crate::offset::{FixedOffset, Offset, TimeZone, Utc};
29#[allow(deprecated)]
30use crate::Date;
31use crate::{expect, try_opt};
32use crate::{Datelike, Months, TimeDelta, Timelike, Weekday};
33
34#[cfg(any(feature = "rkyv", feature = "rkyv-16", feature = "rkyv-32", feature = "rkyv-64"))]
35use rkyv::{Archive, Deserialize, Serialize};
36
37#[cfg(feature = "rustc-serialize")]
38pub(super) mod rustc_serialize;
39
40/// documented at re-export site
41#[cfg(feature = "serde")]
42pub(super) mod serde;
43
44#[cfg(test)]
45mod tests;
46
47/// ISO 8601 combined date and time with time zone.
48///
49/// There are some constructors implemented here (the `from_*` methods), but
50/// the general-purpose constructors are all via the methods on the
51/// [`TimeZone`](./offset/trait.TimeZone.html) implementations.
52#[derive(Clone)]
53#[cfg_attr(
54 any(feature = "rkyv", feature = "rkyv-16", feature = "rkyv-32", feature = "rkyv-64"),
55 derive(Archive, Deserialize, Serialize),
56 archive(compare(PartialEq, PartialOrd))
57)]
58#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))]
59pub struct DateTime<Tz: TimeZone> {
60 datetime: NaiveDateTime,
61 offset: Tz::Offset,
62}
63
64/// The minimum possible `DateTime<Utc>`.
65#[deprecated(since = "0.4.20", note = "Use DateTime::MIN_UTC instead")]
66pub const MIN_DATETIME: DateTime<Utc> = DateTime::<Utc>::MIN_UTC;
67/// The maximum possible `DateTime<Utc>`.
68#[deprecated(since = "0.4.20", note = "Use DateTime::MAX_UTC instead")]
69pub const MAX_DATETIME: DateTime<Utc> = DateTime::<Utc>::MAX_UTC;
70
71impl<Tz: TimeZone> DateTime<Tz> {
72 /// Makes a new `DateTime` from its components: a `NaiveDateTime` in UTC and an `Offset`.
73 ///
74 /// This is a low-level method, intended for use cases such as deserializing a `DateTime` or
75 /// passing it through FFI.
76 ///
77 /// For regular use you will probably want to use a method such as
78 /// [`TimeZone::from_local_datetime`] or [`NaiveDateTime::and_local_timezone`] instead.
79 ///
80 /// # Example
81 ///
82 #[cfg_attr(not(feature = "clock"), doc = "```ignore")]
83 #[cfg_attr(feature = "clock", doc = "```rust")]
84 /// use chrono::{DateTime, Local};
85 ///
86 /// let dt = Local::now();
87 /// // Get components
88 /// let naive_utc = dt.naive_utc();
89 /// let offset = dt.offset().clone();
90 /// // Serialize, pass through FFI... and recreate the `DateTime`:
91 /// let dt_new = DateTime::<Local>::from_naive_utc_and_offset(naive_utc, offset);
92 /// assert_eq!(dt, dt_new);
93 /// ```
94 #[inline]
95 #[must_use]
96 pub const fn from_naive_utc_and_offset(
97 datetime: NaiveDateTime,
98 offset: Tz::Offset,
99 ) -> DateTime<Tz> {
100 DateTime { datetime, offset }
101 }
102
103 /// Makes a new `DateTime` from its components: a `NaiveDateTime` in UTC and an `Offset`.
104 #[inline]
105 #[must_use]
106 #[deprecated(
107 since = "0.4.27",
108 note = "Use TimeZone::from_utc_datetime() or DateTime::from_naive_utc_and_offset instead"
109 )]
110 pub fn from_utc(datetime: NaiveDateTime, offset: Tz::Offset) -> DateTime<Tz> {
111 DateTime { datetime, offset }
112 }
113
114 /// Makes a new `DateTime` from a `NaiveDateTime` in *local* time and an `Offset`.
115 ///
116 /// # Panics
117 ///
118 /// Panics if the local datetime can't be converted to UTC because it would be out of range.
119 ///
120 /// This can happen if `datetime` is near the end of the representable range of `NaiveDateTime`,
121 /// and the offset from UTC pushes it beyond that.
122 #[inline]
123 #[must_use]
124 #[deprecated(
125 since = "0.4.27",
126 note = "Use TimeZone::from_local_datetime() or NaiveDateTime::and_local_timezone instead"
127 )]
128 pub fn from_local(datetime: NaiveDateTime, offset: Tz::Offset) -> DateTime<Tz> {
129 let datetime_utc = datetime - offset.fix();
130
131 DateTime { datetime: datetime_utc, offset }
132 }
133
134 /// Retrieves the date component with an associated timezone.
135 ///
136 /// Unless you are immediately planning on turning this into a `DateTime`
137 /// with the same timezone you should use the [`date_naive`](DateTime::date_naive) method.
138 ///
139 /// [`NaiveDate`] is a more well-defined type, and has more traits implemented on it,
140 /// so should be preferred to [`Date`] any time you truly want to operate on dates.
141 ///
142 /// # Panics
143 ///
144 /// [`DateTime`] internally stores the date and time in UTC with a [`NaiveDateTime`]. This
145 /// method will panic if the offset from UTC would push the local date outside of the
146 /// representable range of a [`Date`].
147 #[inline]
148 #[deprecated(since = "0.4.23", note = "Use `date_naive()` instead")]
149 #[allow(deprecated)]
150 #[must_use]
151 pub fn date(&self) -> Date<Tz> {
152 Date::from_utc(self.naive_local().date(), self.offset.clone())
153 }
154
155 /// Retrieves the date component.
156 ///
157 /// # Panics
158 ///
159 /// [`DateTime`] internally stores the date and time in UTC with a [`NaiveDateTime`]. This
160 /// method will panic if the offset from UTC would push the local date outside of the
161 /// representable range of a [`NaiveDate`].
162 ///
163 /// # Example
164 ///
165 /// ```
166 /// use chrono::prelude::*;
167 ///
168 /// let date: DateTime<Utc> = Utc.with_ymd_and_hms(2020, 1, 1, 0, 0, 0).unwrap();
169 /// let other: DateTime<FixedOffset> =
170 /// FixedOffset::east_opt(23).unwrap().with_ymd_and_hms(2020, 1, 1, 0, 0, 0).unwrap();
171 /// assert_eq!(date.date_naive(), other.date_naive());
172 /// ```
173 #[inline]
174 #[must_use]
175 pub fn date_naive(&self) -> NaiveDate {
176 let local = self.naive_local();
177 NaiveDate::from_ymd_opt(local.year(), local.month(), local.day()).unwrap()
178 }
179
180 /// Retrieves the time component.
181 #[inline]
182 #[must_use]
183 pub fn time(&self) -> NaiveTime {
184 self.datetime.time() + self.offset.fix()
185 }
186
187 /// Returns the number of non-leap seconds since January 1, 1970 0:00:00 UTC
188 /// (aka "UNIX timestamp").
189 ///
190 /// The reverse operation of creating a [`DateTime`] from a timestamp can be performed
191 /// using [`from_timestamp`](DateTime::from_timestamp) or [`TimeZone::timestamp_opt`].
192 ///
193 /// ```
194 /// use chrono::{DateTime, TimeZone, Utc};
195 ///
196 /// let dt: DateTime<Utc> = Utc.with_ymd_and_hms(2015, 5, 15, 0, 0, 0).unwrap();
197 /// assert_eq!(dt.timestamp(), 1431648000);
198 ///
199 /// assert_eq!(DateTime::from_timestamp(dt.timestamp(), dt.timestamp_subsec_nanos()).unwrap(), dt);
200 /// ```
201 #[inline]
202 #[must_use]
203 pub const fn timestamp(&self) -> i64 {
204 let gregorian_day = self.datetime.date().num_days_from_ce() as i64;
205 let seconds_from_midnight = self.datetime.time().num_seconds_from_midnight() as i64;
206 (gregorian_day - UNIX_EPOCH_DAY) * 86_400 + seconds_from_midnight
207 }
208
209 /// Returns the number of non-leap-milliseconds since January 1, 1970 UTC.
210 ///
211 /// # Example
212 ///
213 /// ```
214 /// use chrono::{NaiveDate, Utc};
215 ///
216 /// let dt = NaiveDate::from_ymd_opt(1970, 1, 1)
217 /// .unwrap()
218 /// .and_hms_milli_opt(0, 0, 1, 444)
219 /// .unwrap()
220 /// .and_local_timezone(Utc)
221 /// .unwrap();
222 /// assert_eq!(dt.timestamp_millis(), 1_444);
223 ///
224 /// let dt = NaiveDate::from_ymd_opt(2001, 9, 9)
225 /// .unwrap()
226 /// .and_hms_milli_opt(1, 46, 40, 555)
227 /// .unwrap()
228 /// .and_local_timezone(Utc)
229 /// .unwrap();
230 /// assert_eq!(dt.timestamp_millis(), 1_000_000_000_555);
231 /// ```
232 #[inline]
233 #[must_use]
234 pub const fn timestamp_millis(&self) -> i64 {
235 let as_ms = self.timestamp() * 1000;
236 as_ms + self.timestamp_subsec_millis() as i64
237 }
238
239 /// Returns the number of non-leap-microseconds since January 1, 1970 UTC.
240 ///
241 /// # Example
242 ///
243 /// ```
244 /// use chrono::{NaiveDate, Utc};
245 ///
246 /// let dt = NaiveDate::from_ymd_opt(1970, 1, 1)
247 /// .unwrap()
248 /// .and_hms_micro_opt(0, 0, 1, 444)
249 /// .unwrap()
250 /// .and_local_timezone(Utc)
251 /// .unwrap();
252 /// assert_eq!(dt.timestamp_micros(), 1_000_444);
253 ///
254 /// let dt = NaiveDate::from_ymd_opt(2001, 9, 9)
255 /// .unwrap()
256 /// .and_hms_micro_opt(1, 46, 40, 555)
257 /// .unwrap()
258 /// .and_local_timezone(Utc)
259 /// .unwrap();
260 /// assert_eq!(dt.timestamp_micros(), 1_000_000_000_000_555);
261 /// ```
262 #[inline]
263 #[must_use]
264 pub const fn timestamp_micros(&self) -> i64 {
265 let as_us = self.timestamp() * 1_000_000;
266 as_us + self.timestamp_subsec_micros() as i64
267 }
268
269 /// Returns the number of non-leap-nanoseconds since January 1, 1970 UTC.
270 ///
271 /// # Panics
272 ///
273 /// An `i64` with nanosecond precision can span a range of ~584 years. This function panics on
274 /// an out of range `DateTime`.
275 ///
276 /// The dates that can be represented as nanoseconds are between 1677-09-21T00:12:43.145224192
277 /// and 2262-04-11T23:47:16.854775807.
278 #[deprecated(since = "0.4.31", note = "use `timestamp_nanos_opt()` instead")]
279 #[inline]
280 #[must_use]
281 pub const fn timestamp_nanos(&self) -> i64 {
282 expect!(
283 self.timestamp_nanos_opt(),
284 "value can not be represented in a timestamp with nanosecond precision."
285 )
286 }
287
288 /// Returns the number of non-leap-nanoseconds since January 1, 1970 UTC.
289 ///
290 /// # Errors
291 ///
292 /// An `i64` with nanosecond precision can span a range of ~584 years. This function returns
293 /// `None` on an out of range `DateTime`.
294 ///
295 /// The dates that can be represented as nanoseconds are between 1677-09-21T00:12:43.145224192
296 /// and 2262-04-11T23:47:16.854775807.
297 ///
298 /// # Example
299 ///
300 /// ```
301 /// use chrono::{NaiveDate, Utc};
302 ///
303 /// let dt = NaiveDate::from_ymd_opt(1970, 1, 1)
304 /// .unwrap()
305 /// .and_hms_nano_opt(0, 0, 1, 444)
306 /// .unwrap()
307 /// .and_local_timezone(Utc)
308 /// .unwrap();
309 /// assert_eq!(dt.timestamp_nanos_opt(), Some(1_000_000_444));
310 ///
311 /// let dt = NaiveDate::from_ymd_opt(2001, 9, 9)
312 /// .unwrap()
313 /// .and_hms_nano_opt(1, 46, 40, 555)
314 /// .unwrap()
315 /// .and_local_timezone(Utc)
316 /// .unwrap();
317 /// assert_eq!(dt.timestamp_nanos_opt(), Some(1_000_000_000_000_000_555));
318 ///
319 /// let dt = NaiveDate::from_ymd_opt(1677, 9, 21)
320 /// .unwrap()
321 /// .and_hms_nano_opt(0, 12, 43, 145_224_192)
322 /// .unwrap()
323 /// .and_local_timezone(Utc)
324 /// .unwrap();
325 /// assert_eq!(dt.timestamp_nanos_opt(), Some(-9_223_372_036_854_775_808));
326 ///
327 /// let dt = NaiveDate::from_ymd_opt(2262, 4, 11)
328 /// .unwrap()
329 /// .and_hms_nano_opt(23, 47, 16, 854_775_807)
330 /// .unwrap()
331 /// .and_local_timezone(Utc)
332 /// .unwrap();
333 /// assert_eq!(dt.timestamp_nanos_opt(), Some(9_223_372_036_854_775_807));
334 ///
335 /// let dt = NaiveDate::from_ymd_opt(1677, 9, 21)
336 /// .unwrap()
337 /// .and_hms_nano_opt(0, 12, 43, 145_224_191)
338 /// .unwrap()
339 /// .and_local_timezone(Utc)
340 /// .unwrap();
341 /// assert_eq!(dt.timestamp_nanos_opt(), None);
342 ///
343 /// let dt = NaiveDate::from_ymd_opt(2262, 4, 11)
344 /// .unwrap()
345 /// .and_hms_nano_opt(23, 47, 16, 854_775_808)
346 /// .unwrap()
347 /// .and_local_timezone(Utc)
348 /// .unwrap();
349 /// assert_eq!(dt.timestamp_nanos_opt(), None);
350 /// ```
351 #[inline]
352 #[must_use]
353 pub const fn timestamp_nanos_opt(&self) -> Option<i64> {
354 let mut timestamp = self.timestamp();
355 let mut subsec_nanos = self.timestamp_subsec_nanos() as i64;
356 // `(timestamp * 1_000_000_000) + subsec_nanos` may create a temporary that underflows while
357 // the final value can be represented as an `i64`.
358 // As workaround we converting the negative case to:
359 // `((timestamp + 1) * 1_000_000_000) + (ns - 1_000_000_000)``
360 //
361 // Also see <https://github.com/chronotope/chrono/issues/1289>.
362 if timestamp < 0 {
363 subsec_nanos -= 1_000_000_000;
364 timestamp += 1;
365 }
366 try_opt!(timestamp.checked_mul(1_000_000_000)).checked_add(subsec_nanos)
367 }
368
369 /// Returns the number of milliseconds since the last second boundary.
370 ///
371 /// In event of a leap second this may exceed 999.
372 #[inline]
373 #[must_use]
374 pub const fn timestamp_subsec_millis(&self) -> u32 {
375 self.timestamp_subsec_nanos() / 1_000_000
376 }
377
378 /// Returns the number of microseconds since the last second boundary.
379 ///
380 /// In event of a leap second this may exceed 999,999.
381 #[inline]
382 #[must_use]
383 pub const fn timestamp_subsec_micros(&self) -> u32 {
384 self.timestamp_subsec_nanos() / 1_000
385 }
386
387 /// Returns the number of nanoseconds since the last second boundary
388 ///
389 /// In event of a leap second this may exceed 999,999,999.
390 #[inline]
391 #[must_use]
392 pub const fn timestamp_subsec_nanos(&self) -> u32 {
393 self.datetime.time().nanosecond()
394 }
395
396 /// Retrieves an associated offset from UTC.
397 #[inline]
398 #[must_use]
399 pub const fn offset(&self) -> &Tz::Offset {
400 &self.offset
401 }
402
403 /// Retrieves an associated time zone.
404 #[inline]
405 #[must_use]
406 pub fn timezone(&self) -> Tz {
407 TimeZone::from_offset(&self.offset)
408 }
409
410 /// Changes the associated time zone.
411 /// The returned `DateTime` references the same instant of time from the perspective of the
412 /// provided time zone.
413 #[inline]
414 #[must_use]
415 pub fn with_timezone<Tz2: TimeZone>(&self, tz: &Tz2) -> DateTime<Tz2> {
416 tz.from_utc_datetime(&self.datetime)
417 }
418
419 /// Fix the offset from UTC to its current value, dropping the associated timezone information.
420 /// This it useful for converting a generic `DateTime<Tz: Timezone>` to `DateTime<FixedOffset>`.
421 #[inline]
422 #[must_use]
423 pub fn fixed_offset(&self) -> DateTime<FixedOffset> {
424 self.with_timezone(&self.offset().fix())
425 }
426
427 /// Turn this `DateTime` into a `DateTime<Utc>`, dropping the offset and associated timezone
428 /// information.
429 #[inline]
430 #[must_use]
431 pub const fn to_utc(&self) -> DateTime<Utc> {
432 DateTime { datetime: self.datetime, offset: Utc }
433 }
434
435 /// Adds given `TimeDelta` to the current date and time.
436 ///
437 /// # Errors
438 ///
439 /// Returns `None` if the resulting date would be out of range.
440 #[inline]
441 #[must_use]
442 pub fn checked_add_signed(self, rhs: TimeDelta) -> Option<DateTime<Tz>> {
443 let datetime = self.datetime.checked_add_signed(rhs)?;
444 let tz = self.timezone();
445 Some(tz.from_utc_datetime(&datetime))
446 }
447
448 /// Adds given `Months` to the current date and time.
449 ///
450 /// Uses the last day of the month if the day does not exist in the resulting month.
451 ///
452 /// See [`NaiveDate::checked_add_months`] for more details on behavior.
453 ///
454 /// # Errors
455 ///
456 /// Returns `None` if:
457 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
458 /// daylight saving time transition.
459 /// - The resulting UTC datetime would be out of range.
460 /// - The resulting local datetime would be out of range (unless `months` is zero).
461 #[must_use]
462 pub fn checked_add_months(self, months: Months) -> Option<DateTime<Tz>> {
463 // `NaiveDate::checked_add_months` has a fast path for `Months(0)` that does not validate
464 // the resulting date, with which we can return `Some` even for an out of range local
465 // datetime.
466 self.overflowing_naive_local()
467 .checked_add_months(months)?
468 .and_local_timezone(Tz::from_offset(&self.offset))
469 .single()
470 }
471
472 /// Subtracts given `TimeDelta` from the current date and time.
473 ///
474 /// # Errors
475 ///
476 /// Returns `None` if the resulting date would be out of range.
477 #[inline]
478 #[must_use]
479 pub fn checked_sub_signed(self, rhs: TimeDelta) -> Option<DateTime<Tz>> {
480 let datetime = self.datetime.checked_sub_signed(rhs)?;
481 let tz = self.timezone();
482 Some(tz.from_utc_datetime(&datetime))
483 }
484
485 /// Subtracts given `Months` from the current date and time.
486 ///
487 /// Uses the last day of the month if the day does not exist in the resulting month.
488 ///
489 /// See [`NaiveDate::checked_sub_months`] for more details on behavior.
490 ///
491 /// # Errors
492 ///
493 /// Returns `None` if:
494 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
495 /// daylight saving time transition.
496 /// - The resulting UTC datetime would be out of range.
497 /// - The resulting local datetime would be out of range (unless `months` is zero).
498 #[must_use]
499 pub fn checked_sub_months(self, months: Months) -> Option<DateTime<Tz>> {
500 // `NaiveDate::checked_sub_months` has a fast path for `Months(0)` that does not validate
501 // the resulting date, with which we can return `Some` even for an out of range local
502 // datetime.
503 self.overflowing_naive_local()
504 .checked_sub_months(months)?
505 .and_local_timezone(Tz::from_offset(&self.offset))
506 .single()
507 }
508
509 /// Add a duration in [`Days`] to the date part of the `DateTime`.
510 ///
511 /// # Errors
512 ///
513 /// Returns `None` if:
514 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
515 /// daylight saving time transition.
516 /// - The resulting UTC datetime would be out of range.
517 /// - The resulting local datetime would be out of range (unless `days` is zero).
518 #[must_use]
519 pub fn checked_add_days(self, days: Days) -> Option<Self> {
520 if days == Days::new(0) {
521 return Some(self);
522 }
523 // `NaiveDate::add_days` has a fast path if the result remains within the same year, that
524 // does not validate the resulting date. This allows us to return `Some` even for an out of
525 // range local datetime when adding `Days(0)`.
526 self.overflowing_naive_local()
527 .checked_add_days(days)
528 .and_then(|dt| self.timezone().from_local_datetime(&dt).single())
529 .filter(|dt| dt <= &DateTime::<Utc>::MAX_UTC)
530 }
531
532 /// Subtract a duration in [`Days`] from the date part of the `DateTime`.
533 ///
534 /// # Errors
535 ///
536 /// Returns `None` if:
537 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
538 /// daylight saving time transition.
539 /// - The resulting UTC datetime would be out of range.
540 /// - The resulting local datetime would be out of range (unless `days` is zero).
541 #[must_use]
542 pub fn checked_sub_days(self, days: Days) -> Option<Self> {
543 // `NaiveDate::add_days` has a fast path if the result remains within the same year, that
544 // does not validate the resulting date. This allows us to return `Some` even for an out of
545 // range local datetime when adding `Days(0)`.
546 self.overflowing_naive_local()
547 .checked_sub_days(days)
548 .and_then(|dt| self.timezone().from_local_datetime(&dt).single())
549 .filter(|dt| dt >= &DateTime::<Utc>::MIN_UTC)
550 }
551
552 /// Subtracts another `DateTime` from the current date and time.
553 /// This does not overflow or underflow at all.
554 #[inline]
555 #[must_use]
556 pub fn signed_duration_since<Tz2: TimeZone>(
557 self,
558 rhs: impl Borrow<DateTime<Tz2>>,
559 ) -> TimeDelta {
560 self.datetime.signed_duration_since(rhs.borrow().datetime)
561 }
562
563 /// Returns a view to the naive UTC datetime.
564 #[inline]
565 #[must_use]
566 pub const fn naive_utc(&self) -> NaiveDateTime {
567 self.datetime
568 }
569
570 /// Returns a view to the naive local datetime.
571 ///
572 /// # Panics
573 ///
574 /// [`DateTime`] internally stores the date and time in UTC with a [`NaiveDateTime`]. This
575 /// method will panic if the offset from UTC would push the local datetime outside of the
576 /// representable range of a [`NaiveDateTime`].
577 #[inline]
578 #[must_use]
579 pub fn naive_local(&self) -> NaiveDateTime {
580 self.datetime
581 .checked_add_offset(self.offset.fix())
582 .expect("Local time out of range for `NaiveDateTime`")
583 }
584
585 /// Returns the naive local datetime.
586 ///
587 /// This makes use of the buffer space outside of the representable range of values of
588 /// `NaiveDateTime`. The result can be used as intermediate value, but should never be exposed
589 /// outside chrono.
590 #[inline]
591 #[must_use]
592 pub(crate) fn overflowing_naive_local(&self) -> NaiveDateTime {
593 self.datetime.overflowing_add_offset(self.offset.fix())
594 }
595
596 /// Retrieve the elapsed years from now to the given [`DateTime`].
597 ///
598 /// # Errors
599 ///
600 /// Returns `None` if `base < self`.
601 #[must_use]
602 pub fn years_since(&self, base: Self) -> Option<u32> {
603 let mut years = self.year() - base.year();
604 let earlier_time =
605 (self.month(), self.day(), self.time()) < (base.month(), base.day(), base.time());
606
607 years -= match earlier_time {
608 true => 1,
609 false => 0,
610 };
611
612 match years >= 0 {
613 true => Some(years as u32),
614 false => None,
615 }
616 }
617
618 /// Returns an RFC 2822 date and time string such as `Tue, 1 Jul 2003 10:52:37 +0200`.
619 ///
620 /// # Panics
621 ///
622 /// Panics if the date can not be represented in this format: the year may not be negative and
623 /// can not have more than 4 digits.
624 #[cfg(feature = "alloc")]
625 #[must_use]
626 pub fn to_rfc2822(&self) -> String {
627 let mut result = String::with_capacity(32);
628 write_rfc2822(&mut result, self.overflowing_naive_local(), self.offset.fix())
629 .expect("writing rfc2822 datetime to string should never fail");
630 result
631 }
632
633 /// Returns an RFC 3339 and ISO 8601 date and time string such as `1996-12-19T16:39:57-08:00`.
634 #[cfg(feature = "alloc")]
635 #[must_use]
636 pub fn to_rfc3339(&self) -> String {
637 // For some reason a string with a capacity less than 32 is ca 20% slower when benchmarking.
638 let mut result = String::with_capacity(32);
639 let naive = self.overflowing_naive_local();
640 let offset = self.offset.fix();
641 write_rfc3339(&mut result, naive, offset, SecondsFormat::AutoSi, false)
642 .expect("writing rfc3339 datetime to string should never fail");
643 result
644 }
645
646 /// Return an RFC 3339 and ISO 8601 date and time string with subseconds
647 /// formatted as per `SecondsFormat`.
648 ///
649 /// If `use_z` is true and the timezone is UTC (offset 0), uses `Z` as
650 /// per [`Fixed::TimezoneOffsetColonZ`]. If `use_z` is false, uses
651 /// [`Fixed::TimezoneOffsetColon`]
652 ///
653 /// # Examples
654 ///
655 /// ```rust
656 /// # use chrono::{FixedOffset, SecondsFormat, TimeZone, Utc, NaiveDate};
657 /// let dt = NaiveDate::from_ymd_opt(2018, 1, 26)
658 /// .unwrap()
659 /// .and_hms_micro_opt(18, 30, 9, 453_829)
660 /// .unwrap()
661 /// .and_local_timezone(Utc)
662 /// .unwrap();
663 /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Millis, false), "2018-01-26T18:30:09.453+00:00");
664 /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Millis, true), "2018-01-26T18:30:09.453Z");
665 /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Secs, true), "2018-01-26T18:30:09Z");
666 ///
667 /// let pst = FixedOffset::east_opt(8 * 60 * 60).unwrap();
668 /// let dt = pst
669 /// .from_local_datetime(
670 /// &NaiveDate::from_ymd_opt(2018, 1, 26)
671 /// .unwrap()
672 /// .and_hms_micro_opt(10, 30, 9, 453_829)
673 /// .unwrap(),
674 /// )
675 /// .unwrap();
676 /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Secs, true), "2018-01-26T10:30:09+08:00");
677 /// ```
678 #[cfg(feature = "alloc")]
679 #[must_use]
680 pub fn to_rfc3339_opts(&self, secform: SecondsFormat, use_z: bool) -> String {
681 let mut result = String::with_capacity(38);
682 write_rfc3339(&mut result, self.naive_local(), self.offset.fix(), secform, use_z)
683 .expect("writing rfc3339 datetime to string should never fail");
684 result
685 }
686
687 /// The minimum possible `DateTime<Utc>`.
688 pub const MIN_UTC: DateTime<Utc> = DateTime { datetime: NaiveDateTime::MIN, offset: Utc };
689 /// The maximum possible `DateTime<Utc>`.
690 pub const MAX_UTC: DateTime<Utc> = DateTime { datetime: NaiveDateTime::MAX, offset: Utc };
691}
692
693impl DateTime<Utc> {
694 /// Makes a new `DateTime<Utc>` from the number of non-leap seconds
695 /// since January 1, 1970 0:00:00 UTC (aka "UNIX timestamp")
696 /// and the number of nanoseconds since the last whole non-leap second.
697 ///
698 /// This is guaranteed to round-trip with regard to [`timestamp`](DateTime::timestamp) and
699 /// [`timestamp_subsec_nanos`](DateTime::timestamp_subsec_nanos).
700 ///
701 /// If you need to create a `DateTime` with a [`TimeZone`] different from [`Utc`], use
702 /// [`TimeZone::timestamp_opt`] or [`DateTime::with_timezone`].
703 ///
704 /// The nanosecond part can exceed 1,000,000,000 in order to represent a
705 /// [leap second](NaiveTime#leap-second-handling), but only when `secs % 60 == 59`.
706 /// (The true "UNIX timestamp" cannot represent a leap second unambiguously.)
707 ///
708 /// # Errors
709 ///
710 /// Returns `None` on out-of-range number of seconds and/or
711 /// invalid nanosecond, otherwise returns `Some(DateTime {...})`.
712 ///
713 /// # Example
714 ///
715 /// ```
716 /// use chrono::DateTime;
717 ///
718 /// let dt = DateTime::from_timestamp(1431648000, 0).expect("invalid timestamp");
719 ///
720 /// assert_eq!(dt.to_string(), "2015-05-15 00:00:00 UTC");
721 /// assert_eq!(DateTime::from_timestamp(dt.timestamp(), dt.timestamp_subsec_nanos()).unwrap(), dt);
722 /// ```
723 #[inline]
724 #[must_use]
725 pub const fn from_timestamp(secs: i64, nsecs: u32) -> Option<Self> {
726 let days = secs.div_euclid(86_400) + UNIX_EPOCH_DAY;
727 let secs = secs.rem_euclid(86_400);
728 if days < i32::MIN as i64 || days > i32::MAX as i64 {
729 return None;
730 }
731 let date = try_opt!(NaiveDate::from_num_days_from_ce_opt(days as i32));
732 let time = try_opt!(NaiveTime::from_num_seconds_from_midnight_opt(secs as u32, nsecs));
733 Some(date.and_time(time).and_utc())
734 }
735
736 /// Makes a new `DateTime<Utc>` from the number of non-leap milliseconds
737 /// since January 1, 1970 0:00:00.000 UTC (aka "UNIX timestamp").
738 ///
739 /// This is guaranteed to round-trip with [`timestamp_millis`](DateTime::timestamp_millis).
740 ///
741 /// If you need to create a `DateTime` with a [`TimeZone`] different from [`Utc`], use
742 /// [`TimeZone::timestamp_millis_opt`] or [`DateTime::with_timezone`].
743 ///
744 /// # Errors
745 ///
746 /// Returns `None` on out-of-range number of milliseconds, otherwise returns `Some(DateTime {...})`.
747 ///
748 /// # Example
749 ///
750 /// ```
751 /// use chrono::DateTime;
752 ///
753 /// let dt = DateTime::from_timestamp_millis(947638923004).expect("invalid timestamp");
754 ///
755 /// assert_eq!(dt.to_string(), "2000-01-12 01:02:03.004 UTC");
756 /// assert_eq!(DateTime::from_timestamp_millis(dt.timestamp_millis()).unwrap(), dt);
757 /// ```
758 #[inline]
759 #[must_use]
760 pub const fn from_timestamp_millis(millis: i64) -> Option<Self> {
761 let secs = millis.div_euclid(1000);
762 let nsecs = millis.rem_euclid(1000) as u32 * 1_000_000;
763 Self::from_timestamp(secs, nsecs)
764 }
765
766 /// Creates a new `DateTime<Utc>` from the number of non-leap microseconds
767 /// since January 1, 1970 0:00:00.000 UTC (aka "UNIX timestamp").
768 ///
769 /// This is guaranteed to round-trip with [`timestamp_micros`](DateTime::timestamp_micros).
770 ///
771 /// If you need to create a `DateTime` with a [`TimeZone`] different from [`Utc`], use
772 /// [`TimeZone::timestamp_micros`] or [`DateTime::with_timezone`].
773 ///
774 /// # Errors
775 ///
776 /// Returns `None` if the number of microseconds would be out of range for a `NaiveDateTime`
777 /// (more than ca. 262,000 years away from common era)
778 ///
779 /// # Example
780 ///
781 /// ```
782 /// use chrono::DateTime;
783 ///
784 /// let timestamp_micros: i64 = 1662921288000000; // Sun, 11 Sep 2022 18:34:48 UTC
785 /// let dt = DateTime::from_timestamp_micros(timestamp_micros);
786 /// assert!(dt.is_some());
787 /// assert_eq!(timestamp_micros, dt.expect("invalid timestamp").timestamp_micros());
788 ///
789 /// // Negative timestamps (before the UNIX epoch) are supported as well.
790 /// let timestamp_micros: i64 = -2208936075000000; // Mon, 1 Jan 1900 14:38:45 UTC
791 /// let dt = DateTime::from_timestamp_micros(timestamp_micros);
792 /// assert!(dt.is_some());
793 /// assert_eq!(timestamp_micros, dt.expect("invalid timestamp").timestamp_micros());
794 /// ```
795 #[inline]
796 #[must_use]
797 pub const fn from_timestamp_micros(micros: i64) -> Option<Self> {
798 let secs = micros.div_euclid(1_000_000);
799 let nsecs = micros.rem_euclid(1_000_000) as u32 * 1000;
800 Self::from_timestamp(secs, nsecs)
801 }
802
803 /// Creates a new [`DateTime<Utc>`] from the number of non-leap microseconds
804 /// since January 1, 1970 0:00:00.000 UTC (aka "UNIX timestamp").
805 ///
806 /// This is guaranteed to round-trip with [`timestamp_nanos`](DateTime::timestamp_nanos).
807 ///
808 /// If you need to create a `DateTime` with a [`TimeZone`] different from [`Utc`], use
809 /// [`TimeZone::timestamp_nanos`] or [`DateTime::with_timezone`].
810 ///
811 /// The UNIX epoch starts on midnight, January 1, 1970, UTC.
812 ///
813 /// An `i64` with nanosecond precision can span a range of ~584 years. Because all values can
814 /// be represented as a `DateTime` this method never fails.
815 ///
816 /// # Example
817 ///
818 /// ```
819 /// use chrono::DateTime;
820 ///
821 /// let timestamp_nanos: i64 = 1662921288_000_000_000; // Sun, 11 Sep 2022 18:34:48 UTC
822 /// let dt = DateTime::from_timestamp_nanos(timestamp_nanos);
823 /// assert_eq!(timestamp_nanos, dt.timestamp_nanos_opt().unwrap());
824 ///
825 /// // Negative timestamps (before the UNIX epoch) are supported as well.
826 /// let timestamp_nanos: i64 = -2208936075_000_000_000; // Mon, 1 Jan 1900 14:38:45 UTC
827 /// let dt = DateTime::from_timestamp_nanos(timestamp_nanos);
828 /// assert_eq!(timestamp_nanos, dt.timestamp_nanos_opt().unwrap());
829 /// ```
830 #[inline]
831 #[must_use]
832 pub const fn from_timestamp_nanos(nanos: i64) -> Self {
833 let secs = nanos.div_euclid(1_000_000_000);
834 let nsecs = nanos.rem_euclid(1_000_000_000) as u32;
835 expect!(Self::from_timestamp(secs, nsecs), "timestamp in nanos is always in range")
836 }
837
838 /// The Unix Epoch, 1970-01-01 00:00:00 UTC.
839 pub const UNIX_EPOCH: Self = Self { datetime: NaiveDateTime::UNIX_EPOCH, offset: Utc };
840}
841
842impl Default for DateTime<Utc> {
843 fn default() -> Self {
844 Utc.from_utc_datetime(&NaiveDateTime::default())
845 }
846}
847
848#[cfg(feature = "clock")]
849impl Default for DateTime<Local> {
850 fn default() -> Self {
851 Local.from_utc_datetime(&NaiveDateTime::default())
852 }
853}
854
855impl Default for DateTime<FixedOffset> {
856 fn default() -> Self {
857 FixedOffset::west_opt(0).unwrap().from_utc_datetime(&NaiveDateTime::default())
858 }
859}
860
861/// Convert a `DateTime<Utc>` instance into a `DateTime<FixedOffset>` instance.
862impl From<DateTime<Utc>> for DateTime<FixedOffset> {
863 /// Convert this `DateTime<Utc>` instance into a `DateTime<FixedOffset>` instance.
864 ///
865 /// Conversion is done via [`DateTime::with_timezone`]. Note that the converted value returned by
866 /// this will be created with a fixed timezone offset of 0.
867 fn from(src: DateTime<Utc>) -> Self {
868 src.with_timezone(&FixedOffset::east_opt(secs:0).unwrap())
869 }
870}
871
872/// Convert a `DateTime<Utc>` instance into a `DateTime<Local>` instance.
873#[cfg(feature = "clock")]
874impl From<DateTime<Utc>> for DateTime<Local> {
875 /// Convert this `DateTime<Utc>` instance into a `DateTime<Local>` instance.
876 ///
877 /// Conversion is performed via [`DateTime::with_timezone`], accounting for the difference in timezones.
878 fn from(src: DateTime<Utc>) -> Self {
879 src.with_timezone(&Local)
880 }
881}
882
883/// Convert a `DateTime<FixedOffset>` instance into a `DateTime<Utc>` instance.
884impl From<DateTime<FixedOffset>> for DateTime<Utc> {
885 /// Convert this `DateTime<FixedOffset>` instance into a `DateTime<Utc>` instance.
886 ///
887 /// Conversion is performed via [`DateTime::with_timezone`], accounting for the timezone
888 /// difference.
889 fn from(src: DateTime<FixedOffset>) -> Self {
890 src.with_timezone(&Utc)
891 }
892}
893
894/// Convert a `DateTime<FixedOffset>` instance into a `DateTime<Local>` instance.
895#[cfg(feature = "clock")]
896impl From<DateTime<FixedOffset>> for DateTime<Local> {
897 /// Convert this `DateTime<FixedOffset>` instance into a `DateTime<Local>` instance.
898 ///
899 /// Conversion is performed via [`DateTime::with_timezone`]. Returns the equivalent value in local
900 /// time.
901 fn from(src: DateTime<FixedOffset>) -> Self {
902 src.with_timezone(&Local)
903 }
904}
905
906/// Convert a `DateTime<Local>` instance into a `DateTime<Utc>` instance.
907#[cfg(feature = "clock")]
908impl From<DateTime<Local>> for DateTime<Utc> {
909 /// Convert this `DateTime<Local>` instance into a `DateTime<Utc>` instance.
910 ///
911 /// Conversion is performed via [`DateTime::with_timezone`], accounting for the difference in
912 /// timezones.
913 fn from(src: DateTime<Local>) -> Self {
914 src.with_timezone(&Utc)
915 }
916}
917
918/// Convert a `DateTime<Local>` instance into a `DateTime<FixedOffset>` instance.
919#[cfg(feature = "clock")]
920impl From<DateTime<Local>> for DateTime<FixedOffset> {
921 /// Convert this `DateTime<Local>` instance into a `DateTime<FixedOffset>` instance.
922 ///
923 /// Conversion is performed via [`DateTime::with_timezone`].
924 fn from(src: DateTime<Local>) -> Self {
925 src.with_timezone(&src.offset().fix())
926 }
927}
928
929/// Maps the local datetime to other datetime with given conversion function.
930fn map_local<Tz: TimeZone, F>(dt: &DateTime<Tz>, mut f: F) -> Option<DateTime<Tz>>
931where
932 F: FnMut(NaiveDateTime) -> Option<NaiveDateTime>,
933{
934 fOption>(dt.overflowing_naive_local())
935 .and_then(|datetime: NaiveDateTime| dt.timezone().from_local_datetime(&datetime).single())
936 .filter(|dt: &DateTime| dt >= &DateTime::<Utc>::MIN_UTC && dt <= &DateTime::<Utc>::MAX_UTC)
937}
938
939impl DateTime<FixedOffset> {
940 /// Parses an RFC 2822 date-and-time string into a `DateTime<FixedOffset>` value.
941 ///
942 /// This parses valid RFC 2822 datetime strings (such as `Tue, 1 Jul 2003 10:52:37 +0200`)
943 /// and returns a new [`DateTime`] instance with the parsed timezone as the [`FixedOffset`].
944 ///
945 /// RFC 2822 is the internet message standard that specifies the representation of times in HTTP
946 /// and email headers. It is the 2001 revision of RFC 822, and is itself revised as RFC 5322 in
947 /// 2008.
948 ///
949 /// # Support for the obsolete date format
950 ///
951 /// - A 2-digit year is interpreted to be a year in 1950-2049.
952 /// - The standard allows comments and whitespace between many of the tokens. See [4.3] and
953 /// [Appendix A.5]
954 /// - Single letter 'military' time zone names are parsed as a `-0000` offset.
955 /// They were defined with the wrong sign in RFC 822 and corrected in RFC 2822. But because
956 /// the meaning is now ambiguous, the standard says they should be be considered as `-0000`
957 /// unless there is out-of-band information confirming their meaning.
958 /// The exception is `Z`, which remains identical to `+0000`.
959 ///
960 /// [4.3]: https://www.rfc-editor.org/rfc/rfc2822#section-4.3
961 /// [Appendix A.5]: https://www.rfc-editor.org/rfc/rfc2822#appendix-A.5
962 ///
963 /// # Example
964 ///
965 /// ```
966 /// # use chrono::{DateTime, FixedOffset, TimeZone};
967 /// assert_eq!(
968 /// DateTime::parse_from_rfc2822("Wed, 18 Feb 2015 23:16:09 GMT").unwrap(),
969 /// FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(2015, 2, 18, 23, 16, 9).unwrap()
970 /// );
971 /// ```
972 pub fn parse_from_rfc2822(s: &str) -> ParseResult<DateTime<FixedOffset>> {
973 const ITEMS: &[Item<'static>] = &[Item::Fixed(Fixed::RFC2822)];
974 let mut parsed = Parsed::new();
975 parse(&mut parsed, s, ITEMS.iter())?;
976 parsed.to_datetime()
977 }
978
979 /// Parses an RFC 3339 date-and-time string into a `DateTime<FixedOffset>` value.
980 ///
981 /// Parses all valid RFC 3339 values (as well as the subset of valid ISO 8601 values that are
982 /// also valid RFC 3339 date-and-time values) and returns a new [`DateTime`] with a
983 /// [`FixedOffset`] corresponding to the parsed timezone. While RFC 3339 values come in a wide
984 /// variety of shapes and sizes, `1996-12-19T16:39:57-08:00` is an example of the most commonly
985 /// encountered variety of RFC 3339 formats.
986 ///
987 /// Why isn't this named `parse_from_iso8601`? That's because ISO 8601 allows representing
988 /// values in a wide range of formats, only some of which represent actual date-and-time
989 /// instances (rather than periods, ranges, dates, or times). Some valid ISO 8601 values are
990 /// also simultaneously valid RFC 3339 values, but not all RFC 3339 values are valid ISO 8601
991 /// values (or the other way around).
992 pub fn parse_from_rfc3339(s: &str) -> ParseResult<DateTime<FixedOffset>> {
993 let mut parsed = Parsed::new();
994 let (s, _) = parse_rfc3339(&mut parsed, s)?;
995 if !s.is_empty() {
996 return Err(TOO_LONG);
997 }
998 parsed.to_datetime()
999 }
1000
1001 /// Parses a string from a user-specified format into a `DateTime<FixedOffset>` value.
1002 ///
1003 /// Note that this method *requires a timezone* in the input string. See
1004 /// [`NaiveDateTime::parse_from_str`](./naive/struct.NaiveDateTime.html#method.parse_from_str)
1005 /// for a version that does not require a timezone in the to-be-parsed str. The returned
1006 /// [`DateTime`] value will have a [`FixedOffset`] reflecting the parsed timezone.
1007 ///
1008 /// See the [`format::strftime` module](./format/strftime/index.html) for supported format
1009 /// sequences.
1010 ///
1011 /// # Example
1012 ///
1013 /// ```rust
1014 /// use chrono::{DateTime, FixedOffset, NaiveDate, TimeZone};
1015 ///
1016 /// let dt = DateTime::parse_from_str("1983 Apr 13 12:09:14.274 +0000", "%Y %b %d %H:%M:%S%.3f %z");
1017 /// assert_eq!(
1018 /// dt,
1019 /// Ok(FixedOffset::east_opt(0)
1020 /// .unwrap()
1021 /// .from_local_datetime(
1022 /// &NaiveDate::from_ymd_opt(1983, 4, 13)
1023 /// .unwrap()
1024 /// .and_hms_milli_opt(12, 9, 14, 274)
1025 /// .unwrap()
1026 /// )
1027 /// .unwrap())
1028 /// );
1029 /// ```
1030 pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<DateTime<FixedOffset>> {
1031 let mut parsed = Parsed::new();
1032 parse(&mut parsed, s, StrftimeItems::new(fmt))?;
1033 parsed.to_datetime()
1034 }
1035
1036 /// Parses a string from a user-specified format into a `DateTime<FixedOffset>` value, and a
1037 /// slice with the remaining portion of the string.
1038 ///
1039 /// Note that this method *requires a timezone* in the input string. See
1040 /// [`NaiveDateTime::parse_and_remainder`] for a version that does not
1041 /// require a timezone in `s`. The returned [`DateTime`] value will have a [`FixedOffset`]
1042 /// reflecting the parsed timezone.
1043 ///
1044 /// See the [`format::strftime` module](./format/strftime/index.html) for supported format
1045 /// sequences.
1046 ///
1047 /// Similar to [`parse_from_str`](#method.parse_from_str).
1048 ///
1049 /// # Example
1050 ///
1051 /// ```rust
1052 /// # use chrono::{DateTime, FixedOffset, TimeZone};
1053 /// let (datetime, remainder) = DateTime::parse_and_remainder(
1054 /// "2015-02-18 23:16:09 +0200 trailing text",
1055 /// "%Y-%m-%d %H:%M:%S %z",
1056 /// )
1057 /// .unwrap();
1058 /// assert_eq!(
1059 /// datetime,
1060 /// FixedOffset::east_opt(2 * 3600).unwrap().with_ymd_and_hms(2015, 2, 18, 23, 16, 9).unwrap()
1061 /// );
1062 /// assert_eq!(remainder, " trailing text");
1063 /// ```
1064 pub fn parse_and_remainder<'a>(
1065 s: &'a str,
1066 fmt: &str,
1067 ) -> ParseResult<(DateTime<FixedOffset>, &'a str)> {
1068 let mut parsed = Parsed::new();
1069 let remainder = parse_and_remainder(&mut parsed, s, StrftimeItems::new(fmt))?;
1070 parsed.to_datetime().map(|d| (d, remainder))
1071 }
1072}
1073
1074impl<Tz: TimeZone> DateTime<Tz>
1075where
1076 Tz::Offset: fmt::Display,
1077{
1078 /// Formats the combined date and time with the specified formatting items.
1079 #[cfg(feature = "alloc")]
1080 #[inline]
1081 #[must_use]
1082 pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
1083 where
1084 I: Iterator<Item = B> + Clone,
1085 B: Borrow<Item<'a>>,
1086 {
1087 let local = self.overflowing_naive_local();
1088 DelayedFormat::new_with_offset(Some(local.date()), Some(local.time()), &self.offset, items)
1089 }
1090
1091 /// Formats the combined date and time per the specified format string.
1092 ///
1093 /// See the [`crate::format::strftime`] module for the supported escape sequences.
1094 ///
1095 /// # Example
1096 /// ```rust
1097 /// use chrono::prelude::*;
1098 ///
1099 /// let date_time: DateTime<Utc> = Utc.with_ymd_and_hms(2017, 04, 02, 12, 50, 32).unwrap();
1100 /// let formatted = format!("{}", date_time.format("%d/%m/%Y %H:%M"));
1101 /// assert_eq!(formatted, "02/04/2017 12:50");
1102 /// ```
1103 #[cfg(feature = "alloc")]
1104 #[inline]
1105 #[must_use]
1106 pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
1107 self.format_with_items(StrftimeItems::new(fmt))
1108 }
1109
1110 /// Formats the combined date and time with the specified formatting items and locale.
1111 #[cfg(all(feature = "unstable-locales", feature = "alloc"))]
1112 #[inline]
1113 #[must_use]
1114 pub fn format_localized_with_items<'a, I, B>(
1115 &self,
1116 items: I,
1117 locale: Locale,
1118 ) -> DelayedFormat<I>
1119 where
1120 I: Iterator<Item = B> + Clone,
1121 B: Borrow<Item<'a>>,
1122 {
1123 let local = self.overflowing_naive_local();
1124 DelayedFormat::new_with_offset_and_locale(
1125 Some(local.date()),
1126 Some(local.time()),
1127 &self.offset,
1128 items,
1129 locale,
1130 )
1131 }
1132
1133 /// Formats the combined date and time per the specified format string and
1134 /// locale.
1135 ///
1136 /// See the [`crate::format::strftime`] module on the supported escape
1137 /// sequences.
1138 #[cfg(all(feature = "unstable-locales", feature = "alloc"))]
1139 #[inline]
1140 #[must_use]
1141 pub fn format_localized<'a>(
1142 &self,
1143 fmt: &'a str,
1144 locale: Locale,
1145 ) -> DelayedFormat<StrftimeItems<'a>> {
1146 self.format_localized_with_items(StrftimeItems::new_with_locale(fmt, locale), locale)
1147 }
1148}
1149
1150impl<Tz: TimeZone> Datelike for DateTime<Tz> {
1151 #[inline]
1152 fn year(&self) -> i32 {
1153 self.overflowing_naive_local().year()
1154 }
1155 #[inline]
1156 fn month(&self) -> u32 {
1157 self.overflowing_naive_local().month()
1158 }
1159 #[inline]
1160 fn month0(&self) -> u32 {
1161 self.overflowing_naive_local().month0()
1162 }
1163 #[inline]
1164 fn day(&self) -> u32 {
1165 self.overflowing_naive_local().day()
1166 }
1167 #[inline]
1168 fn day0(&self) -> u32 {
1169 self.overflowing_naive_local().day0()
1170 }
1171 #[inline]
1172 fn ordinal(&self) -> u32 {
1173 self.overflowing_naive_local().ordinal()
1174 }
1175 #[inline]
1176 fn ordinal0(&self) -> u32 {
1177 self.overflowing_naive_local().ordinal0()
1178 }
1179 #[inline]
1180 fn weekday(&self) -> Weekday {
1181 self.overflowing_naive_local().weekday()
1182 }
1183 #[inline]
1184 fn iso_week(&self) -> IsoWeek {
1185 self.overflowing_naive_local().iso_week()
1186 }
1187
1188 #[inline]
1189 /// Makes a new `DateTime` with the year number changed, while keeping the same month and day.
1190 ///
1191 /// See also the [`NaiveDate::with_year`] method.
1192 ///
1193 /// # Errors
1194 ///
1195 /// Returns `None` if:
1196 /// - The resulting date does not exist (February 29 in a non-leap year).
1197 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1198 /// daylight saving time transition.
1199 /// - The resulting UTC datetime would be out of range.
1200 /// - The resulting local datetime would be out of range (unless the year remains the same).
1201 fn with_year(&self, year: i32) -> Option<DateTime<Tz>> {
1202 map_local(self, |dt| match dt.year() == year {
1203 true => Some(dt),
1204 false => dt.with_year(year),
1205 })
1206 }
1207
1208 /// Makes a new `DateTime` with the month number (starting from 1) changed.
1209 ///
1210 /// Don't combine multiple `Datelike::with_*` methods. The intermediate value may not exist.
1211 ///
1212 /// See also the [`NaiveDate::with_month`] method.
1213 ///
1214 /// # Errors
1215 ///
1216 /// Returns `None` if:
1217 /// - The resulting date does not exist (for example `month(4)` when day of the month is 31).
1218 /// - The value for `month` is invalid.
1219 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1220 /// daylight saving time transition.
1221 #[inline]
1222 fn with_month(&self, month: u32) -> Option<DateTime<Tz>> {
1223 map_local(self, |datetime| datetime.with_month(month))
1224 }
1225
1226 /// Makes a new `DateTime` with the month number (starting from 0) changed.
1227 ///
1228 /// See also the [`NaiveDate::with_month0`] method.
1229 ///
1230 /// # Errors
1231 ///
1232 /// Returns `None` if:
1233 /// - The resulting date does not exist (for example `month0(3)` when day of the month is 31).
1234 /// - The value for `month0` is invalid.
1235 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1236 /// daylight saving time transition.
1237 #[inline]
1238 fn with_month0(&self, month0: u32) -> Option<DateTime<Tz>> {
1239 map_local(self, |datetime| datetime.with_month0(month0))
1240 }
1241
1242 /// Makes a new `DateTime` with the day of month (starting from 1) changed.
1243 ///
1244 /// See also the [`NaiveDate::with_day`] method.
1245 ///
1246 /// # Errors
1247 ///
1248 /// Returns `None` if:
1249 /// - The resulting date does not exist (for example `day(31)` in April).
1250 /// - The value for `day` is invalid.
1251 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1252 /// daylight saving time transition.
1253 #[inline]
1254 fn with_day(&self, day: u32) -> Option<DateTime<Tz>> {
1255 map_local(self, |datetime| datetime.with_day(day))
1256 }
1257
1258 /// Makes a new `DateTime` with the day of month (starting from 0) changed.
1259 ///
1260 /// See also the [`NaiveDate::with_day0`] method.
1261 ///
1262 /// # Errors
1263 ///
1264 /// Returns `None` if:
1265 /// - The resulting date does not exist (for example `day(30)` in April).
1266 /// - The value for `day0` is invalid.
1267 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1268 /// daylight saving time transition.
1269 #[inline]
1270 fn with_day0(&self, day0: u32) -> Option<DateTime<Tz>> {
1271 map_local(self, |datetime| datetime.with_day0(day0))
1272 }
1273
1274 /// Makes a new `DateTime` with the day of year (starting from 1) changed.
1275 ///
1276 /// See also the [`NaiveDate::with_ordinal`] method.
1277 ///
1278 /// # Errors
1279 ///
1280 /// Returns `None` if:
1281 /// - The resulting date does not exist (`with_ordinal(366)` in a non-leap year).
1282 /// - The value for `ordinal` is invalid.
1283 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1284 /// daylight saving time transition.
1285 #[inline]
1286 fn with_ordinal(&self, ordinal: u32) -> Option<DateTime<Tz>> {
1287 map_local(self, |datetime| datetime.with_ordinal(ordinal))
1288 }
1289
1290 /// Makes a new `DateTime` with the day of year (starting from 0) changed.
1291 ///
1292 /// See also the [`NaiveDate::with_ordinal0`] method.
1293 ///
1294 /// # Errors
1295 ///
1296 /// Returns `None` if:
1297 /// - The resulting date does not exist (`with_ordinal0(365)` in a non-leap year).
1298 /// - The value for `ordinal0` is invalid.
1299 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1300 /// daylight saving time transition.
1301 #[inline]
1302 fn with_ordinal0(&self, ordinal0: u32) -> Option<DateTime<Tz>> {
1303 map_local(self, |datetime| datetime.with_ordinal0(ordinal0))
1304 }
1305}
1306
1307impl<Tz: TimeZone> Timelike for DateTime<Tz> {
1308 #[inline]
1309 fn hour(&self) -> u32 {
1310 self.overflowing_naive_local().hour()
1311 }
1312 #[inline]
1313 fn minute(&self) -> u32 {
1314 self.overflowing_naive_local().minute()
1315 }
1316 #[inline]
1317 fn second(&self) -> u32 {
1318 self.overflowing_naive_local().second()
1319 }
1320 #[inline]
1321 fn nanosecond(&self) -> u32 {
1322 self.overflowing_naive_local().nanosecond()
1323 }
1324
1325 /// Makes a new `DateTime` with the hour number changed.
1326 ///
1327 /// See also the [`NaiveTime::with_hour`] method.
1328 ///
1329 /// # Errors
1330 ///
1331 /// Returns `None` if:
1332 /// - The value for `hour` is invalid.
1333 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1334 /// daylight saving time transition.
1335 #[inline]
1336 fn with_hour(&self, hour: u32) -> Option<DateTime<Tz>> {
1337 map_local(self, |datetime| datetime.with_hour(hour))
1338 }
1339
1340 /// Makes a new `DateTime` with the minute number changed.
1341 ///
1342 /// See also the [`NaiveTime::with_minute`] method.
1343 ///
1344 /// # Errors
1345 ///
1346 /// - The value for `minute` is invalid.
1347 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1348 /// daylight saving time transition.
1349 #[inline]
1350 fn with_minute(&self, min: u32) -> Option<DateTime<Tz>> {
1351 map_local(self, |datetime| datetime.with_minute(min))
1352 }
1353
1354 /// Makes a new `DateTime` with the second number changed.
1355 ///
1356 /// As with the [`second`](#method.second) method,
1357 /// the input range is restricted to 0 through 59.
1358 ///
1359 /// See also the [`NaiveTime::with_second`] method.
1360 ///
1361 /// # Errors
1362 ///
1363 /// Returns `None` if:
1364 /// - The value for `second` is invalid.
1365 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1366 /// daylight saving time transition.
1367 #[inline]
1368 fn with_second(&self, sec: u32) -> Option<DateTime<Tz>> {
1369 map_local(self, |datetime| datetime.with_second(sec))
1370 }
1371
1372 /// Makes a new `DateTime` with nanoseconds since the whole non-leap second changed.
1373 ///
1374 /// Returns `None` when the resulting `NaiveDateTime` would be invalid.
1375 /// As with the [`NaiveDateTime::nanosecond`] method,
1376 /// the input range can exceed 1,000,000,000 for leap seconds.
1377 ///
1378 /// See also the [`NaiveTime::with_nanosecond`] method.
1379 ///
1380 /// # Errors
1381 ///
1382 /// Returns `None` if `nanosecond >= 2,000,000,000`.
1383 #[inline]
1384 fn with_nanosecond(&self, nano: u32) -> Option<DateTime<Tz>> {
1385 map_local(self, |datetime| datetime.with_nanosecond(nano))
1386 }
1387}
1388
1389// we need them as automatic impls cannot handle associated types
1390impl<Tz: TimeZone> Copy for DateTime<Tz> where <Tz as TimeZone>::Offset: Copy {}
1391unsafe impl<Tz: TimeZone> Send for DateTime<Tz> where <Tz as TimeZone>::Offset: Send {}
1392
1393impl<Tz: TimeZone, Tz2: TimeZone> PartialEq<DateTime<Tz2>> for DateTime<Tz> {
1394 fn eq(&self, other: &DateTime<Tz2>) -> bool {
1395 self.datetime == other.datetime
1396 }
1397}
1398
1399impl<Tz: TimeZone> Eq for DateTime<Tz> {}
1400
1401impl<Tz: TimeZone, Tz2: TimeZone> PartialOrd<DateTime<Tz2>> for DateTime<Tz> {
1402 /// Compare two DateTimes based on their true time, ignoring time zones
1403 ///
1404 /// # Example
1405 ///
1406 /// ```
1407 /// use chrono::prelude::*;
1408 ///
1409 /// let earlier = Utc
1410 /// .with_ymd_and_hms(2015, 5, 15, 2, 0, 0)
1411 /// .unwrap()
1412 /// .with_timezone(&FixedOffset::west_opt(1 * 3600).unwrap());
1413 /// let later = Utc
1414 /// .with_ymd_and_hms(2015, 5, 15, 3, 0, 0)
1415 /// .unwrap()
1416 /// .with_timezone(&FixedOffset::west_opt(5 * 3600).unwrap());
1417 ///
1418 /// assert_eq!(earlier.to_string(), "2015-05-15 01:00:00 -01:00");
1419 /// assert_eq!(later.to_string(), "2015-05-14 22:00:00 -05:00");
1420 ///
1421 /// assert!(later > earlier);
1422 /// ```
1423 fn partial_cmp(&self, other: &DateTime<Tz2>) -> Option<Ordering> {
1424 self.datetime.partial_cmp(&other.datetime)
1425 }
1426}
1427
1428impl<Tz: TimeZone> Ord for DateTime<Tz> {
1429 fn cmp(&self, other: &DateTime<Tz>) -> Ordering {
1430 self.datetime.cmp(&other.datetime)
1431 }
1432}
1433
1434impl<Tz: TimeZone> hash::Hash for DateTime<Tz> {
1435 fn hash<H: hash::Hasher>(&self, state: &mut H) {
1436 self.datetime.hash(state)
1437 }
1438}
1439
1440/// Add `TimeDelta` to `DateTime`.
1441///
1442/// As a part of Chrono's [leap second handling], the addition assumes that **there is no leap
1443/// second ever**, except when the `NaiveDateTime` itself represents a leap second in which case
1444/// the assumption becomes that **there is exactly a single leap second ever**.
1445///
1446/// # Panics
1447///
1448/// Panics if the resulting date would be out of range.
1449/// Consider using [`DateTime<Tz>::checked_add_signed`] to get an `Option` instead.
1450impl<Tz: TimeZone> Add<TimeDelta> for DateTime<Tz> {
1451 type Output = DateTime<Tz>;
1452
1453 #[inline]
1454 fn add(self, rhs: TimeDelta) -> DateTime<Tz> {
1455 self.checked_add_signed(rhs).expect(msg:"`DateTime + TimeDelta` overflowed")
1456 }
1457}
1458
1459/// Add `std::time::Duration` to `DateTime`.
1460///
1461/// As a part of Chrono's [leap second handling], the addition assumes that **there is no leap
1462/// second ever**, except when the `NaiveDateTime` itself represents a leap second in which case
1463/// the assumption becomes that **there is exactly a single leap second ever**.
1464///
1465/// # Panics
1466///
1467/// Panics if the resulting date would be out of range.
1468/// Consider using [`DateTime<Tz>::checked_add_signed`] to get an `Option` instead.
1469impl<Tz: TimeZone> Add<Duration> for DateTime<Tz> {
1470 type Output = DateTime<Tz>;
1471
1472 #[inline]
1473 fn add(self, rhs: Duration) -> DateTime<Tz> {
1474 let rhs: TimeDelta = TimeDelta::from_std(rhs)
1475 .expect(msg:"overflow converting from core::time::Duration to TimeDelta");
1476 self.checked_add_signed(rhs).expect(msg:"`DateTime + TimeDelta` overflowed")
1477 }
1478}
1479
1480/// Add-assign `chrono::Duration` to `DateTime`.
1481///
1482/// As a part of Chrono's [leap second handling], the addition assumes that **there is no leap
1483/// second ever**, except when the `NaiveDateTime` itself represents a leap second in which case
1484/// the assumption becomes that **there is exactly a single leap second ever**.
1485///
1486/// # Panics
1487///
1488/// Panics if the resulting date would be out of range.
1489/// Consider using [`DateTime<Tz>::checked_add_signed`] to get an `Option` instead.
1490impl<Tz: TimeZone> AddAssign<TimeDelta> for DateTime<Tz> {
1491 #[inline]
1492 fn add_assign(&mut self, rhs: TimeDelta) {
1493 let datetime: NaiveDateTime =
1494 self.datetime.checked_add_signed(rhs).expect(msg:"`DateTime + TimeDelta` overflowed");
1495 let tz: Tz = self.timezone();
1496 *self = tz.from_utc_datetime(&datetime);
1497 }
1498}
1499
1500/// Add-assign `std::time::Duration` to `DateTime`.
1501///
1502/// As a part of Chrono's [leap second handling], the addition assumes that **there is no leap
1503/// second ever**, except when the `NaiveDateTime` itself represents a leap second in which case
1504/// the assumption becomes that **there is exactly a single leap second ever**.
1505///
1506/// # Panics
1507///
1508/// Panics if the resulting date would be out of range.
1509/// Consider using [`DateTime<Tz>::checked_add_signed`] to get an `Option` instead.
1510impl<Tz: TimeZone> AddAssign<Duration> for DateTime<Tz> {
1511 #[inline]
1512 fn add_assign(&mut self, rhs: Duration) {
1513 let rhs: TimeDelta = TimeDelta::from_std(rhs)
1514 .expect(msg:"overflow converting from core::time::Duration to TimeDelta");
1515 *self += rhs;
1516 }
1517}
1518
1519/// Add `FixedOffset` to the datetime value of `DateTime` (offset remains unchanged).
1520///
1521/// # Panics
1522///
1523/// Panics if the resulting date would be out of range.
1524impl<Tz: TimeZone> Add<FixedOffset> for DateTime<Tz> {
1525 type Output = DateTime<Tz>;
1526
1527 #[inline]
1528 fn add(mut self, rhs: FixedOffset) -> DateTime<Tz> {
1529 self.datetime =
1530 self.naive_utc().checked_add_offset(rhs).expect(msg:"`DateTime + FixedOffset` overflowed");
1531 self
1532 }
1533}
1534
1535/// Add `Months` to `DateTime`.
1536///
1537/// The result will be clamped to valid days in the resulting month, see `checked_add_months` for
1538/// details.
1539///
1540/// # Panics
1541///
1542/// Panics if:
1543/// - The resulting date would be out of range.
1544/// - The local time at the resulting date does not exist or is ambiguous, for example during a
1545/// daylight saving time transition.
1546///
1547/// Strongly consider using [`DateTime<Tz>::checked_add_months`] to get an `Option` instead.
1548impl<Tz: TimeZone> Add<Months> for DateTime<Tz> {
1549 type Output = DateTime<Tz>;
1550
1551 fn add(self, rhs: Months) -> Self::Output {
1552 self.checked_add_months(rhs).expect(msg:"`DateTime + Months` out of range")
1553 }
1554}
1555
1556/// Subtract `TimeDelta` from `DateTime`.
1557///
1558/// This is the same as the addition with a negated `TimeDelta`.
1559///
1560/// As a part of Chrono's [leap second handling] the subtraction assumes that **there is no leap
1561/// second ever**, except when the `DateTime` itself represents a leap second in which case
1562/// the assumption becomes that **there is exactly a single leap second ever**.
1563///
1564/// # Panics
1565///
1566/// Panics if the resulting date would be out of range.
1567/// Consider using [`DateTime<Tz>::checked_sub_signed`] to get an `Option` instead.
1568impl<Tz: TimeZone> Sub<TimeDelta> for DateTime<Tz> {
1569 type Output = DateTime<Tz>;
1570
1571 #[inline]
1572 fn sub(self, rhs: TimeDelta) -> DateTime<Tz> {
1573 self.checked_sub_signed(rhs).expect(msg:"`DateTime - TimeDelta` overflowed")
1574 }
1575}
1576
1577/// Subtract `std::time::Duration` from `DateTime`.
1578///
1579/// As a part of Chrono's [leap second handling] the subtraction assumes that **there is no leap
1580/// second ever**, except when the `DateTime` itself represents a leap second in which case
1581/// the assumption becomes that **there is exactly a single leap second ever**.
1582///
1583/// # Panics
1584///
1585/// Panics if the resulting date would be out of range.
1586/// Consider using [`DateTime<Tz>::checked_sub_signed`] to get an `Option` instead.
1587impl<Tz: TimeZone> Sub<Duration> for DateTime<Tz> {
1588 type Output = DateTime<Tz>;
1589
1590 #[inline]
1591 fn sub(self, rhs: Duration) -> DateTime<Tz> {
1592 let rhs: TimeDelta = TimeDelta::from_std(rhs)
1593 .expect(msg:"overflow converting from core::time::Duration to TimeDelta");
1594 self.checked_sub_signed(rhs).expect(msg:"`DateTime - TimeDelta` overflowed")
1595 }
1596}
1597
1598/// Subtract-assign `TimeDelta` from `DateTime`.
1599///
1600/// This is the same as the addition with a negated `TimeDelta`.
1601///
1602/// As a part of Chrono's [leap second handling], the addition assumes that **there is no leap
1603/// second ever**, except when the `DateTime` itself represents a leap second in which case
1604/// the assumption becomes that **there is exactly a single leap second ever**.
1605///
1606/// # Panics
1607///
1608/// Panics if the resulting date would be out of range.
1609/// Consider using [`DateTime<Tz>::checked_sub_signed`] to get an `Option` instead.
1610impl<Tz: TimeZone> SubAssign<TimeDelta> for DateTime<Tz> {
1611 #[inline]
1612 fn sub_assign(&mut self, rhs: TimeDelta) {
1613 let datetime: NaiveDateTime =
1614 self.datetime.checked_sub_signed(rhs).expect(msg:"`DateTime - TimeDelta` overflowed");
1615 let tz: Tz = self.timezone();
1616 *self = tz.from_utc_datetime(&datetime)
1617 }
1618}
1619
1620/// Subtract-assign `std::time::Duration` from `DateTime`.
1621///
1622/// As a part of Chrono's [leap second handling], the addition assumes that **there is no leap
1623/// second ever**, except when the `DateTime` itself represents a leap second in which case
1624/// the assumption becomes that **there is exactly a single leap second ever**.
1625///
1626/// # Panics
1627///
1628/// Panics if the resulting date would be out of range.
1629/// Consider using [`DateTime<Tz>::checked_sub_signed`] to get an `Option` instead.
1630impl<Tz: TimeZone> SubAssign<Duration> for DateTime<Tz> {
1631 #[inline]
1632 fn sub_assign(&mut self, rhs: Duration) {
1633 let rhs: TimeDelta = TimeDelta::from_std(rhs)
1634 .expect(msg:"overflow converting from core::time::Duration to TimeDelta");
1635 *self -= rhs;
1636 }
1637}
1638
1639/// Subtract `FixedOffset` from the datetime value of `DateTime` (offset remains unchanged).
1640///
1641/// # Panics
1642///
1643/// Panics if the resulting date would be out of range.
1644impl<Tz: TimeZone> Sub<FixedOffset> for DateTime<Tz> {
1645 type Output = DateTime<Tz>;
1646
1647 #[inline]
1648 fn sub(mut self, rhs: FixedOffset) -> DateTime<Tz> {
1649 self.datetime =
1650 self.naive_utc().checked_sub_offset(rhs).expect(msg:"`DateTime - FixedOffset` overflowed");
1651 self
1652 }
1653}
1654
1655/// Subtract `Months` from `DateTime`.
1656///
1657/// The result will be clamped to valid days in the resulting month, see
1658/// [`DateTime<Tz>::checked_sub_months`] for details.
1659///
1660/// # Panics
1661///
1662/// Panics if:
1663/// - The resulting date would be out of range.
1664/// - The local time at the resulting date does not exist or is ambiguous, for example during a
1665/// daylight saving time transition.
1666///
1667/// Strongly consider using [`DateTime<Tz>::checked_sub_months`] to get an `Option` instead.
1668impl<Tz: TimeZone> Sub<Months> for DateTime<Tz> {
1669 type Output = DateTime<Tz>;
1670
1671 fn sub(self, rhs: Months) -> Self::Output {
1672 self.checked_sub_months(rhs).expect(msg:"`DateTime - Months` out of range")
1673 }
1674}
1675
1676impl<Tz: TimeZone> Sub<DateTime<Tz>> for DateTime<Tz> {
1677 type Output = TimeDelta;
1678
1679 #[inline]
1680 fn sub(self, rhs: DateTime<Tz>) -> TimeDelta {
1681 self.signed_duration_since(rhs)
1682 }
1683}
1684
1685impl<Tz: TimeZone> Sub<&DateTime<Tz>> for DateTime<Tz> {
1686 type Output = TimeDelta;
1687
1688 #[inline]
1689 fn sub(self, rhs: &DateTime<Tz>) -> TimeDelta {
1690 self.signed_duration_since(rhs)
1691 }
1692}
1693
1694/// Add `Days` to `NaiveDateTime`.
1695///
1696/// # Panics
1697///
1698/// Panics if:
1699/// - The resulting date would be out of range.
1700/// - The local time at the resulting date does not exist or is ambiguous, for example during a
1701/// daylight saving time transition.
1702///
1703/// Strongly consider using `DateTime<Tz>::checked_sub_days` to get an `Option` instead.
1704impl<Tz: TimeZone> Add<Days> for DateTime<Tz> {
1705 type Output = DateTime<Tz>;
1706
1707 fn add(self, days: Days) -> Self::Output {
1708 self.checked_add_days(days).expect(msg:"`DateTime + Days` out of range")
1709 }
1710}
1711
1712/// Subtract `Days` from `DateTime`.
1713///
1714/// # Panics
1715///
1716/// Panics if:
1717/// - The resulting date would be out of range.
1718/// - The local time at the resulting date does not exist or is ambiguous, for example during a
1719/// daylight saving time transition.
1720///
1721/// Strongly consider using `DateTime<Tz>::checked_sub_days` to get an `Option` instead.
1722impl<Tz: TimeZone> Sub<Days> for DateTime<Tz> {
1723 type Output = DateTime<Tz>;
1724
1725 fn sub(self, days: Days) -> Self::Output {
1726 self.checked_sub_days(days).expect(msg:"`DateTime - Days` out of range")
1727 }
1728}
1729
1730impl<Tz: TimeZone> fmt::Debug for DateTime<Tz> {
1731 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1732 self.overflowing_naive_local().fmt(f)?;
1733 self.offset.fmt(f)
1734 }
1735}
1736
1737// `fmt::Debug` is hand implemented for the `rkyv::Archive` variant of `DateTime` because
1738// deriving a trait recursively does not propagate trait defined associated types with their own
1739// constraints:
1740// In our case `<<Tz as offset::TimeZone>::Offset as Archive>::Archived`
1741// cannot be formatted using `{:?}` because it doesn't implement `Debug`.
1742// See below for further discussion:
1743// * https://github.com/rust-lang/rust/issues/26925
1744// * https://github.com/rkyv/rkyv/issues/333
1745// * https://github.com/dtolnay/syn/issues/370
1746#[cfg(feature = "rkyv-validation")]
1747impl<Tz: TimeZone> fmt::Debug for ArchivedDateTime<Tz>
1748where
1749 Tz: Archive,
1750 <Tz as Archive>::Archived: fmt::Debug,
1751 <<Tz as TimeZone>::Offset as Archive>::Archived: fmt::Debug,
1752 <Tz as TimeZone>::Offset: fmt::Debug + Archive,
1753{
1754 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1755 f.debug_struct("ArchivedDateTime")
1756 .field("datetime", &self.datetime)
1757 .field("offset", &self.offset)
1758 .finish()
1759 }
1760}
1761
1762impl<Tz: TimeZone> fmt::Display for DateTime<Tz>
1763where
1764 Tz::Offset: fmt::Display,
1765{
1766 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1767 self.overflowing_naive_local().fmt(f)?;
1768 f.write_char(' ')?;
1769 self.offset.fmt(f)
1770 }
1771}
1772
1773/// Accepts a relaxed form of RFC3339.
1774/// A space or a 'T' are accepted as the separator between the date and time
1775/// parts.
1776///
1777/// All of these examples are equivalent:
1778/// ```
1779/// # use chrono::{DateTime, Utc};
1780/// "2012-12-12T12:12:12Z".parse::<DateTime<Utc>>()?;
1781/// "2012-12-12 12:12:12Z".parse::<DateTime<Utc>>()?;
1782/// "2012-12-12 12:12:12+0000".parse::<DateTime<Utc>>()?;
1783/// "2012-12-12 12:12:12+00:00".parse::<DateTime<Utc>>()?;
1784/// # Ok::<(), chrono::ParseError>(())
1785/// ```
1786impl str::FromStr for DateTime<Utc> {
1787 type Err = ParseError;
1788
1789 fn from_str(s: &str) -> ParseResult<DateTime<Utc>> {
1790 s.parse::<DateTime<FixedOffset>>().map(|dt: DateTime| dt.with_timezone(&Utc))
1791 }
1792}
1793
1794/// Accepts a relaxed form of RFC3339.
1795/// A space or a 'T' are accepted as the separator between the date and time
1796/// parts.
1797///
1798/// All of these examples are equivalent:
1799/// ```
1800/// # use chrono::{DateTime, Local};
1801/// "2012-12-12T12:12:12Z".parse::<DateTime<Local>>()?;
1802/// "2012-12-12 12:12:12Z".parse::<DateTime<Local>>()?;
1803/// "2012-12-12 12:12:12+0000".parse::<DateTime<Local>>()?;
1804/// "2012-12-12 12:12:12+00:00".parse::<DateTime<Local>>()?;
1805/// # Ok::<(), chrono::ParseError>(())
1806/// ```
1807#[cfg(feature = "clock")]
1808impl str::FromStr for DateTime<Local> {
1809 type Err = ParseError;
1810
1811 fn from_str(s: &str) -> ParseResult<DateTime<Local>> {
1812 s.parse::<DateTime<FixedOffset>>().map(|dt: DateTime| dt.with_timezone(&Local))
1813 }
1814}
1815
1816#[cfg(feature = "std")]
1817impl From<SystemTime> for DateTime<Utc> {
1818 fn from(t: SystemTime) -> DateTime<Utc> {
1819 let (sec: i64, nsec: u32) = match t.duration_since(UNIX_EPOCH) {
1820 Ok(dur: Duration) => (dur.as_secs() as i64, dur.subsec_nanos()),
1821 Err(e: SystemTimeError) => {
1822 // unlikely but should be handled
1823 let dur: Duration = e.duration();
1824 let (sec: i64, nsec: u32) = (dur.as_secs() as i64, dur.subsec_nanos());
1825 if nsec == 0 {
1826 (-sec, 0)
1827 } else {
1828 (-sec - 1, 1_000_000_000 - nsec)
1829 }
1830 }
1831 };
1832 Utc.timestamp_opt(secs:sec, nsecs:nsec).unwrap()
1833 }
1834}
1835
1836#[cfg(feature = "clock")]
1837impl From<SystemTime> for DateTime<Local> {
1838 fn from(t: SystemTime) -> DateTime<Local> {
1839 DateTime::<Utc>::from(t).with_timezone(&Local)
1840 }
1841}
1842
1843#[cfg(feature = "std")]
1844impl<Tz: TimeZone> From<DateTime<Tz>> for SystemTime {
1845 fn from(dt: DateTime<Tz>) -> SystemTime {
1846 let sec: i64 = dt.timestamp();
1847 let nsec: u32 = dt.timestamp_subsec_nanos();
1848 if sec < 0 {
1849 // unlikely but should be handled
1850 UNIX_EPOCH - Duration::new(-sec as u64, nanos:0) + Duration::new(secs:0, nanos:nsec)
1851 } else {
1852 UNIX_EPOCH + Duration::new(secs:sec as u64, nanos:nsec)
1853 }
1854 }
1855}
1856
1857#[cfg(all(
1858 target_arch = "wasm32",
1859 feature = "wasmbind",
1860 not(any(target_os = "emscripten", target_os = "wasi"))
1861))]
1862impl From<js_sys::Date> for DateTime<Utc> {
1863 fn from(date: js_sys::Date) -> DateTime<Utc> {
1864 DateTime::<Utc>::from(&date)
1865 }
1866}
1867
1868#[cfg(all(
1869 target_arch = "wasm32",
1870 feature = "wasmbind",
1871 not(any(target_os = "emscripten", target_os = "wasi"))
1872))]
1873impl From<&js_sys::Date> for DateTime<Utc> {
1874 fn from(date: &js_sys::Date) -> DateTime<Utc> {
1875 Utc.timestamp_millis_opt(date.get_time() as i64).unwrap()
1876 }
1877}
1878
1879#[cfg(all(
1880 target_arch = "wasm32",
1881 feature = "wasmbind",
1882 not(any(target_os = "emscripten", target_os = "wasi"))
1883))]
1884impl From<DateTime<Utc>> for js_sys::Date {
1885 /// Converts a `DateTime<Utc>` to a JS `Date`. The resulting value may be lossy,
1886 /// any values that have a millisecond timestamp value greater/less than ±8,640,000,000,000,000
1887 /// (April 20, 271821 BCE ~ September 13, 275760 CE) will become invalid dates in JS.
1888 fn from(date: DateTime<Utc>) -> js_sys::Date {
1889 let js_millis = wasm_bindgen::JsValue::from_f64(date.timestamp_millis() as f64);
1890 js_sys::Date::new(&js_millis)
1891 }
1892}
1893
1894// Note that implementation of Arbitrary cannot be simply derived for DateTime<Tz>, due to
1895// the nontrivial bound <Tz as TimeZone>::Offset: Arbitrary.
1896#[cfg(all(feature = "arbitrary", feature = "std"))]
1897impl<'a, Tz> arbitrary::Arbitrary<'a> for DateTime<Tz>
1898where
1899 Tz: TimeZone,
1900 <Tz as TimeZone>::Offset: arbitrary::Arbitrary<'a>,
1901{
1902 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<DateTime<Tz>> {
1903 let datetime = NaiveDateTime::arbitrary(u)?;
1904 let offset = <Tz as TimeZone>::Offset::arbitrary(u)?;
1905 Ok(DateTime::from_naive_utc_and_offset(datetime, offset))
1906 }
1907}
1908
1909/// Number of days between Januari 1, 1970 and December 31, 1 BCE which we define to be day 0.
1910/// 4 full leap year cycles until December 31, 1600 4 * 146097 = 584388
1911/// 1 day until January 1, 1601 1
1912/// 369 years until Januari 1, 1970 369 * 365 = 134685
1913/// of which floor(369 / 4) are leap years floor(369 / 4) = 92
1914/// except for 1700, 1800 and 1900 -3 +
1915/// --------
1916/// 719163
1917const UNIX_EPOCH_DAY: i64 = 719_163;
1918
1919#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))]
1920fn test_encodable_json<FUtc, FFixed, E>(to_string_utc: FUtc, to_string_fixed: FFixed)
1921where
1922 FUtc: Fn(&DateTime<Utc>) -> Result<String, E>,
1923 FFixed: Fn(&DateTime<FixedOffset>) -> Result<String, E>,
1924 E: ::core::fmt::Debug,
1925{
1926 assert_eq!(
1927 to_string_utc(&Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()).ok(),
1928 Some(r#""2014-07-24T12:34:06Z""#.into())
1929 );
1930
1931 assert_eq!(
1932 to_string_fixed(
1933 &FixedOffset::east_opt(3660).unwrap().with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()
1934 )
1935 .ok(),
1936 Some(r#""2014-07-24T12:34:06+01:01""#.into())
1937 );
1938 assert_eq!(
1939 to_string_fixed(
1940 &FixedOffset::east_opt(3650).unwrap().with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()
1941 )
1942 .ok(),
1943 // An offset with seconds is not allowed by RFC 3339, so we round it to the nearest minute.
1944 // In this case `+01:00:50` becomes `+01:01`
1945 Some(r#""2014-07-24T12:34:06+01:01""#.into())
1946 );
1947}
1948
1949#[cfg(all(test, feature = "clock", any(feature = "rustc-serialize", feature = "serde")))]
1950fn test_decodable_json<FUtc, FFixed, FLocal, E>(
1951 utc_from_str: FUtc,
1952 fixed_from_str: FFixed,
1953 local_from_str: FLocal,
1954) where
1955 FUtc: Fn(&str) -> Result<DateTime<Utc>, E>,
1956 FFixed: Fn(&str) -> Result<DateTime<FixedOffset>, E>,
1957 FLocal: Fn(&str) -> Result<DateTime<Local>, E>,
1958 E: ::core::fmt::Debug,
1959{
1960 // should check against the offset as well (the normal DateTime comparison will ignore them)
1961 fn norm<Tz: TimeZone>(dt: &Option<DateTime<Tz>>) -> Option<(&DateTime<Tz>, &Tz::Offset)> {
1962 dt.as_ref().map(|dt| (dt, dt.offset()))
1963 }
1964
1965 assert_eq!(
1966 norm(&utc_from_str(r#""2014-07-24T12:34:06Z""#).ok()),
1967 norm(&Some(Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()))
1968 );
1969 assert_eq!(
1970 norm(&utc_from_str(r#""2014-07-24T13:57:06+01:23""#).ok()),
1971 norm(&Some(Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()))
1972 );
1973
1974 assert_eq!(
1975 norm(&fixed_from_str(r#""2014-07-24T12:34:06Z""#).ok()),
1976 norm(&Some(
1977 FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()
1978 ))
1979 );
1980 assert_eq!(
1981 norm(&fixed_from_str(r#""2014-07-24T13:57:06+01:23""#).ok()),
1982 norm(&Some(
1983 FixedOffset::east_opt(60 * 60 + 23 * 60)
1984 .unwrap()
1985 .with_ymd_and_hms(2014, 7, 24, 13, 57, 6)
1986 .unwrap()
1987 ))
1988 );
1989
1990 // we don't know the exact local offset but we can check that
1991 // the conversion didn't change the instant itself
1992 assert_eq!(
1993 local_from_str(r#""2014-07-24T12:34:06Z""#).expect("local should parse"),
1994 Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()
1995 );
1996 assert_eq!(
1997 local_from_str(r#""2014-07-24T13:57:06+01:23""#).expect("local should parse with offset"),
1998 Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()
1999 );
2000
2001 assert!(utc_from_str(r#""2014-07-32T12:34:06Z""#).is_err());
2002 assert!(fixed_from_str(r#""2014-07-32T12:34:06Z""#).is_err());
2003}
2004
2005#[cfg(all(test, feature = "clock", feature = "rustc-serialize"))]
2006fn test_decodable_json_timestamps<FUtc, FFixed, FLocal, E>(
2007 utc_from_str: FUtc,
2008 fixed_from_str: FFixed,
2009 local_from_str: FLocal,
2010) where
2011 FUtc: Fn(&str) -> Result<rustc_serialize::TsSeconds<Utc>, E>,
2012 FFixed: Fn(&str) -> Result<rustc_serialize::TsSeconds<FixedOffset>, E>,
2013 FLocal: Fn(&str) -> Result<rustc_serialize::TsSeconds<Local>, E>,
2014 E: ::core::fmt::Debug,
2015{
2016 fn norm<Tz: TimeZone>(dt: &Option<DateTime<Tz>>) -> Option<(&DateTime<Tz>, &Tz::Offset)> {
2017 dt.as_ref().map(|dt| (dt, dt.offset()))
2018 }
2019
2020 assert_eq!(
2021 norm(&utc_from_str("0").ok().map(DateTime::from)),
2022 norm(&Some(Utc.with_ymd_and_hms(1970, 1, 1, 0, 0, 0).unwrap()))
2023 );
2024 assert_eq!(
2025 norm(&utc_from_str("-1").ok().map(DateTime::from)),
2026 norm(&Some(Utc.with_ymd_and_hms(1969, 12, 31, 23, 59, 59).unwrap()))
2027 );
2028
2029 assert_eq!(
2030 norm(&fixed_from_str("0").ok().map(DateTime::from)),
2031 norm(&Some(
2032 FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(1970, 1, 1, 0, 0, 0).unwrap()
2033 ))
2034 );
2035 assert_eq!(
2036 norm(&fixed_from_str("-1").ok().map(DateTime::from)),
2037 norm(&Some(
2038 FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(1969, 12, 31, 23, 59, 59).unwrap()
2039 ))
2040 );
2041
2042 assert_eq!(
2043 *fixed_from_str("0").expect("0 timestamp should parse"),
2044 Utc.with_ymd_and_hms(1970, 1, 1, 0, 0, 0).unwrap()
2045 );
2046 assert_eq!(
2047 *local_from_str("-1").expect("-1 timestamp should parse"),
2048 Utc.with_ymd_and_hms(1969, 12, 31, 23, 59, 59).unwrap()
2049 );
2050}
2051