chrono/datetime/mod.rs
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(feature = "alloc", not(feature = "std"), not(test)))]
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, LocalResult, 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(Copy, 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 /// ```
83 /// # #[cfg(feature = "clock")] {
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 /// ```
95 #[inline]
96 #[must_use]
97 pub const fn from_naive_utc_and_offset(
98 datetime: NaiveDateTime,
99 offset: Tz::Offset,
100 ) -> DateTime<Tz> {
101 DateTime { datetime, offset }
102 }
103
104 /// Makes a new `DateTime` from its components: a `NaiveDateTime` in UTC and an `Offset`.
105 #[inline]
106 #[must_use]
107 #[deprecated(
108 since = "0.4.27",
109 note = "Use TimeZone::from_utc_datetime() or DateTime::from_naive_utc_and_offset instead"
110 )]
111 pub fn from_utc(datetime: NaiveDateTime, offset: Tz::Offset) -> DateTime<Tz> {
112 DateTime { datetime, offset }
113 }
114
115 /// Makes a new `DateTime` from a `NaiveDateTime` in *local* time and an `Offset`.
116 ///
117 /// # Panics
118 ///
119 /// Panics if the local datetime can't be converted to UTC because it would be out of range.
120 ///
121 /// This can happen if `datetime` is near the end of the representable range of `NaiveDateTime`,
122 /// and the offset from UTC pushes it beyond that.
123 #[inline]
124 #[must_use]
125 #[deprecated(
126 since = "0.4.27",
127 note = "Use TimeZone::from_local_datetime() or NaiveDateTime::and_local_timezone instead"
128 )]
129 pub fn from_local(datetime: NaiveDateTime, offset: Tz::Offset) -> DateTime<Tz> {
130 let datetime_utc = datetime - offset.fix();
131
132 DateTime { datetime: datetime_utc, offset }
133 }
134
135 /// Retrieves the date component with an associated timezone.
136 ///
137 /// Unless you are immediately planning on turning this into a `DateTime`
138 /// with the same timezone you should use the [`date_naive`](DateTime::date_naive) method.
139 ///
140 /// [`NaiveDate`] is a more well-defined type, and has more traits implemented on it,
141 /// so should be preferred to [`Date`] any time you truly want to operate on dates.
142 ///
143 /// # Panics
144 ///
145 /// [`DateTime`] internally stores the date and time in UTC with a [`NaiveDateTime`]. This
146 /// method will panic if the offset from UTC would push the local date outside of the
147 /// representable range of a [`Date`].
148 #[inline]
149 #[deprecated(since = "0.4.23", note = "Use `date_naive()` instead")]
150 #[allow(deprecated)]
151 #[must_use]
152 pub fn date(&self) -> Date<Tz> {
153 Date::from_utc(self.naive_local().date(), self.offset.clone())
154 }
155
156 /// Retrieves the date component.
157 ///
158 /// # Panics
159 ///
160 /// [`DateTime`] internally stores the date and time in UTC with a [`NaiveDateTime`]. This
161 /// method will panic if the offset from UTC would push the local date outside of the
162 /// representable range of a [`NaiveDate`].
163 ///
164 /// # Example
165 ///
166 /// ```
167 /// use chrono::prelude::*;
168 ///
169 /// let date: DateTime<Utc> = Utc.with_ymd_and_hms(2020, 1, 1, 0, 0, 0).unwrap();
170 /// let other: DateTime<FixedOffset> =
171 /// FixedOffset::east_opt(23).unwrap().with_ymd_and_hms(2020, 1, 1, 0, 0, 0).unwrap();
172 /// assert_eq!(date.date_naive(), other.date_naive());
173 /// ```
174 #[inline]
175 #[must_use]
176 pub fn date_naive(&self) -> NaiveDate {
177 self.naive_local().date()
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, 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_utc();
662 /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Millis, false), "2018-01-26T18:30:09.453+00:00");
663 /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Millis, true), "2018-01-26T18:30:09.453Z");
664 /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Secs, true), "2018-01-26T18:30:09Z");
665 ///
666 /// let pst = FixedOffset::east_opt(8 * 60 * 60).unwrap();
667 /// let dt = pst
668 /// .from_local_datetime(
669 /// &NaiveDate::from_ymd_opt(2018, 1, 26)
670 /// .unwrap()
671 /// .and_hms_micro_opt(10, 30, 9, 453_829)
672 /// .unwrap(),
673 /// )
674 /// .unwrap();
675 /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Secs, true), "2018-01-26T10:30:09+08:00");
676 /// ```
677 #[cfg(feature = "alloc")]
678 #[must_use]
679 pub fn to_rfc3339_opts(&self, secform: SecondsFormat, use_z: bool) -> String {
680 let mut result = String::with_capacity(38);
681 write_rfc3339(&mut result, self.naive_local(), self.offset.fix(), secform, use_z)
682 .expect("writing rfc3339 datetime to string should never fail");
683 result
684 }
685
686 /// Set the time to a new fixed time on the existing date.
687 ///
688 /// # Errors
689 ///
690 /// Returns `LocalResult::None` if the datetime is at the edge of the representable range for a
691 /// `DateTime`, and `with_time` would push the value in UTC out of range.
692 ///
693 /// # Example
694 ///
695 /// ```
696 /// # #[cfg(feature = "clock")] {
697 /// use chrono::{Local, NaiveTime};
698 ///
699 /// let noon = NaiveTime::from_hms_opt(12, 0, 0).unwrap();
700 /// let today_noon = Local::now().with_time(noon);
701 /// let today_midnight = Local::now().with_time(NaiveTime::MIN);
702 ///
703 /// assert_eq!(today_noon.single().unwrap().time(), noon);
704 /// assert_eq!(today_midnight.single().unwrap().time(), NaiveTime::MIN);
705 /// # }
706 /// ```
707 #[must_use]
708 pub fn with_time(&self, time: NaiveTime) -> LocalResult<Self> {
709 self.timezone().from_local_datetime(&self.overflowing_naive_local().date().and_time(time))
710 }
711
712 /// The minimum possible `DateTime<Utc>`.
713 pub const MIN_UTC: DateTime<Utc> = DateTime { datetime: NaiveDateTime::MIN, offset: Utc };
714 /// The maximum possible `DateTime<Utc>`.
715 pub const MAX_UTC: DateTime<Utc> = DateTime { datetime: NaiveDateTime::MAX, offset: Utc };
716}
717
718impl DateTime<Utc> {
719 /// Makes a new `DateTime<Utc>` from the number of non-leap seconds
720 /// since January 1, 1970 0:00:00 UTC (aka "UNIX timestamp")
721 /// and the number of nanoseconds since the last whole non-leap second.
722 ///
723 /// This is guaranteed to round-trip with regard to [`timestamp`](DateTime::timestamp) and
724 /// [`timestamp_subsec_nanos`](DateTime::timestamp_subsec_nanos).
725 ///
726 /// If you need to create a `DateTime` with a [`TimeZone`] different from [`Utc`], use
727 /// [`TimeZone::timestamp_opt`] or [`DateTime::with_timezone`].
728 ///
729 /// The nanosecond part can exceed 1,000,000,000 in order to represent a
730 /// [leap second](NaiveTime#leap-second-handling), but only when `secs % 60 == 59`.
731 /// (The true "UNIX timestamp" cannot represent a leap second unambiguously.)
732 ///
733 /// # Errors
734 ///
735 /// Returns `None` on out-of-range number of seconds and/or
736 /// invalid nanosecond, otherwise returns `Some(DateTime {...})`.
737 ///
738 /// # Example
739 ///
740 /// ```
741 /// use chrono::DateTime;
742 ///
743 /// let dt = DateTime::from_timestamp(1431648000, 0).expect("invalid timestamp");
744 ///
745 /// assert_eq!(dt.to_string(), "2015-05-15 00:00:00 UTC");
746 /// assert_eq!(DateTime::from_timestamp(dt.timestamp(), dt.timestamp_subsec_nanos()).unwrap(), dt);
747 /// ```
748 #[inline]
749 #[must_use]
750 pub const fn from_timestamp(secs: i64, nsecs: u32) -> Option<Self> {
751 let days = secs.div_euclid(86_400) + UNIX_EPOCH_DAY;
752 let secs = secs.rem_euclid(86_400);
753 if days < i32::MIN as i64 || days > i32::MAX as i64 {
754 return None;
755 }
756 let date = try_opt!(NaiveDate::from_num_days_from_ce_opt(days as i32));
757 let time = try_opt!(NaiveTime::from_num_seconds_from_midnight_opt(secs as u32, nsecs));
758 Some(date.and_time(time).and_utc())
759 }
760
761 /// Makes a new `DateTime<Utc>` from the number of non-leap milliseconds
762 /// since January 1, 1970 0:00:00.000 UTC (aka "UNIX timestamp").
763 ///
764 /// This is guaranteed to round-trip with [`timestamp_millis`](DateTime::timestamp_millis).
765 ///
766 /// If you need to create a `DateTime` with a [`TimeZone`] different from [`Utc`], use
767 /// [`TimeZone::timestamp_millis_opt`] or [`DateTime::with_timezone`].
768 ///
769 /// # Errors
770 ///
771 /// Returns `None` on out-of-range number of milliseconds, otherwise returns `Some(DateTime {...})`.
772 ///
773 /// # Example
774 ///
775 /// ```
776 /// use chrono::DateTime;
777 ///
778 /// let dt = DateTime::from_timestamp_millis(947638923004).expect("invalid timestamp");
779 ///
780 /// assert_eq!(dt.to_string(), "2000-01-12 01:02:03.004 UTC");
781 /// assert_eq!(DateTime::from_timestamp_millis(dt.timestamp_millis()).unwrap(), dt);
782 /// ```
783 #[inline]
784 #[must_use]
785 pub const fn from_timestamp_millis(millis: i64) -> Option<Self> {
786 let secs = millis.div_euclid(1000);
787 let nsecs = millis.rem_euclid(1000) as u32 * 1_000_000;
788 Self::from_timestamp(secs, nsecs)
789 }
790
791 /// Creates a new `DateTime<Utc>` from the number of non-leap microseconds
792 /// since January 1, 1970 0:00:00.000 UTC (aka "UNIX timestamp").
793 ///
794 /// This is guaranteed to round-trip with [`timestamp_micros`](DateTime::timestamp_micros).
795 ///
796 /// If you need to create a `DateTime` with a [`TimeZone`] different from [`Utc`], use
797 /// [`TimeZone::timestamp_micros`] or [`DateTime::with_timezone`].
798 ///
799 /// # Errors
800 ///
801 /// Returns `None` if the number of microseconds would be out of range for a `NaiveDateTime`
802 /// (more than ca. 262,000 years away from common era)
803 ///
804 /// # Example
805 ///
806 /// ```
807 /// use chrono::DateTime;
808 ///
809 /// let timestamp_micros: i64 = 1662921288000000; // Sun, 11 Sep 2022 18:34:48 UTC
810 /// let dt = DateTime::from_timestamp_micros(timestamp_micros);
811 /// assert!(dt.is_some());
812 /// assert_eq!(timestamp_micros, dt.expect("invalid timestamp").timestamp_micros());
813 ///
814 /// // Negative timestamps (before the UNIX epoch) are supported as well.
815 /// let timestamp_micros: i64 = -2208936075000000; // Mon, 1 Jan 1900 14:38:45 UTC
816 /// let dt = DateTime::from_timestamp_micros(timestamp_micros);
817 /// assert!(dt.is_some());
818 /// assert_eq!(timestamp_micros, dt.expect("invalid timestamp").timestamp_micros());
819 /// ```
820 #[inline]
821 #[must_use]
822 pub const fn from_timestamp_micros(micros: i64) -> Option<Self> {
823 let secs = micros.div_euclid(1_000_000);
824 let nsecs = micros.rem_euclid(1_000_000) as u32 * 1000;
825 Self::from_timestamp(secs, nsecs)
826 }
827
828 /// Creates a new [`DateTime<Utc>`] from the number of non-leap microseconds
829 /// since January 1, 1970 0:00:00.000 UTC (aka "UNIX timestamp").
830 ///
831 /// This is guaranteed to round-trip with [`timestamp_nanos`](DateTime::timestamp_nanos).
832 ///
833 /// If you need to create a `DateTime` with a [`TimeZone`] different from [`Utc`], use
834 /// [`TimeZone::timestamp_nanos`] or [`DateTime::with_timezone`].
835 ///
836 /// The UNIX epoch starts on midnight, January 1, 1970, UTC.
837 ///
838 /// An `i64` with nanosecond precision can span a range of ~584 years. Because all values can
839 /// be represented as a `DateTime` this method never fails.
840 ///
841 /// # Example
842 ///
843 /// ```
844 /// use chrono::DateTime;
845 ///
846 /// let timestamp_nanos: i64 = 1662921288_000_000_000; // Sun, 11 Sep 2022 18:34:48 UTC
847 /// let dt = DateTime::from_timestamp_nanos(timestamp_nanos);
848 /// assert_eq!(timestamp_nanos, dt.timestamp_nanos_opt().unwrap());
849 ///
850 /// // Negative timestamps (before the UNIX epoch) are supported as well.
851 /// let timestamp_nanos: i64 = -2208936075_000_000_000; // Mon, 1 Jan 1900 14:38:45 UTC
852 /// let dt = DateTime::from_timestamp_nanos(timestamp_nanos);
853 /// assert_eq!(timestamp_nanos, dt.timestamp_nanos_opt().unwrap());
854 /// ```
855 #[inline]
856 #[must_use]
857 pub const fn from_timestamp_nanos(nanos: i64) -> Self {
858 let secs = nanos.div_euclid(1_000_000_000);
859 let nsecs = nanos.rem_euclid(1_000_000_000) as u32;
860 expect(Self::from_timestamp(secs, nsecs), "timestamp in nanos is always in range")
861 }
862
863 /// The Unix Epoch, 1970-01-01 00:00:00 UTC.
864 pub const UNIX_EPOCH: Self = Self { datetime: NaiveDateTime::UNIX_EPOCH, offset: Utc };
865}
866
867impl Default for DateTime<Utc> {
868 fn default() -> Self {
869 Utc.from_utc_datetime(&NaiveDateTime::default())
870 }
871}
872
873#[cfg(feature = "clock")]
874impl Default for DateTime<Local> {
875 fn default() -> Self {
876 Local.from_utc_datetime(&NaiveDateTime::default())
877 }
878}
879
880impl Default for DateTime<FixedOffset> {
881 fn default() -> Self {
882 FixedOffset::west_opt(0).unwrap().from_utc_datetime(&NaiveDateTime::default())
883 }
884}
885
886/// Convert a `DateTime<Utc>` instance into a `DateTime<FixedOffset>` instance.
887impl From<DateTime<Utc>> for DateTime<FixedOffset> {
888 /// Convert this `DateTime<Utc>` instance into a `DateTime<FixedOffset>` instance.
889 ///
890 /// Conversion is done via [`DateTime::with_timezone`]. Note that the converted value returned by
891 /// this will be created with a fixed timezone offset of 0.
892 fn from(src: DateTime<Utc>) -> Self {
893 src.with_timezone(&FixedOffset::east_opt(0).unwrap())
894 }
895}
896
897/// Convert a `DateTime<Utc>` instance into a `DateTime<Local>` instance.
898#[cfg(feature = "clock")]
899impl From<DateTime<Utc>> for DateTime<Local> {
900 /// Convert this `DateTime<Utc>` instance into a `DateTime<Local>` instance.
901 ///
902 /// Conversion is performed via [`DateTime::with_timezone`], accounting for the difference in timezones.
903 fn from(src: DateTime<Utc>) -> Self {
904 src.with_timezone(&Local)
905 }
906}
907
908/// Convert a `DateTime<FixedOffset>` instance into a `DateTime<Utc>` instance.
909impl From<DateTime<FixedOffset>> for DateTime<Utc> {
910 /// Convert this `DateTime<FixedOffset>` instance into a `DateTime<Utc>` instance.
911 ///
912 /// Conversion is performed via [`DateTime::with_timezone`], accounting for the timezone
913 /// difference.
914 fn from(src: DateTime<FixedOffset>) -> Self {
915 src.with_timezone(&Utc)
916 }
917}
918
919/// Convert a `DateTime<FixedOffset>` instance into a `DateTime<Local>` instance.
920#[cfg(feature = "clock")]
921impl From<DateTime<FixedOffset>> for DateTime<Local> {
922 /// Convert this `DateTime<FixedOffset>` instance into a `DateTime<Local>` instance.
923 ///
924 /// Conversion is performed via [`DateTime::with_timezone`]. Returns the equivalent value in local
925 /// time.
926 fn from(src: DateTime<FixedOffset>) -> Self {
927 src.with_timezone(&Local)
928 }
929}
930
931/// Convert a `DateTime<Local>` instance into a `DateTime<Utc>` instance.
932#[cfg(feature = "clock")]
933impl From<DateTime<Local>> for DateTime<Utc> {
934 /// Convert this `DateTime<Local>` instance into a `DateTime<Utc>` instance.
935 ///
936 /// Conversion is performed via [`DateTime::with_timezone`], accounting for the difference in
937 /// timezones.
938 fn from(src: DateTime<Local>) -> Self {
939 src.with_timezone(&Utc)
940 }
941}
942
943/// Convert a `DateTime<Local>` instance into a `DateTime<FixedOffset>` instance.
944#[cfg(feature = "clock")]
945impl From<DateTime<Local>> for DateTime<FixedOffset> {
946 /// Convert this `DateTime<Local>` instance into a `DateTime<FixedOffset>` instance.
947 ///
948 /// Conversion is performed via [`DateTime::with_timezone`].
949 fn from(src: DateTime<Local>) -> Self {
950 src.with_timezone(&src.offset().fix())
951 }
952}
953
954/// Maps the local datetime to other datetime with given conversion function.
955fn map_local<Tz: TimeZone, F>(dt: &DateTime<Tz>, mut f: F) -> Option<DateTime<Tz>>
956where
957 F: FnMut(NaiveDateTime) -> Option<NaiveDateTime>,
958{
959 f(dt.overflowing_naive_local())
960 .and_then(|datetime| dt.timezone().from_local_datetime(&datetime).single())
961 .filter(|dt| dt >= &DateTime::<Utc>::MIN_UTC && dt <= &DateTime::<Utc>::MAX_UTC)
962}
963
964impl DateTime<FixedOffset> {
965 /// Parses an RFC 2822 date-and-time string into a `DateTime<FixedOffset>` value.
966 ///
967 /// This parses valid RFC 2822 datetime strings (such as `Tue, 1 Jul 2003 10:52:37 +0200`)
968 /// and returns a new [`DateTime`] instance with the parsed timezone as the [`FixedOffset`].
969 ///
970 /// RFC 2822 is the internet message standard that specifies the representation of times in HTTP
971 /// and email headers. It is the 2001 revision of RFC 822, and is itself revised as RFC 5322 in
972 /// 2008.
973 ///
974 /// # Support for the obsolete date format
975 ///
976 /// - A 2-digit year is interpreted to be a year in 1950-2049.
977 /// - The standard allows comments and whitespace between many of the tokens. See [4.3] and
978 /// [Appendix A.5]
979 /// - Single letter 'military' time zone names are parsed as a `-0000` offset.
980 /// They were defined with the wrong sign in RFC 822 and corrected in RFC 2822. But because
981 /// the meaning is now ambiguous, the standard says they should be be considered as `-0000`
982 /// unless there is out-of-band information confirming their meaning.
983 /// The exception is `Z`, which remains identical to `+0000`.
984 ///
985 /// [4.3]: https://www.rfc-editor.org/rfc/rfc2822#section-4.3
986 /// [Appendix A.5]: https://www.rfc-editor.org/rfc/rfc2822#appendix-A.5
987 ///
988 /// # Example
989 ///
990 /// ```
991 /// # use chrono::{DateTime, FixedOffset, TimeZone};
992 /// assert_eq!(
993 /// DateTime::parse_from_rfc2822("Wed, 18 Feb 2015 23:16:09 GMT").unwrap(),
994 /// FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(2015, 2, 18, 23, 16, 9).unwrap()
995 /// );
996 /// ```
997 pub fn parse_from_rfc2822(s: &str) -> ParseResult<DateTime<FixedOffset>> {
998 const ITEMS: &[Item<'static>] = &[Item::Fixed(Fixed::RFC2822)];
999 let mut parsed = Parsed::new();
1000 parse(&mut parsed, s, ITEMS.iter())?;
1001 parsed.to_datetime()
1002 }
1003
1004 /// Parses an RFC 3339 date-and-time string into a `DateTime<FixedOffset>` value.
1005 ///
1006 /// Parses all valid RFC 3339 values (as well as the subset of valid ISO 8601 values that are
1007 /// also valid RFC 3339 date-and-time values) and returns a new [`DateTime`] with a
1008 /// [`FixedOffset`] corresponding to the parsed timezone. While RFC 3339 values come in a wide
1009 /// variety of shapes and sizes, `1996-12-19T16:39:57-08:00` is an example of the most commonly
1010 /// encountered variety of RFC 3339 formats.
1011 ///
1012 /// Why isn't this named `parse_from_iso8601`? That's because ISO 8601 allows representing
1013 /// values in a wide range of formats, only some of which represent actual date-and-time
1014 /// instances (rather than periods, ranges, dates, or times). Some valid ISO 8601 values are
1015 /// also simultaneously valid RFC 3339 values, but not all RFC 3339 values are valid ISO 8601
1016 /// values (or the other way around).
1017 pub fn parse_from_rfc3339(s: &str) -> ParseResult<DateTime<FixedOffset>> {
1018 let mut parsed = Parsed::new();
1019 let (s, _) = parse_rfc3339(&mut parsed, s)?;
1020 if !s.is_empty() {
1021 return Err(TOO_LONG);
1022 }
1023 parsed.to_datetime()
1024 }
1025
1026 /// Parses a string from a user-specified format into a `DateTime<FixedOffset>` value.
1027 ///
1028 /// Note that this method *requires a timezone* in the input string. See
1029 /// [`NaiveDateTime::parse_from_str`](./naive/struct.NaiveDateTime.html#method.parse_from_str)
1030 /// for a version that does not require a timezone in the to-be-parsed str. The returned
1031 /// [`DateTime`] value will have a [`FixedOffset`] reflecting the parsed timezone.
1032 ///
1033 /// See the [`format::strftime` module](./format/strftime/index.html) for supported format
1034 /// sequences.
1035 ///
1036 /// # Example
1037 ///
1038 /// ```rust
1039 /// use chrono::{DateTime, FixedOffset, NaiveDate, TimeZone};
1040 ///
1041 /// let dt = DateTime::parse_from_str("1983 Apr 13 12:09:14.274 +0000", "%Y %b %d %H:%M:%S%.3f %z");
1042 /// assert_eq!(
1043 /// dt,
1044 /// Ok(FixedOffset::east_opt(0)
1045 /// .unwrap()
1046 /// .from_local_datetime(
1047 /// &NaiveDate::from_ymd_opt(1983, 4, 13)
1048 /// .unwrap()
1049 /// .and_hms_milli_opt(12, 9, 14, 274)
1050 /// .unwrap()
1051 /// )
1052 /// .unwrap())
1053 /// );
1054 /// ```
1055 pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<DateTime<FixedOffset>> {
1056 let mut parsed = Parsed::new();
1057 parse(&mut parsed, s, StrftimeItems::new(fmt))?;
1058 parsed.to_datetime()
1059 }
1060
1061 /// Parses a string from a user-specified format into a `DateTime<FixedOffset>` value, and a
1062 /// slice with the remaining portion of the string.
1063 ///
1064 /// Note that this method *requires a timezone* in the input string. See
1065 /// [`NaiveDateTime::parse_and_remainder`] for a version that does not
1066 /// require a timezone in `s`. The returned [`DateTime`] value will have a [`FixedOffset`]
1067 /// reflecting the parsed timezone.
1068 ///
1069 /// See the [`format::strftime` module](./format/strftime/index.html) for supported format
1070 /// sequences.
1071 ///
1072 /// Similar to [`parse_from_str`](#method.parse_from_str).
1073 ///
1074 /// # Example
1075 ///
1076 /// ```rust
1077 /// # use chrono::{DateTime, FixedOffset, TimeZone};
1078 /// let (datetime, remainder) = DateTime::parse_and_remainder(
1079 /// "2015-02-18 23:16:09 +0200 trailing text",
1080 /// "%Y-%m-%d %H:%M:%S %z",
1081 /// )
1082 /// .unwrap();
1083 /// assert_eq!(
1084 /// datetime,
1085 /// FixedOffset::east_opt(2 * 3600).unwrap().with_ymd_and_hms(2015, 2, 18, 23, 16, 9).unwrap()
1086 /// );
1087 /// assert_eq!(remainder, " trailing text");
1088 /// ```
1089 pub fn parse_and_remainder<'a>(
1090 s: &'a str,
1091 fmt: &str,
1092 ) -> ParseResult<(DateTime<FixedOffset>, &'a str)> {
1093 let mut parsed = Parsed::new();
1094 let remainder = parse_and_remainder(&mut parsed, s, StrftimeItems::new(fmt))?;
1095 parsed.to_datetime().map(|d| (d, remainder))
1096 }
1097}
1098
1099impl<Tz: TimeZone> DateTime<Tz>
1100where
1101 Tz::Offset: fmt::Display,
1102{
1103 /// Formats the combined date and time with the specified formatting items.
1104 #[cfg(feature = "alloc")]
1105 #[inline]
1106 #[must_use]
1107 pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
1108 where
1109 I: Iterator<Item = B> + Clone,
1110 B: Borrow<Item<'a>>,
1111 {
1112 let local = self.overflowing_naive_local();
1113 DelayedFormat::new_with_offset(Some(local.date()), Some(local.time()), &self.offset, items)
1114 }
1115
1116 /// Formats the combined date and time per the specified format string.
1117 ///
1118 /// See the [`crate::format::strftime`] module for the supported escape sequences.
1119 ///
1120 /// # Example
1121 /// ```rust
1122 /// use chrono::prelude::*;
1123 ///
1124 /// let date_time: DateTime<Utc> = Utc.with_ymd_and_hms(2017, 04, 02, 12, 50, 32).unwrap();
1125 /// let formatted = format!("{}", date_time.format("%d/%m/%Y %H:%M"));
1126 /// assert_eq!(formatted, "02/04/2017 12:50");
1127 /// ```
1128 #[cfg(feature = "alloc")]
1129 #[inline]
1130 #[must_use]
1131 pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
1132 self.format_with_items(StrftimeItems::new(fmt))
1133 }
1134
1135 /// Formats the combined date and time with the specified formatting items and locale.
1136 #[cfg(all(feature = "unstable-locales", feature = "alloc"))]
1137 #[inline]
1138 #[must_use]
1139 pub fn format_localized_with_items<'a, I, B>(
1140 &self,
1141 items: I,
1142 locale: Locale,
1143 ) -> DelayedFormat<I>
1144 where
1145 I: Iterator<Item = B> + Clone,
1146 B: Borrow<Item<'a>>,
1147 {
1148 let local = self.overflowing_naive_local();
1149 DelayedFormat::new_with_offset_and_locale(
1150 Some(local.date()),
1151 Some(local.time()),
1152 &self.offset,
1153 items,
1154 locale,
1155 )
1156 }
1157
1158 /// Formats the combined date and time per the specified format string and
1159 /// locale.
1160 ///
1161 /// See the [`crate::format::strftime`] module on the supported escape
1162 /// sequences.
1163 #[cfg(all(feature = "unstable-locales", feature = "alloc"))]
1164 #[inline]
1165 #[must_use]
1166 pub fn format_localized<'a>(
1167 &self,
1168 fmt: &'a str,
1169 locale: Locale,
1170 ) -> DelayedFormat<StrftimeItems<'a>> {
1171 self.format_localized_with_items(StrftimeItems::new_with_locale(fmt, locale), locale)
1172 }
1173}
1174
1175impl<Tz: TimeZone> Datelike for DateTime<Tz> {
1176 #[inline]
1177 fn year(&self) -> i32 {
1178 self.overflowing_naive_local().year()
1179 }
1180 #[inline]
1181 fn month(&self) -> u32 {
1182 self.overflowing_naive_local().month()
1183 }
1184 #[inline]
1185 fn month0(&self) -> u32 {
1186 self.overflowing_naive_local().month0()
1187 }
1188 #[inline]
1189 fn day(&self) -> u32 {
1190 self.overflowing_naive_local().day()
1191 }
1192 #[inline]
1193 fn day0(&self) -> u32 {
1194 self.overflowing_naive_local().day0()
1195 }
1196 #[inline]
1197 fn ordinal(&self) -> u32 {
1198 self.overflowing_naive_local().ordinal()
1199 }
1200 #[inline]
1201 fn ordinal0(&self) -> u32 {
1202 self.overflowing_naive_local().ordinal0()
1203 }
1204 #[inline]
1205 fn weekday(&self) -> Weekday {
1206 self.overflowing_naive_local().weekday()
1207 }
1208 #[inline]
1209 fn iso_week(&self) -> IsoWeek {
1210 self.overflowing_naive_local().iso_week()
1211 }
1212
1213 #[inline]
1214 /// Makes a new `DateTime` with the year number changed, while keeping the same month and day.
1215 ///
1216 /// See also the [`NaiveDate::with_year`] method.
1217 ///
1218 /// # Errors
1219 ///
1220 /// Returns `None` if:
1221 /// - The resulting date does not exist (February 29 in a non-leap year).
1222 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1223 /// daylight saving time transition.
1224 /// - The resulting UTC datetime would be out of range.
1225 /// - The resulting local datetime would be out of range (unless the year remains the same).
1226 fn with_year(&self, year: i32) -> Option<DateTime<Tz>> {
1227 map_local(self, |dt| match dt.year() == year {
1228 true => Some(dt),
1229 false => dt.with_year(year),
1230 })
1231 }
1232
1233 /// Makes a new `DateTime` with the month number (starting from 1) changed.
1234 ///
1235 /// Don't combine multiple `Datelike::with_*` methods. The intermediate value may not exist.
1236 ///
1237 /// See also the [`NaiveDate::with_month`] method.
1238 ///
1239 /// # Errors
1240 ///
1241 /// Returns `None` if:
1242 /// - The resulting date does not exist (for example `month(4)` when day of the month is 31).
1243 /// - The value for `month` is invalid.
1244 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1245 /// daylight saving time transition.
1246 #[inline]
1247 fn with_month(&self, month: u32) -> Option<DateTime<Tz>> {
1248 map_local(self, |datetime| datetime.with_month(month))
1249 }
1250
1251 /// Makes a new `DateTime` with the month number (starting from 0) changed.
1252 ///
1253 /// See also the [`NaiveDate::with_month0`] method.
1254 ///
1255 /// # Errors
1256 ///
1257 /// Returns `None` if:
1258 /// - The resulting date does not exist (for example `month0(3)` when day of the month is 31).
1259 /// - The value for `month0` is invalid.
1260 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1261 /// daylight saving time transition.
1262 #[inline]
1263 fn with_month0(&self, month0: u32) -> Option<DateTime<Tz>> {
1264 map_local(self, |datetime| datetime.with_month0(month0))
1265 }
1266
1267 /// Makes a new `DateTime` with the day of month (starting from 1) changed.
1268 ///
1269 /// See also the [`NaiveDate::with_day`] method.
1270 ///
1271 /// # Errors
1272 ///
1273 /// Returns `None` if:
1274 /// - The resulting date does not exist (for example `day(31)` in April).
1275 /// - The value for `day` is invalid.
1276 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1277 /// daylight saving time transition.
1278 #[inline]
1279 fn with_day(&self, day: u32) -> Option<DateTime<Tz>> {
1280 map_local(self, |datetime| datetime.with_day(day))
1281 }
1282
1283 /// Makes a new `DateTime` with the day of month (starting from 0) changed.
1284 ///
1285 /// See also the [`NaiveDate::with_day0`] method.
1286 ///
1287 /// # Errors
1288 ///
1289 /// Returns `None` if:
1290 /// - The resulting date does not exist (for example `day(30)` in April).
1291 /// - The value for `day0` is invalid.
1292 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1293 /// daylight saving time transition.
1294 #[inline]
1295 fn with_day0(&self, day0: u32) -> Option<DateTime<Tz>> {
1296 map_local(self, |datetime| datetime.with_day0(day0))
1297 }
1298
1299 /// Makes a new `DateTime` with the day of year (starting from 1) changed.
1300 ///
1301 /// See also the [`NaiveDate::with_ordinal`] method.
1302 ///
1303 /// # Errors
1304 ///
1305 /// Returns `None` if:
1306 /// - The resulting date does not exist (`with_ordinal(366)` in a non-leap year).
1307 /// - The value for `ordinal` is invalid.
1308 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1309 /// daylight saving time transition.
1310 #[inline]
1311 fn with_ordinal(&self, ordinal: u32) -> Option<DateTime<Tz>> {
1312 map_local(self, |datetime| datetime.with_ordinal(ordinal))
1313 }
1314
1315 /// Makes a new `DateTime` with the day of year (starting from 0) changed.
1316 ///
1317 /// See also the [`NaiveDate::with_ordinal0`] method.
1318 ///
1319 /// # Errors
1320 ///
1321 /// Returns `None` if:
1322 /// - The resulting date does not exist (`with_ordinal0(365)` in a non-leap year).
1323 /// - The value for `ordinal0` is invalid.
1324 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1325 /// daylight saving time transition.
1326 #[inline]
1327 fn with_ordinal0(&self, ordinal0: u32) -> Option<DateTime<Tz>> {
1328 map_local(self, |datetime| datetime.with_ordinal0(ordinal0))
1329 }
1330}
1331
1332impl<Tz: TimeZone> Timelike for DateTime<Tz> {
1333 #[inline]
1334 fn hour(&self) -> u32 {
1335 self.overflowing_naive_local().hour()
1336 }
1337 #[inline]
1338 fn minute(&self) -> u32 {
1339 self.overflowing_naive_local().minute()
1340 }
1341 #[inline]
1342 fn second(&self) -> u32 {
1343 self.overflowing_naive_local().second()
1344 }
1345 #[inline]
1346 fn nanosecond(&self) -> u32 {
1347 self.overflowing_naive_local().nanosecond()
1348 }
1349
1350 /// Makes a new `DateTime` with the hour number changed.
1351 ///
1352 /// See also the [`NaiveTime::with_hour`] method.
1353 ///
1354 /// # Errors
1355 ///
1356 /// Returns `None` if:
1357 /// - The value for `hour` is invalid.
1358 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1359 /// daylight saving time transition.
1360 #[inline]
1361 fn with_hour(&self, hour: u32) -> Option<DateTime<Tz>> {
1362 map_local(self, |datetime| datetime.with_hour(hour))
1363 }
1364
1365 /// Makes a new `DateTime` with the minute number changed.
1366 ///
1367 /// See also the [`NaiveTime::with_minute`] method.
1368 ///
1369 /// # Errors
1370 ///
1371 /// - The value for `minute` is invalid.
1372 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1373 /// daylight saving time transition.
1374 #[inline]
1375 fn with_minute(&self, min: u32) -> Option<DateTime<Tz>> {
1376 map_local(self, |datetime| datetime.with_minute(min))
1377 }
1378
1379 /// Makes a new `DateTime` with the second number changed.
1380 ///
1381 /// As with the [`second`](#method.second) method,
1382 /// the input range is restricted to 0 through 59.
1383 ///
1384 /// See also the [`NaiveTime::with_second`] method.
1385 ///
1386 /// # Errors
1387 ///
1388 /// Returns `None` if:
1389 /// - The value for `second` is invalid.
1390 /// - The local time at the resulting date does not exist or is ambiguous, for example during a
1391 /// daylight saving time transition.
1392 #[inline]
1393 fn with_second(&self, sec: u32) -> Option<DateTime<Tz>> {
1394 map_local(self, |datetime| datetime.with_second(sec))
1395 }
1396
1397 /// Makes a new `DateTime` with nanoseconds since the whole non-leap second changed.
1398 ///
1399 /// Returns `None` when the resulting `NaiveDateTime` would be invalid.
1400 /// As with the [`NaiveDateTime::nanosecond`] method,
1401 /// the input range can exceed 1,000,000,000 for leap seconds.
1402 ///
1403 /// See also the [`NaiveTime::with_nanosecond`] method.
1404 ///
1405 /// # Errors
1406 ///
1407 /// Returns `None` if `nanosecond >= 2,000,000,000`.
1408 #[inline]
1409 fn with_nanosecond(&self, nano: u32) -> Option<DateTime<Tz>> {
1410 map_local(self, |datetime| datetime.with_nanosecond(nano))
1411 }
1412}
1413
1414impl<Tz: TimeZone, Tz2: TimeZone> PartialEq<DateTime<Tz2>> for DateTime<Tz> {
1415 fn eq(&self, other: &DateTime<Tz2>) -> bool {
1416 self.datetime == other.datetime
1417 }
1418}
1419
1420impl<Tz: TimeZone> Eq for DateTime<Tz> {}
1421
1422impl<Tz: TimeZone, Tz2: TimeZone> PartialOrd<DateTime<Tz2>> for DateTime<Tz> {
1423 /// Compare two DateTimes based on their true time, ignoring time zones
1424 ///
1425 /// # Example
1426 ///
1427 /// ```
1428 /// use chrono::prelude::*;
1429 ///
1430 /// let earlier = Utc
1431 /// .with_ymd_and_hms(2015, 5, 15, 2, 0, 0)
1432 /// .unwrap()
1433 /// .with_timezone(&FixedOffset::west_opt(1 * 3600).unwrap());
1434 /// let later = Utc
1435 /// .with_ymd_and_hms(2015, 5, 15, 3, 0, 0)
1436 /// .unwrap()
1437 /// .with_timezone(&FixedOffset::west_opt(5 * 3600).unwrap());
1438 ///
1439 /// assert_eq!(earlier.to_string(), "2015-05-15 01:00:00 -01:00");
1440 /// assert_eq!(later.to_string(), "2015-05-14 22:00:00 -05:00");
1441 ///
1442 /// assert!(later > earlier);
1443 /// ```
1444 fn partial_cmp(&self, other: &DateTime<Tz2>) -> Option<Ordering> {
1445 self.datetime.partial_cmp(&other.datetime)
1446 }
1447}
1448
1449impl<Tz: TimeZone> Ord for DateTime<Tz> {
1450 fn cmp(&self, other: &DateTime<Tz>) -> Ordering {
1451 self.datetime.cmp(&other.datetime)
1452 }
1453}
1454
1455impl<Tz: TimeZone> hash::Hash for DateTime<Tz> {
1456 fn hash<H: hash::Hasher>(&self, state: &mut H) {
1457 self.datetime.hash(state)
1458 }
1459}
1460
1461/// Add `TimeDelta` to `DateTime`.
1462///
1463/// As a part of Chrono's [leap second handling], the addition assumes that **there is no leap
1464/// second ever**, except when the `NaiveDateTime` itself represents a leap second in which case
1465/// the assumption becomes that **there is exactly a single leap second ever**.
1466///
1467/// # Panics
1468///
1469/// Panics if the resulting date would be out of range.
1470/// Consider using [`DateTime<Tz>::checked_add_signed`] to get an `Option` instead.
1471impl<Tz: TimeZone> Add<TimeDelta> for DateTime<Tz> {
1472 type Output = DateTime<Tz>;
1473
1474 #[inline]
1475 fn add(self, rhs: TimeDelta) -> DateTime<Tz> {
1476 self.checked_add_signed(rhs).expect("`DateTime + TimeDelta` overflowed")
1477 }
1478}
1479
1480/// Add `std::time::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> Add<Duration> for DateTime<Tz> {
1491 type Output = DateTime<Tz>;
1492
1493 #[inline]
1494 fn add(self, rhs: Duration) -> DateTime<Tz> {
1495 let rhs = TimeDelta::from_std(rhs)
1496 .expect("overflow converting from core::time::Duration to TimeDelta");
1497 self.checked_add_signed(rhs).expect("`DateTime + TimeDelta` overflowed")
1498 }
1499}
1500
1501/// Add-assign `chrono::Duration` to `DateTime`.
1502///
1503/// As a part of Chrono's [leap second handling], the addition assumes that **there is no leap
1504/// second ever**, except when the `NaiveDateTime` itself represents a leap second in which case
1505/// the assumption becomes that **there is exactly a single leap second ever**.
1506///
1507/// # Panics
1508///
1509/// Panics if the resulting date would be out of range.
1510/// Consider using [`DateTime<Tz>::checked_add_signed`] to get an `Option` instead.
1511impl<Tz: TimeZone> AddAssign<TimeDelta> for DateTime<Tz> {
1512 #[inline]
1513 fn add_assign(&mut self, rhs: TimeDelta) {
1514 let datetime =
1515 self.datetime.checked_add_signed(rhs).expect("`DateTime + TimeDelta` overflowed");
1516 let tz = self.timezone();
1517 *self = tz.from_utc_datetime(&datetime);
1518 }
1519}
1520
1521/// Add-assign `std::time::Duration` to `DateTime`.
1522///
1523/// As a part of Chrono's [leap second handling], the addition assumes that **there is no leap
1524/// second ever**, except when the `NaiveDateTime` itself represents a leap second in which case
1525/// the assumption becomes that **there is exactly a single leap second ever**.
1526///
1527/// # Panics
1528///
1529/// Panics if the resulting date would be out of range.
1530/// Consider using [`DateTime<Tz>::checked_add_signed`] to get an `Option` instead.
1531impl<Tz: TimeZone> AddAssign<Duration> for DateTime<Tz> {
1532 #[inline]
1533 fn add_assign(&mut self, rhs: Duration) {
1534 let rhs = TimeDelta::from_std(rhs)
1535 .expect("overflow converting from core::time::Duration to TimeDelta");
1536 *self += rhs;
1537 }
1538}
1539
1540/// Add `FixedOffset` to the datetime value of `DateTime` (offset remains unchanged).
1541///
1542/// # Panics
1543///
1544/// Panics if the resulting date would be out of range.
1545impl<Tz: TimeZone> Add<FixedOffset> for DateTime<Tz> {
1546 type Output = DateTime<Tz>;
1547
1548 #[inline]
1549 fn add(mut self, rhs: FixedOffset) -> DateTime<Tz> {
1550 self.datetime =
1551 self.naive_utc().checked_add_offset(rhs).expect("`DateTime + FixedOffset` overflowed");
1552 self
1553 }
1554}
1555
1556/// Add `Months` to `DateTime`.
1557///
1558/// The result will be clamped to valid days in the resulting month, see `checked_add_months` for
1559/// details.
1560///
1561/// # Panics
1562///
1563/// Panics if:
1564/// - The resulting date would be out of range.
1565/// - The local time at the resulting date does not exist or is ambiguous, for example during a
1566/// daylight saving time transition.
1567///
1568/// Strongly consider using [`DateTime<Tz>::checked_add_months`] to get an `Option` instead.
1569impl<Tz: TimeZone> Add<Months> for DateTime<Tz> {
1570 type Output = DateTime<Tz>;
1571
1572 fn add(self, rhs: Months) -> Self::Output {
1573 self.checked_add_months(rhs).expect("`DateTime + Months` out of range")
1574 }
1575}
1576
1577/// Subtract `TimeDelta` from `DateTime`.
1578///
1579/// This is the same as the addition with a negated `TimeDelta`.
1580///
1581/// As a part of Chrono's [leap second handling] the subtraction assumes that **there is no leap
1582/// second ever**, except when the `DateTime` itself represents a leap second in which case
1583/// the assumption becomes that **there is exactly a single leap second ever**.
1584///
1585/// # Panics
1586///
1587/// Panics if the resulting date would be out of range.
1588/// Consider using [`DateTime<Tz>::checked_sub_signed`] to get an `Option` instead.
1589impl<Tz: TimeZone> Sub<TimeDelta> for DateTime<Tz> {
1590 type Output = DateTime<Tz>;
1591
1592 #[inline]
1593 fn sub(self, rhs: TimeDelta) -> DateTime<Tz> {
1594 self.checked_sub_signed(rhs).expect("`DateTime - TimeDelta` overflowed")
1595 }
1596}
1597
1598/// Subtract `std::time::Duration` from `DateTime`.
1599///
1600/// As a part of Chrono's [leap second handling] the subtraction assumes that **there is no leap
1601/// second ever**, except when the `DateTime` itself represents a leap second in which case
1602/// the assumption becomes that **there is exactly a single leap second ever**.
1603///
1604/// # Panics
1605///
1606/// Panics if the resulting date would be out of range.
1607/// Consider using [`DateTime<Tz>::checked_sub_signed`] to get an `Option` instead.
1608impl<Tz: TimeZone> Sub<Duration> for DateTime<Tz> {
1609 type Output = DateTime<Tz>;
1610
1611 #[inline]
1612 fn sub(self, rhs: Duration) -> DateTime<Tz> {
1613 let rhs = TimeDelta::from_std(rhs)
1614 .expect("overflow converting from core::time::Duration to TimeDelta");
1615 self.checked_sub_signed(rhs).expect("`DateTime - TimeDelta` overflowed")
1616 }
1617}
1618
1619/// Subtract-assign `TimeDelta` from `DateTime`.
1620///
1621/// This is the same as the addition with a negated `TimeDelta`.
1622///
1623/// As a part of Chrono's [leap second handling], the addition assumes that **there is no leap
1624/// second ever**, except when the `DateTime` itself represents a leap second in which case
1625/// the assumption becomes that **there is exactly a single leap second ever**.
1626///
1627/// # Panics
1628///
1629/// Panics if the resulting date would be out of range.
1630/// Consider using [`DateTime<Tz>::checked_sub_signed`] to get an `Option` instead.
1631impl<Tz: TimeZone> SubAssign<TimeDelta> for DateTime<Tz> {
1632 #[inline]
1633 fn sub_assign(&mut self, rhs: TimeDelta) {
1634 let datetime =
1635 self.datetime.checked_sub_signed(rhs).expect("`DateTime - TimeDelta` overflowed");
1636 let tz = self.timezone();
1637 *self = tz.from_utc_datetime(&datetime)
1638 }
1639}
1640
1641/// Subtract-assign `std::time::Duration` from `DateTime`.
1642///
1643/// As a part of Chrono's [leap second handling], the addition assumes that **there is no leap
1644/// second ever**, except when the `DateTime` itself represents a leap second in which case
1645/// the assumption becomes that **there is exactly a single leap second ever**.
1646///
1647/// # Panics
1648///
1649/// Panics if the resulting date would be out of range.
1650/// Consider using [`DateTime<Tz>::checked_sub_signed`] to get an `Option` instead.
1651impl<Tz: TimeZone> SubAssign<Duration> for DateTime<Tz> {
1652 #[inline]
1653 fn sub_assign(&mut self, rhs: Duration) {
1654 let rhs = TimeDelta::from_std(rhs)
1655 .expect("overflow converting from core::time::Duration to TimeDelta");
1656 *self -= rhs;
1657 }
1658}
1659
1660/// Subtract `FixedOffset` from the datetime value of `DateTime` (offset remains unchanged).
1661///
1662/// # Panics
1663///
1664/// Panics if the resulting date would be out of range.
1665impl<Tz: TimeZone> Sub<FixedOffset> for DateTime<Tz> {
1666 type Output = DateTime<Tz>;
1667
1668 #[inline]
1669 fn sub(mut self, rhs: FixedOffset) -> DateTime<Tz> {
1670 self.datetime =
1671 self.naive_utc().checked_sub_offset(rhs).expect("`DateTime - FixedOffset` overflowed");
1672 self
1673 }
1674}
1675
1676/// Subtract `Months` from `DateTime`.
1677///
1678/// The result will be clamped to valid days in the resulting month, see
1679/// [`DateTime<Tz>::checked_sub_months`] for details.
1680///
1681/// # Panics
1682///
1683/// Panics if:
1684/// - The resulting date would be out of range.
1685/// - The local time at the resulting date does not exist or is ambiguous, for example during a
1686/// daylight saving time transition.
1687///
1688/// Strongly consider using [`DateTime<Tz>::checked_sub_months`] to get an `Option` instead.
1689impl<Tz: TimeZone> Sub<Months> for DateTime<Tz> {
1690 type Output = DateTime<Tz>;
1691
1692 fn sub(self, rhs: Months) -> Self::Output {
1693 self.checked_sub_months(rhs).expect("`DateTime - Months` out of range")
1694 }
1695}
1696
1697impl<Tz: TimeZone> Sub<DateTime<Tz>> for DateTime<Tz> {
1698 type Output = TimeDelta;
1699
1700 #[inline]
1701 fn sub(self, rhs: DateTime<Tz>) -> TimeDelta {
1702 self.signed_duration_since(rhs)
1703 }
1704}
1705
1706impl<Tz: TimeZone> Sub<&DateTime<Tz>> for DateTime<Tz> {
1707 type Output = TimeDelta;
1708
1709 #[inline]
1710 fn sub(self, rhs: &DateTime<Tz>) -> TimeDelta {
1711 self.signed_duration_since(rhs)
1712 }
1713}
1714
1715/// Add `Days` to `NaiveDateTime`.
1716///
1717/// # Panics
1718///
1719/// Panics if:
1720/// - The resulting date would be out of range.
1721/// - The local time at the resulting date does not exist or is ambiguous, for example during a
1722/// daylight saving time transition.
1723///
1724/// Strongly consider using `DateTime<Tz>::checked_sub_days` to get an `Option` instead.
1725impl<Tz: TimeZone> Add<Days> for DateTime<Tz> {
1726 type Output = DateTime<Tz>;
1727
1728 fn add(self, days: Days) -> Self::Output {
1729 self.checked_add_days(days).expect("`DateTime + Days` out of range")
1730 }
1731}
1732
1733/// Subtract `Days` from `DateTime`.
1734///
1735/// # Panics
1736///
1737/// Panics if:
1738/// - The resulting date would be out of range.
1739/// - The local time at the resulting date does not exist or is ambiguous, for example during a
1740/// daylight saving time transition.
1741///
1742/// Strongly consider using `DateTime<Tz>::checked_sub_days` to get an `Option` instead.
1743impl<Tz: TimeZone> Sub<Days> for DateTime<Tz> {
1744 type Output = DateTime<Tz>;
1745
1746 fn sub(self, days: Days) -> Self::Output {
1747 self.checked_sub_days(days).expect("`DateTime - Days` out of range")
1748 }
1749}
1750
1751impl<Tz: TimeZone> fmt::Debug for DateTime<Tz> {
1752 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1753 self.overflowing_naive_local().fmt(f)?;
1754 self.offset.fmt(f)
1755 }
1756}
1757
1758// `fmt::Debug` is hand implemented for the `rkyv::Archive` variant of `DateTime` because
1759// deriving a trait recursively does not propagate trait defined associated types with their own
1760// constraints:
1761// In our case `<<Tz as offset::TimeZone>::Offset as Archive>::Archived`
1762// cannot be formatted using `{:?}` because it doesn't implement `Debug`.
1763// See below for further discussion:
1764// * https://github.com/rust-lang/rust/issues/26925
1765// * https://github.com/rkyv/rkyv/issues/333
1766// * https://github.com/dtolnay/syn/issues/370
1767#[cfg(feature = "rkyv-validation")]
1768impl<Tz: TimeZone> fmt::Debug for ArchivedDateTime<Tz>
1769where
1770 Tz: Archive,
1771 <Tz as Archive>::Archived: fmt::Debug,
1772 <<Tz as TimeZone>::Offset as Archive>::Archived: fmt::Debug,
1773 <Tz as TimeZone>::Offset: fmt::Debug + Archive,
1774{
1775 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1776 f.debug_struct("ArchivedDateTime")
1777 .field("datetime", &self.datetime)
1778 .field("offset", &self.offset)
1779 .finish()
1780 }
1781}
1782
1783impl<Tz: TimeZone> fmt::Display for DateTime<Tz>
1784where
1785 Tz::Offset: fmt::Display,
1786{
1787 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1788 self.overflowing_naive_local().fmt(f)?;
1789 f.write_char(' ')?;
1790 self.offset.fmt(f)
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, Utc};
1801/// "2012-12-12T12:12:12Z".parse::<DateTime<Utc>>()?;
1802/// "2012-12-12 12:12:12Z".parse::<DateTime<Utc>>()?;
1803/// "2012-12-12 12:12:12+0000".parse::<DateTime<Utc>>()?;
1804/// "2012-12-12 12:12:12+00:00".parse::<DateTime<Utc>>()?;
1805/// # Ok::<(), chrono::ParseError>(())
1806/// ```
1807impl str::FromStr for DateTime<Utc> {
1808 type Err = ParseError;
1809
1810 fn from_str(s: &str) -> ParseResult<DateTime<Utc>> {
1811 s.parse::<DateTime<FixedOffset>>().map(|dt| dt.with_timezone(&Utc))
1812 }
1813}
1814
1815/// Accepts a relaxed form of RFC3339.
1816/// A space or a 'T' are accepted as the separator between the date and time
1817/// parts.
1818///
1819/// All of these examples are equivalent:
1820/// ```
1821/// # use chrono::{DateTime, Local};
1822/// "2012-12-12T12:12:12Z".parse::<DateTime<Local>>()?;
1823/// "2012-12-12 12:12:12Z".parse::<DateTime<Local>>()?;
1824/// "2012-12-12 12:12:12+0000".parse::<DateTime<Local>>()?;
1825/// "2012-12-12 12:12:12+00:00".parse::<DateTime<Local>>()?;
1826/// # Ok::<(), chrono::ParseError>(())
1827/// ```
1828#[cfg(feature = "clock")]
1829impl str::FromStr for DateTime<Local> {
1830 type Err = ParseError;
1831
1832 fn from_str(s: &str) -> ParseResult<DateTime<Local>> {
1833 s.parse::<DateTime<FixedOffset>>().map(|dt| dt.with_timezone(&Local))
1834 }
1835}
1836
1837#[cfg(feature = "std")]
1838impl From<SystemTime> for DateTime<Utc> {
1839 fn from(t: SystemTime) -> DateTime<Utc> {
1840 let (sec, nsec) = match t.duration_since(UNIX_EPOCH) {
1841 Ok(dur) => (dur.as_secs() as i64, dur.subsec_nanos()),
1842 Err(e) => {
1843 // unlikely but should be handled
1844 let dur = e.duration();
1845 let (sec, nsec) = (dur.as_secs() as i64, dur.subsec_nanos());
1846 if nsec == 0 {
1847 (-sec, 0)
1848 } else {
1849 (-sec - 1, 1_000_000_000 - nsec)
1850 }
1851 }
1852 };
1853 Utc.timestamp_opt(sec, nsec).unwrap()
1854 }
1855}
1856
1857#[cfg(feature = "clock")]
1858impl From<SystemTime> for DateTime<Local> {
1859 fn from(t: SystemTime) -> DateTime<Local> {
1860 DateTime::<Utc>::from(t).with_timezone(&Local)
1861 }
1862}
1863
1864#[cfg(feature = "std")]
1865impl<Tz: TimeZone> From<DateTime<Tz>> for SystemTime {
1866 fn from(dt: DateTime<Tz>) -> SystemTime {
1867 let sec = dt.timestamp();
1868 let nsec = dt.timestamp_subsec_nanos();
1869 if sec < 0 {
1870 // unlikely but should be handled
1871 UNIX_EPOCH - Duration::new(-sec as u64, 0) + Duration::new(0, nsec)
1872 } else {
1873 UNIX_EPOCH + Duration::new(sec as u64, nsec)
1874 }
1875 }
1876}
1877
1878#[cfg(all(
1879 target_arch = "wasm32",
1880 feature = "wasmbind",
1881 not(any(target_os = "emscripten", target_os = "wasi"))
1882))]
1883impl From<js_sys::Date> for DateTime<Utc> {
1884 fn from(date: js_sys::Date) -> DateTime<Utc> {
1885 DateTime::<Utc>::from(&date)
1886 }
1887}
1888
1889#[cfg(all(
1890 target_arch = "wasm32",
1891 feature = "wasmbind",
1892 not(any(target_os = "emscripten", target_os = "wasi"))
1893))]
1894impl From<&js_sys::Date> for DateTime<Utc> {
1895 fn from(date: &js_sys::Date) -> DateTime<Utc> {
1896 Utc.timestamp_millis_opt(date.get_time() as i64).unwrap()
1897 }
1898}
1899
1900#[cfg(all(
1901 target_arch = "wasm32",
1902 feature = "wasmbind",
1903 not(any(target_os = "emscripten", target_os = "wasi"))
1904))]
1905impl From<DateTime<Utc>> for js_sys::Date {
1906 /// Converts a `DateTime<Utc>` to a JS `Date`. The resulting value may be lossy,
1907 /// any values that have a millisecond timestamp value greater/less than ±8,640,000,000,000,000
1908 /// (April 20, 271821 BCE ~ September 13, 275760 CE) will become invalid dates in JS.
1909 fn from(date: DateTime<Utc>) -> js_sys::Date {
1910 let js_millis = wasm_bindgen::JsValue::from_f64(date.timestamp_millis() as f64);
1911 js_sys::Date::new(&js_millis)
1912 }
1913}
1914
1915// Note that implementation of Arbitrary cannot be simply derived for DateTime<Tz>, due to
1916// the nontrivial bound <Tz as TimeZone>::Offset: Arbitrary.
1917#[cfg(all(feature = "arbitrary", feature = "std"))]
1918impl<'a, Tz> arbitrary::Arbitrary<'a> for DateTime<Tz>
1919where
1920 Tz: TimeZone,
1921 <Tz as TimeZone>::Offset: arbitrary::Arbitrary<'a>,
1922{
1923 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<DateTime<Tz>> {
1924 let datetime = NaiveDateTime::arbitrary(u)?;
1925 let offset = <Tz as TimeZone>::Offset::arbitrary(u)?;
1926 Ok(DateTime::from_naive_utc_and_offset(datetime, offset))
1927 }
1928}
1929
1930/// Number of days between Januari 1, 1970 and December 31, 1 BCE which we define to be day 0.
1931/// 4 full leap year cycles until December 31, 1600 4 * 146097 = 584388
1932/// 1 day until January 1, 1601 1
1933/// 369 years until Januari 1, 1970 369 * 365 = 134685
1934/// of which floor(369 / 4) are leap years floor(369 / 4) = 92
1935/// except for 1700, 1800 and 1900 -3 +
1936/// --------
1937/// 719163
1938const UNIX_EPOCH_DAY: i64 = 719_163;
1939
1940#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))]
1941fn test_encodable_json<FUtc, FFixed, E>(to_string_utc: FUtc, to_string_fixed: FFixed)
1942where
1943 FUtc: Fn(&DateTime<Utc>) -> Result<String, E>,
1944 FFixed: Fn(&DateTime<FixedOffset>) -> Result<String, E>,
1945 E: ::core::fmt::Debug,
1946{
1947 assert_eq!(
1948 to_string_utc(&Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()).ok(),
1949 Some(r#""2014-07-24T12:34:06Z""#.into())
1950 );
1951
1952 assert_eq!(
1953 to_string_fixed(
1954 &FixedOffset::east_opt(3660).unwrap().with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()
1955 )
1956 .ok(),
1957 Some(r#""2014-07-24T12:34:06+01:01""#.into())
1958 );
1959 assert_eq!(
1960 to_string_fixed(
1961 &FixedOffset::east_opt(3650).unwrap().with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()
1962 )
1963 .ok(),
1964 // An offset with seconds is not allowed by RFC 3339, so we round it to the nearest minute.
1965 // In this case `+01:00:50` becomes `+01:01`
1966 Some(r#""2014-07-24T12:34:06+01:01""#.into())
1967 );
1968}
1969
1970#[cfg(all(test, feature = "clock", any(feature = "rustc-serialize", feature = "serde")))]
1971fn test_decodable_json<FUtc, FFixed, FLocal, E>(
1972 utc_from_str: FUtc,
1973 fixed_from_str: FFixed,
1974 local_from_str: FLocal,
1975) where
1976 FUtc: Fn(&str) -> Result<DateTime<Utc>, E>,
1977 FFixed: Fn(&str) -> Result<DateTime<FixedOffset>, E>,
1978 FLocal: Fn(&str) -> Result<DateTime<Local>, E>,
1979 E: ::core::fmt::Debug,
1980{
1981 // should check against the offset as well (the normal DateTime comparison will ignore them)
1982 fn norm<Tz: TimeZone>(dt: &Option<DateTime<Tz>>) -> Option<(&DateTime<Tz>, &Tz::Offset)> {
1983 dt.as_ref().map(|dt| (dt, dt.offset()))
1984 }
1985
1986 assert_eq!(
1987 norm(&utc_from_str(r#""2014-07-24T12:34:06Z""#).ok()),
1988 norm(&Some(Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()))
1989 );
1990 assert_eq!(
1991 norm(&utc_from_str(r#""2014-07-24T13:57:06+01:23""#).ok()),
1992 norm(&Some(Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()))
1993 );
1994
1995 assert_eq!(
1996 norm(&fixed_from_str(r#""2014-07-24T12:34:06Z""#).ok()),
1997 norm(&Some(
1998 FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()
1999 ))
2000 );
2001 assert_eq!(
2002 norm(&fixed_from_str(r#""2014-07-24T13:57:06+01:23""#).ok()),
2003 norm(&Some(
2004 FixedOffset::east_opt(60 * 60 + 23 * 60)
2005 .unwrap()
2006 .with_ymd_and_hms(2014, 7, 24, 13, 57, 6)
2007 .unwrap()
2008 ))
2009 );
2010
2011 // we don't know the exact local offset but we can check that
2012 // the conversion didn't change the instant itself
2013 assert_eq!(
2014 local_from_str(r#""2014-07-24T12:34:06Z""#).expect("local should parse"),
2015 Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()
2016 );
2017 assert_eq!(
2018 local_from_str(r#""2014-07-24T13:57:06+01:23""#).expect("local should parse with offset"),
2019 Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()
2020 );
2021
2022 assert!(utc_from_str(r#""2014-07-32T12:34:06Z""#).is_err());
2023 assert!(fixed_from_str(r#""2014-07-32T12:34:06Z""#).is_err());
2024}
2025
2026#[cfg(all(test, feature = "clock", feature = "rustc-serialize"))]
2027fn test_decodable_json_timestamps<FUtc, FFixed, FLocal, E>(
2028 utc_from_str: FUtc,
2029 fixed_from_str: FFixed,
2030 local_from_str: FLocal,
2031) where
2032 FUtc: Fn(&str) -> Result<rustc_serialize::TsSeconds<Utc>, E>,
2033 FFixed: Fn(&str) -> Result<rustc_serialize::TsSeconds<FixedOffset>, E>,
2034 FLocal: Fn(&str) -> Result<rustc_serialize::TsSeconds<Local>, E>,
2035 E: ::core::fmt::Debug,
2036{
2037 fn norm<Tz: TimeZone>(dt: &Option<DateTime<Tz>>) -> Option<(&DateTime<Tz>, &Tz::Offset)> {
2038 dt.as_ref().map(|dt| (dt, dt.offset()))
2039 }
2040
2041 assert_eq!(
2042 norm(&utc_from_str("0").ok().map(DateTime::from)),
2043 norm(&Some(Utc.with_ymd_and_hms(1970, 1, 1, 0, 0, 0).unwrap()))
2044 );
2045 assert_eq!(
2046 norm(&utc_from_str("-1").ok().map(DateTime::from)),
2047 norm(&Some(Utc.with_ymd_and_hms(1969, 12, 31, 23, 59, 59).unwrap()))
2048 );
2049
2050 assert_eq!(
2051 norm(&fixed_from_str("0").ok().map(DateTime::from)),
2052 norm(&Some(
2053 FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(1970, 1, 1, 0, 0, 0).unwrap()
2054 ))
2055 );
2056 assert_eq!(
2057 norm(&fixed_from_str("-1").ok().map(DateTime::from)),
2058 norm(&Some(
2059 FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(1969, 12, 31, 23, 59, 59).unwrap()
2060 ))
2061 );
2062
2063 assert_eq!(
2064 *fixed_from_str("0").expect("0 timestamp should parse"),
2065 Utc.with_ymd_and_hms(1970, 1, 1, 0, 0, 0).unwrap()
2066 );
2067 assert_eq!(
2068 *local_from_str("-1").expect("-1 timestamp should parse"),
2069 Utc.with_ymd_and_hms(1969, 12, 31, 23, 59, 59).unwrap()
2070 );
2071}