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 use core::cmp::Ordering;
7 use core::ops::{Add, Sub};
8 use core::{fmt, hash, str};
9 use oldtime::Duration as OldDuration;
10 #[cfg(any(feature = "std", test))]
11 use std::time::{SystemTime, UNIX_EPOCH};
12 
13 #[cfg(all(not(feature = "std"), feature = "alloc"))]
14 use alloc::string::{String, ToString};
15 #[cfg(feature = "std")]
16 use std::string::ToString;
17 
18 #[cfg(any(feature = "alloc", feature = "std", test))]
19 use core::borrow::Borrow;
20 #[cfg(any(feature = "alloc", feature = "std", test))]
21 use format::DelayedFormat;
22 #[cfg(feature = "unstable-locales")]
23 use format::Locale;
24 use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems};
25 use format::{Fixed, Item};
26 use naive::{self, IsoWeek, NaiveDateTime, NaiveTime};
27 #[cfg(feature = "clock")]
28 use offset::Local;
29 use offset::{FixedOffset, Offset, TimeZone, Utc};
30 use Date;
31 use {Datelike, Timelike, Weekday};
32 
33 /// Specific formatting options for seconds. This may be extended in the
34 /// future, so exhaustive matching in external code is not recommended.
35 ///
36 /// See the `TimeZone::to_rfc3339_opts` function for usage.
37 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
38 pub enum SecondsFormat {
39     /// Format whole seconds only, with no decimal point nor subseconds.
40     Secs,
41 
42     /// Use fixed 3 subsecond digits. This corresponds to
43     /// [Fixed::Nanosecond3](format/enum.Fixed.html#variant.Nanosecond3).
44     Millis,
45 
46     /// Use fixed 6 subsecond digits. This corresponds to
47     /// [Fixed::Nanosecond6](format/enum.Fixed.html#variant.Nanosecond6).
48     Micros,
49 
50     /// Use fixed 9 subsecond digits. This corresponds to
51     /// [Fixed::Nanosecond9](format/enum.Fixed.html#variant.Nanosecond9).
52     Nanos,
53 
54     /// Automatically select one of `Secs`, `Millis`, `Micros`, or `Nanos` to
55     /// display all available non-zero sub-second digits.  This corresponds to
56     /// [Fixed::Nanosecond](format/enum.Fixed.html#variant.Nanosecond).
57     AutoSi,
58 
59     // Do not match against this.
60     #[doc(hidden)]
61     __NonExhaustive,
62 }
63 
64 /// ISO 8601 combined date and time with time zone.
65 ///
66 /// There are some constructors implemented here (the `from_*` methods), but
67 /// the general-purpose constructors are all via the methods on the
68 /// [`TimeZone`](./offset/trait.TimeZone.html) implementations.
69 #[derive(Clone)]
70 pub struct DateTime<Tz: TimeZone> {
71     datetime: NaiveDateTime,
72     offset: Tz::Offset,
73 }
74 
75 /// The minimum possible `DateTime<Utc>`.
76 pub const MIN_DATETIME: DateTime<Utc> = DateTime { datetime: naive::MIN_DATETIME, offset: Utc };
77 /// The maximum possible `DateTime<Utc>`.
78 pub const MAX_DATETIME: DateTime<Utc> = DateTime { datetime: naive::MAX_DATETIME, offset: Utc };
79 
80 impl<Tz: TimeZone> DateTime<Tz> {
81     /// Makes a new `DateTime` with given *UTC* datetime and offset.
82     /// The local datetime should be constructed via the `TimeZone` trait.
83     ///
84     /// # Example
85     ///
86     /// ~~~~
87     /// use chrono::{DateTime, TimeZone, NaiveDateTime, Utc};
88     ///
89     /// let dt = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(61, 0), Utc);
90     /// assert_eq!(Utc.timestamp(61, 0), dt);
91     /// ~~~~
92     //
93     // note: this constructor is purposely not named to `new` to discourage the direct usage.
94     #[inline]
from_utc(datetime: NaiveDateTime, offset: Tz::Offset) -> DateTime<Tz>95     pub fn from_utc(datetime: NaiveDateTime, offset: Tz::Offset) -> DateTime<Tz> {
96         DateTime { datetime: datetime, offset: offset }
97     }
98 
99     /// Retrieves a date component.
100     #[inline]
date(&self) -> Date<Tz>101     pub fn date(&self) -> Date<Tz> {
102         Date::from_utc(self.naive_local().date(), self.offset.clone())
103     }
104 
105     /// Retrieves a time component.
106     /// Unlike `date`, this is not associated to the time zone.
107     #[inline]
time(&self) -> NaiveTime108     pub fn time(&self) -> NaiveTime {
109         self.datetime.time() + self.offset.fix()
110     }
111 
112     /// Returns the number of non-leap seconds since January 1, 1970 0:00:00 UTC
113     /// (aka "UNIX timestamp").
114     #[inline]
timestamp(&self) -> i64115     pub fn timestamp(&self) -> i64 {
116         self.datetime.timestamp()
117     }
118 
119     /// Returns the number of non-leap-milliseconds since January 1, 1970 UTC
120     ///
121     /// Note that this does reduce the number of years that can be represented
122     /// from ~584 Billion to ~584 Million. (If this is a problem, please file
123     /// an issue to let me know what domain needs millisecond precision over
124     /// billions of years, I'm curious.)
125     ///
126     /// # Example
127     ///
128     /// ~~~~
129     /// use chrono::Utc;
130     /// use chrono::TimeZone;
131     ///
132     /// let dt = Utc.ymd(1970, 1, 1).and_hms_milli(0, 0, 1, 444);
133     /// assert_eq!(dt.timestamp_millis(), 1_444);
134     ///
135     /// let dt = Utc.ymd(2001, 9, 9).and_hms_milli(1, 46, 40, 555);
136     /// assert_eq!(dt.timestamp_millis(), 1_000_000_000_555);
137     /// ~~~~
138     #[inline]
timestamp_millis(&self) -> i64139     pub fn timestamp_millis(&self) -> i64 {
140         self.datetime.timestamp_millis()
141     }
142 
143     /// Returns the number of non-leap-nanoseconds since January 1, 1970 UTC
144     ///
145     /// Note that this does reduce the number of years that can be represented
146     /// from ~584 Billion to ~584. (If this is a problem, please file
147     /// an issue to let me know what domain needs nanosecond precision over
148     /// millennia, I'm curious.)
149     ///
150     /// # Example
151     ///
152     /// ~~~~
153     /// use chrono::Utc;
154     /// use chrono::TimeZone;
155     ///
156     /// let dt = Utc.ymd(1970, 1, 1).and_hms_nano(0, 0, 1, 444);
157     /// assert_eq!(dt.timestamp_nanos(), 1_000_000_444);
158     ///
159     /// let dt = Utc.ymd(2001, 9, 9).and_hms_nano(1, 46, 40, 555);
160     /// assert_eq!(dt.timestamp_nanos(), 1_000_000_000_000_000_555);
161     /// ~~~~
162     #[inline]
timestamp_nanos(&self) -> i64163     pub fn timestamp_nanos(&self) -> i64 {
164         self.datetime.timestamp_nanos()
165     }
166 
167     /// Returns the number of milliseconds since the last second boundary
168     ///
169     /// warning: in event of a leap second, this may exceed 999
170     ///
171     /// note: this is not the number of milliseconds since January 1, 1970 0:00:00 UTC
172     #[inline]
timestamp_subsec_millis(&self) -> u32173     pub fn timestamp_subsec_millis(&self) -> u32 {
174         self.datetime.timestamp_subsec_millis()
175     }
176 
177     /// Returns the number of microseconds since the last second boundary
178     ///
179     /// warning: in event of a leap second, this may exceed 999_999
180     ///
181     /// note: this is not the number of microseconds since January 1, 1970 0:00:00 UTC
182     #[inline]
timestamp_subsec_micros(&self) -> u32183     pub fn timestamp_subsec_micros(&self) -> u32 {
184         self.datetime.timestamp_subsec_micros()
185     }
186 
187     /// Returns the number of nanoseconds since the last second boundary
188     ///
189     /// warning: in event of a leap second, this may exceed 999_999_999
190     ///
191     /// note: this is not the number of nanoseconds since January 1, 1970 0:00:00 UTC
192     #[inline]
timestamp_subsec_nanos(&self) -> u32193     pub fn timestamp_subsec_nanos(&self) -> u32 {
194         self.datetime.timestamp_subsec_nanos()
195     }
196 
197     /// Retrieves an associated offset from UTC.
198     #[inline]
offset(&self) -> &Tz::Offset199     pub fn offset(&self) -> &Tz::Offset {
200         &self.offset
201     }
202 
203     /// Retrieves an associated time zone.
204     #[inline]
timezone(&self) -> Tz205     pub fn timezone(&self) -> Tz {
206         TimeZone::from_offset(&self.offset)
207     }
208 
209     /// Changes the associated time zone.
210     /// This does not change the actual `DateTime` (but will change the string representation).
211     #[inline]
with_timezone<Tz2: TimeZone>(&self, tz: &Tz2) -> DateTime<Tz2>212     pub fn with_timezone<Tz2: TimeZone>(&self, tz: &Tz2) -> DateTime<Tz2> {
213         tz.from_utc_datetime(&self.datetime)
214     }
215 
216     /// Adds given `Duration` to the current date and time.
217     ///
218     /// Returns `None` when it will result in overflow.
219     #[inline]
checked_add_signed(self, rhs: OldDuration) -> Option<DateTime<Tz>>220     pub fn checked_add_signed(self, rhs: OldDuration) -> Option<DateTime<Tz>> {
221         let datetime = try_opt!(self.datetime.checked_add_signed(rhs));
222         let tz = self.timezone();
223         Some(tz.from_utc_datetime(&datetime))
224     }
225 
226     /// Subtracts given `Duration` from the current date and time.
227     ///
228     /// Returns `None` when it will result in overflow.
229     #[inline]
checked_sub_signed(self, rhs: OldDuration) -> Option<DateTime<Tz>>230     pub fn checked_sub_signed(self, rhs: OldDuration) -> Option<DateTime<Tz>> {
231         let datetime = try_opt!(self.datetime.checked_sub_signed(rhs));
232         let tz = self.timezone();
233         Some(tz.from_utc_datetime(&datetime))
234     }
235 
236     /// Subtracts another `DateTime` from the current date and time.
237     /// This does not overflow or underflow at all.
238     #[inline]
signed_duration_since<Tz2: TimeZone>(self, rhs: DateTime<Tz2>) -> OldDuration239     pub fn signed_duration_since<Tz2: TimeZone>(self, rhs: DateTime<Tz2>) -> OldDuration {
240         self.datetime.signed_duration_since(rhs.datetime)
241     }
242 
243     /// Returns a view to the naive UTC datetime.
244     #[inline]
naive_utc(&self) -> NaiveDateTime245     pub fn naive_utc(&self) -> NaiveDateTime {
246         self.datetime
247     }
248 
249     /// Returns a view to the naive local datetime.
250     #[inline]
naive_local(&self) -> NaiveDateTime251     pub fn naive_local(&self) -> NaiveDateTime {
252         self.datetime + self.offset.fix()
253     }
254 }
255 
256 /// Convert a `DateTime<Utc>` instance into a `DateTime<FixedOffset>` instance.
257 impl From<DateTime<Utc>> for DateTime<FixedOffset> {
258     /// Convert this `DateTime<Utc>` instance into a `DateTime<FixedOffset>` instance.
259     ///
260     /// Conversion is done via [`DateTime::with_timezone`]. Note that the converted value returned by
261     /// this will be created with a fixed timezone offset of 0.
from(src: DateTime<Utc>) -> Self262     fn from(src: DateTime<Utc>) -> Self {
263         src.with_timezone(&FixedOffset::east(0))
264     }
265 }
266 
267 /// Convert a `DateTime<Utc>` instance into a `DateTime<Local>` instance.
268 #[cfg(feature = "clock")]
269 impl From<DateTime<Utc>> for DateTime<Local> {
270     /// Convert this `DateTime<Utc>` instance into a `DateTime<Local>` instance.
271     ///
272     /// Conversion is performed via [`DateTime::with_timezone`], accounting for the difference in timezones.
from(src: DateTime<Utc>) -> Self273     fn from(src: DateTime<Utc>) -> Self {
274         src.with_timezone(&Local)
275     }
276 }
277 
278 /// Convert a `DateTime<FixedOffset>` instance into a `DateTime<Utc>` instance.
279 impl From<DateTime<FixedOffset>> for DateTime<Utc> {
280     /// Convert this `DateTime<FixedOffset>` instance into a `DateTime<Utc>` instance.
281     ///
282     /// Conversion is performed via [`DateTime::with_timezone`], accounting for the timezone
283     /// difference.
from(src: DateTime<FixedOffset>) -> Self284     fn from(src: DateTime<FixedOffset>) -> Self {
285         src.with_timezone(&Utc)
286     }
287 }
288 
289 /// Convert a `DateTime<FixedOffset>` instance into a `DateTime<Local>` instance.
290 #[cfg(feature = "clock")]
291 impl From<DateTime<FixedOffset>> for DateTime<Local> {
292     /// Convert this `DateTime<FixedOffset>` instance into a `DateTime<Local>` instance.
293     ///
294     /// Conversion is performed via [`DateTime::with_timezone`]. Returns the equivalent value in local
295     /// time.
from(src: DateTime<FixedOffset>) -> Self296     fn from(src: DateTime<FixedOffset>) -> Self {
297         src.with_timezone(&Local)
298     }
299 }
300 
301 /// Convert a `DateTime<Local>` instance into a `DateTime<Utc>` instance.
302 #[cfg(feature = "clock")]
303 impl From<DateTime<Local>> for DateTime<Utc> {
304     /// Convert this `DateTime<Local>` instance into a `DateTime<Utc>` instance.
305     ///
306     /// Conversion is performed via [`DateTime::with_timezone`], accounting for the difference in
307     /// timezones.
from(src: DateTime<Local>) -> Self308     fn from(src: DateTime<Local>) -> Self {
309         src.with_timezone(&Utc)
310     }
311 }
312 
313 /// Convert a `DateTime<Local>` instance into a `DateTime<FixedOffset>` instance.
314 #[cfg(feature = "clock")]
315 impl From<DateTime<Local>> for DateTime<FixedOffset> {
316     /// Convert this `DateTime<Local>` instance into a `DateTime<FixedOffset>` instance.
317     ///
318     /// Conversion is performed via [`DateTime::with_timezone`]. Note that the converted value returned
319     /// by this will be created with a fixed timezone offset of 0.
from(src: DateTime<Local>) -> Self320     fn from(src: DateTime<Local>) -> Self {
321         src.with_timezone(&FixedOffset::east(0))
322     }
323 }
324 
325 /// Maps the local datetime to other datetime with given conversion function.
map_local<Tz: TimeZone, F>(dt: &DateTime<Tz>, mut f: F) -> Option<DateTime<Tz>> where F: FnMut(NaiveDateTime) -> Option<NaiveDateTime>,326 fn map_local<Tz: TimeZone, F>(dt: &DateTime<Tz>, mut f: F) -> Option<DateTime<Tz>>
327 where
328     F: FnMut(NaiveDateTime) -> Option<NaiveDateTime>,
329 {
330     f(dt.naive_local()).and_then(|datetime| dt.timezone().from_local_datetime(&datetime).single())
331 }
332 
333 impl DateTime<FixedOffset> {
334     /// Parses an RFC 2822 date and time string such as `Tue, 1 Jul 2003 10:52:37 +0200`,
335     /// then returns a new `DateTime` with a parsed `FixedOffset`.
336     ///
337     /// RFC 2822 is the internet message standard that specifices the
338     /// representation of times in HTTP and email headers.
339     ///
340     /// ```
341     /// # use chrono::{DateTime, FixedOffset, TimeZone};
342     /// assert_eq!(
343     ///     DateTime::parse_from_rfc2822("Wed, 18 Feb 2015 23:16:09 GMT").unwrap(),
344     ///     FixedOffset::east(0).ymd(2015, 2, 18).and_hms(23, 16, 9)
345     /// );
346     /// ```
parse_from_rfc2822(s: &str) -> ParseResult<DateTime<FixedOffset>>347     pub fn parse_from_rfc2822(s: &str) -> ParseResult<DateTime<FixedOffset>> {
348         const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC2822)];
349         let mut parsed = Parsed::new();
350         parse(&mut parsed, s, ITEMS.iter())?;
351         parsed.to_datetime()
352     }
353 
354     /// Parses an RFC 3339 and ISO 8601 date and time string such as `1996-12-19T16:39:57-08:00`,
355     /// then returns a new `DateTime` with a parsed `FixedOffset`.
356     ///
357     /// Why isn't this named `parse_from_iso8601`? That's because ISO 8601 allows some freedom
358     /// over the syntax and RFC 3339 exercises that freedom to rigidly define a fixed format.
parse_from_rfc3339(s: &str) -> ParseResult<DateTime<FixedOffset>>359     pub fn parse_from_rfc3339(s: &str) -> ParseResult<DateTime<FixedOffset>> {
360         const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC3339)];
361         let mut parsed = Parsed::new();
362         parse(&mut parsed, s, ITEMS.iter())?;
363         parsed.to_datetime()
364     }
365 
366     /// Parses a string with the specified format string and
367     /// returns a new `DateTime` with a parsed `FixedOffset`.
368     /// See the [`format::strftime` module](./format/strftime/index.html)
369     /// on the supported escape sequences.
370     ///
371     /// See also `Offset::datetime_from_str` which gives a local `DateTime` on specific time zone.
372     ///
373     /// Note that this method *requires a timezone* in the string. See
374     /// [`NaiveDateTime::parse_from_str`](./naive/struct.NaiveDateTime.html#method.parse_from_str)
375     /// for a version that does not require a timezone in the to-be-parsed str.
376     ///
377     /// # Example
378     ///
379     /// ```rust
380     /// use chrono::{DateTime, FixedOffset, TimeZone};
381     ///
382     /// let dt = DateTime::parse_from_str(
383     ///     "1983 Apr 13 12:09:14.274 +0000", "%Y %b %d %H:%M:%S%.3f %z");
384     /// assert_eq!(dt, Ok(FixedOffset::east(0).ymd(1983, 4, 13).and_hms_milli(12, 9, 14, 274)));
385     /// ```
parse_from_str(s: &str, fmt: &str) -> ParseResult<DateTime<FixedOffset>>386     pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<DateTime<FixedOffset>> {
387         let mut parsed = Parsed::new();
388         parse(&mut parsed, s, StrftimeItems::new(fmt))?;
389         parsed.to_datetime()
390     }
391 }
392 
393 impl<Tz: TimeZone> DateTime<Tz>
394 where
395     Tz::Offset: fmt::Display,
396 {
397     /// Returns an RFC 2822 date and time string such as `Tue, 1 Jul 2003 10:52:37 +0200`.
398     #[cfg(any(feature = "alloc", feature = "std", test))]
to_rfc2822(&self) -> String399     pub fn to_rfc2822(&self) -> String {
400         const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC2822)];
401         self.format_with_items(ITEMS.iter()).to_string()
402     }
403 
404     /// Returns an RFC 3339 and ISO 8601 date and time string such as `1996-12-19T16:39:57-08:00`.
405     #[cfg(any(feature = "alloc", feature = "std", test))]
to_rfc3339(&self) -> String406     pub fn to_rfc3339(&self) -> String {
407         const ITEMS: &'static [Item<'static>] = &[Item::Fixed(Fixed::RFC3339)];
408         self.format_with_items(ITEMS.iter()).to_string()
409     }
410 
411     /// Return an RFC 3339 and ISO 8601 date and time string with subseconds
412     /// formatted as per a `SecondsFormat`. If passed `use_z` true and the
413     /// timezone is UTC (offset 0), use 'Z', as per
414     /// [Fixed::TimezoneOffsetColonZ](format/enum.Fixed.html#variant.TimezoneOffsetColonZ).
415     /// If passed `use_z` false, use
416     /// [Fixed::TimezoneOffsetColon](format/enum.Fixed.html#variant.TimezoneOffsetColon).
417     ///
418     /// # Examples
419     ///
420     /// ```rust
421     /// # use chrono::{DateTime, FixedOffset, SecondsFormat, TimeZone, Utc};
422     /// let dt = Utc.ymd(2018, 1, 26).and_hms_micro(18, 30, 9, 453_829);
423     /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Millis, false),
424     ///            "2018-01-26T18:30:09.453+00:00");
425     /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Millis, true),
426     ///            "2018-01-26T18:30:09.453Z");
427     /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Secs, true),
428     ///            "2018-01-26T18:30:09Z");
429     ///
430     /// let pst = FixedOffset::east(8 * 60 * 60);
431     /// let dt = pst.ymd(2018, 1, 26).and_hms_micro(10, 30, 9, 453_829);
432     /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Secs, true),
433     ///            "2018-01-26T10:30:09+08:00");
434     /// ```
435     #[cfg(any(feature = "alloc", feature = "std", test))]
to_rfc3339_opts(&self, secform: SecondsFormat, use_z: bool) -> String436     pub fn to_rfc3339_opts(&self, secform: SecondsFormat, use_z: bool) -> String {
437         use format::Numeric::*;
438         use format::Pad::Zero;
439         use SecondsFormat::*;
440 
441         debug_assert!(secform != __NonExhaustive, "Do not use __NonExhaustive!");
442 
443         const PREFIX: &'static [Item<'static>] = &[
444             Item::Numeric(Year, Zero),
445             Item::Literal("-"),
446             Item::Numeric(Month, Zero),
447             Item::Literal("-"),
448             Item::Numeric(Day, Zero),
449             Item::Literal("T"),
450             Item::Numeric(Hour, Zero),
451             Item::Literal(":"),
452             Item::Numeric(Minute, Zero),
453             Item::Literal(":"),
454             Item::Numeric(Second, Zero),
455         ];
456 
457         let ssitem = match secform {
458             Secs => None,
459             Millis => Some(Item::Fixed(Fixed::Nanosecond3)),
460             Micros => Some(Item::Fixed(Fixed::Nanosecond6)),
461             Nanos => Some(Item::Fixed(Fixed::Nanosecond9)),
462             AutoSi => Some(Item::Fixed(Fixed::Nanosecond)),
463             __NonExhaustive => unreachable!(),
464         };
465 
466         let tzitem = Item::Fixed(if use_z {
467             Fixed::TimezoneOffsetColonZ
468         } else {
469             Fixed::TimezoneOffsetColon
470         });
471 
472         match ssitem {
473             None => self.format_with_items(PREFIX.iter().chain([tzitem].iter())).to_string(),
474             Some(s) => self.format_with_items(PREFIX.iter().chain([s, tzitem].iter())).to_string(),
475         }
476     }
477 
478     /// Formats the combined date and time with the specified formatting items.
479     #[cfg(any(feature = "alloc", feature = "std", test))]
480     #[inline]
format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I> where I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>,481     pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
482     where
483         I: Iterator<Item = B> + Clone,
484         B: Borrow<Item<'a>>,
485     {
486         let local = self.naive_local();
487         DelayedFormat::new_with_offset(Some(local.date()), Some(local.time()), &self.offset, items)
488     }
489 
490     /// Formats the combined date and time with the specified format string.
491     /// See the [`format::strftime` module](./format/strftime/index.html)
492     /// on the supported escape sequences.
493     #[cfg(any(feature = "alloc", feature = "std", test))]
494     #[inline]
format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>>495     pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
496         self.format_with_items(StrftimeItems::new(fmt))
497     }
498 
499     /// Formats the combined date and time with the specified formatting items and locale.
500     #[cfg(feature = "unstable-locales")]
501     #[inline]
format_localized_with_items<'a, I, B>( &self, items: I, locale: Locale, ) -> DelayedFormat<I> where I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>,502     pub fn format_localized_with_items<'a, I, B>(
503         &self,
504         items: I,
505         locale: Locale,
506     ) -> DelayedFormat<I>
507     where
508         I: Iterator<Item = B> + Clone,
509         B: Borrow<Item<'a>>,
510     {
511         let local = self.naive_local();
512         DelayedFormat::new_with_offset_and_locale(
513             Some(local.date()),
514             Some(local.time()),
515             &self.offset,
516             items,
517             locale,
518         )
519     }
520 
521     /// Formats the combined date and time with the specified format string and locale.
522     /// See the [`format::strftime` module](./format/strftime/index.html)
523     /// on the supported escape sequences.
524     #[cfg(feature = "unstable-locales")]
525     #[inline]
format_localized<'a>( &self, fmt: &'a str, locale: Locale, ) -> DelayedFormat<StrftimeItems<'a>>526     pub fn format_localized<'a>(
527         &self,
528         fmt: &'a str,
529         locale: Locale,
530     ) -> DelayedFormat<StrftimeItems<'a>> {
531         self.format_localized_with_items(StrftimeItems::new_with_locale(fmt, locale), locale)
532     }
533 }
534 
535 impl<Tz: TimeZone> Datelike for DateTime<Tz> {
536     #[inline]
year(&self) -> i32537     fn year(&self) -> i32 {
538         self.naive_local().year()
539     }
540     #[inline]
month(&self) -> u32541     fn month(&self) -> u32 {
542         self.naive_local().month()
543     }
544     #[inline]
month0(&self) -> u32545     fn month0(&self) -> u32 {
546         self.naive_local().month0()
547     }
548     #[inline]
day(&self) -> u32549     fn day(&self) -> u32 {
550         self.naive_local().day()
551     }
552     #[inline]
day0(&self) -> u32553     fn day0(&self) -> u32 {
554         self.naive_local().day0()
555     }
556     #[inline]
ordinal(&self) -> u32557     fn ordinal(&self) -> u32 {
558         self.naive_local().ordinal()
559     }
560     #[inline]
ordinal0(&self) -> u32561     fn ordinal0(&self) -> u32 {
562         self.naive_local().ordinal0()
563     }
564     #[inline]
weekday(&self) -> Weekday565     fn weekday(&self) -> Weekday {
566         self.naive_local().weekday()
567     }
568     #[inline]
iso_week(&self) -> IsoWeek569     fn iso_week(&self) -> IsoWeek {
570         self.naive_local().iso_week()
571     }
572 
573     #[inline]
with_year(&self, year: i32) -> Option<DateTime<Tz>>574     fn with_year(&self, year: i32) -> Option<DateTime<Tz>> {
575         map_local(self, |datetime| datetime.with_year(year))
576     }
577 
578     #[inline]
with_month(&self, month: u32) -> Option<DateTime<Tz>>579     fn with_month(&self, month: u32) -> Option<DateTime<Tz>> {
580         map_local(self, |datetime| datetime.with_month(month))
581     }
582 
583     #[inline]
with_month0(&self, month0: u32) -> Option<DateTime<Tz>>584     fn with_month0(&self, month0: u32) -> Option<DateTime<Tz>> {
585         map_local(self, |datetime| datetime.with_month0(month0))
586     }
587 
588     #[inline]
with_day(&self, day: u32) -> Option<DateTime<Tz>>589     fn with_day(&self, day: u32) -> Option<DateTime<Tz>> {
590         map_local(self, |datetime| datetime.with_day(day))
591     }
592 
593     #[inline]
with_day0(&self, day0: u32) -> Option<DateTime<Tz>>594     fn with_day0(&self, day0: u32) -> Option<DateTime<Tz>> {
595         map_local(self, |datetime| datetime.with_day0(day0))
596     }
597 
598     #[inline]
with_ordinal(&self, ordinal: u32) -> Option<DateTime<Tz>>599     fn with_ordinal(&self, ordinal: u32) -> Option<DateTime<Tz>> {
600         map_local(self, |datetime| datetime.with_ordinal(ordinal))
601     }
602 
603     #[inline]
with_ordinal0(&self, ordinal0: u32) -> Option<DateTime<Tz>>604     fn with_ordinal0(&self, ordinal0: u32) -> Option<DateTime<Tz>> {
605         map_local(self, |datetime| datetime.with_ordinal0(ordinal0))
606     }
607 }
608 
609 impl<Tz: TimeZone> Timelike for DateTime<Tz> {
610     #[inline]
hour(&self) -> u32611     fn hour(&self) -> u32 {
612         self.naive_local().hour()
613     }
614     #[inline]
minute(&self) -> u32615     fn minute(&self) -> u32 {
616         self.naive_local().minute()
617     }
618     #[inline]
second(&self) -> u32619     fn second(&self) -> u32 {
620         self.naive_local().second()
621     }
622     #[inline]
nanosecond(&self) -> u32623     fn nanosecond(&self) -> u32 {
624         self.naive_local().nanosecond()
625     }
626 
627     #[inline]
with_hour(&self, hour: u32) -> Option<DateTime<Tz>>628     fn with_hour(&self, hour: u32) -> Option<DateTime<Tz>> {
629         map_local(self, |datetime| datetime.with_hour(hour))
630     }
631 
632     #[inline]
with_minute(&self, min: u32) -> Option<DateTime<Tz>>633     fn with_minute(&self, min: u32) -> Option<DateTime<Tz>> {
634         map_local(self, |datetime| datetime.with_minute(min))
635     }
636 
637     #[inline]
with_second(&self, sec: u32) -> Option<DateTime<Tz>>638     fn with_second(&self, sec: u32) -> Option<DateTime<Tz>> {
639         map_local(self, |datetime| datetime.with_second(sec))
640     }
641 
642     #[inline]
with_nanosecond(&self, nano: u32) -> Option<DateTime<Tz>>643     fn with_nanosecond(&self, nano: u32) -> Option<DateTime<Tz>> {
644         map_local(self, |datetime| datetime.with_nanosecond(nano))
645     }
646 }
647 
648 // we need them as automatic impls cannot handle associated types
649 impl<Tz: TimeZone> Copy for DateTime<Tz> where <Tz as TimeZone>::Offset: Copy {}
650 unsafe impl<Tz: TimeZone> Send for DateTime<Tz> where <Tz as TimeZone>::Offset: Send {}
651 
652 impl<Tz: TimeZone, Tz2: TimeZone> PartialEq<DateTime<Tz2>> for DateTime<Tz> {
eq(&self, other: &DateTime<Tz2>) -> bool653     fn eq(&self, other: &DateTime<Tz2>) -> bool {
654         self.datetime == other.datetime
655     }
656 }
657 
658 impl<Tz: TimeZone> Eq for DateTime<Tz> {}
659 
660 impl<Tz: TimeZone, Tz2: TimeZone> PartialOrd<DateTime<Tz2>> for DateTime<Tz> {
661     /// Compare two DateTimes based on their true time, ignoring time zones
662     ///
663     /// # Example
664     ///
665     /// ```
666     /// use chrono::prelude::*;
667     ///
668     /// let earlier = Utc.ymd(2015, 5, 15).and_hms(2, 0, 0).with_timezone(&FixedOffset::west(1 * 3600));
669     /// let later   = Utc.ymd(2015, 5, 15).and_hms(3, 0, 0).with_timezone(&FixedOffset::west(5 * 3600));
670     ///
671     /// assert_eq!(earlier.to_string(), "2015-05-15 01:00:00 -01:00");
672     /// assert_eq!(later.to_string(), "2015-05-14 22:00:00 -05:00");
673     ///
674     /// assert!(later > earlier);
675     /// ```
partial_cmp(&self, other: &DateTime<Tz2>) -> Option<Ordering>676     fn partial_cmp(&self, other: &DateTime<Tz2>) -> Option<Ordering> {
677         self.datetime.partial_cmp(&other.datetime)
678     }
679 }
680 
681 impl<Tz: TimeZone> Ord for DateTime<Tz> {
cmp(&self, other: &DateTime<Tz>) -> Ordering682     fn cmp(&self, other: &DateTime<Tz>) -> Ordering {
683         self.datetime.cmp(&other.datetime)
684     }
685 }
686 
687 impl<Tz: TimeZone> hash::Hash for DateTime<Tz> {
hash<H: hash::Hasher>(&self, state: &mut H)688     fn hash<H: hash::Hasher>(&self, state: &mut H) {
689         self.datetime.hash(state)
690     }
691 }
692 
693 impl<Tz: TimeZone> Add<OldDuration> for DateTime<Tz> {
694     type Output = DateTime<Tz>;
695 
696     #[inline]
add(self, rhs: OldDuration) -> DateTime<Tz>697     fn add(self, rhs: OldDuration) -> DateTime<Tz> {
698         self.checked_add_signed(rhs).expect("`DateTime + Duration` overflowed")
699     }
700 }
701 
702 impl<Tz: TimeZone> Sub<OldDuration> for DateTime<Tz> {
703     type Output = DateTime<Tz>;
704 
705     #[inline]
sub(self, rhs: OldDuration) -> DateTime<Tz>706     fn sub(self, rhs: OldDuration) -> DateTime<Tz> {
707         self.checked_sub_signed(rhs).expect("`DateTime - Duration` overflowed")
708     }
709 }
710 
711 impl<Tz: TimeZone> Sub<DateTime<Tz>> for DateTime<Tz> {
712     type Output = OldDuration;
713 
714     #[inline]
sub(self, rhs: DateTime<Tz>) -> OldDuration715     fn sub(self, rhs: DateTime<Tz>) -> OldDuration {
716         self.signed_duration_since(rhs)
717     }
718 }
719 
720 impl<Tz: TimeZone> fmt::Debug for DateTime<Tz> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result721     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
722         write!(f, "{:?}{:?}", self.naive_local(), self.offset)
723     }
724 }
725 
726 impl<Tz: TimeZone> fmt::Display for DateTime<Tz>
727 where
728     Tz::Offset: fmt::Display,
729 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result730     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
731         write!(f, "{} {}", self.naive_local(), self.offset)
732     }
733 }
734 
735 impl str::FromStr for DateTime<Utc> {
736     type Err = ParseError;
737 
from_str(s: &str) -> ParseResult<DateTime<Utc>>738     fn from_str(s: &str) -> ParseResult<DateTime<Utc>> {
739         s.parse::<DateTime<FixedOffset>>().map(|dt| dt.with_timezone(&Utc))
740     }
741 }
742 
743 #[cfg(feature = "clock")]
744 impl str::FromStr for DateTime<Local> {
745     type Err = ParseError;
746 
from_str(s: &str) -> ParseResult<DateTime<Local>>747     fn from_str(s: &str) -> ParseResult<DateTime<Local>> {
748         s.parse::<DateTime<FixedOffset>>().map(|dt| dt.with_timezone(&Local))
749     }
750 }
751 
752 #[cfg(any(feature = "std", test))]
753 impl From<SystemTime> for DateTime<Utc> {
from(t: SystemTime) -> DateTime<Utc>754     fn from(t: SystemTime) -> DateTime<Utc> {
755         let (sec, nsec) = match t.duration_since(UNIX_EPOCH) {
756             Ok(dur) => (dur.as_secs() as i64, dur.subsec_nanos()),
757             Err(e) => {
758                 // unlikely but should be handled
759                 let dur = e.duration();
760                 let (sec, nsec) = (dur.as_secs() as i64, dur.subsec_nanos());
761                 if nsec == 0 {
762                     (-sec, 0)
763                 } else {
764                     (-sec - 1, 1_000_000_000 - nsec)
765                 }
766             }
767         };
768         Utc.timestamp(sec, nsec)
769     }
770 }
771 
772 #[cfg(feature = "clock")]
773 impl From<SystemTime> for DateTime<Local> {
from(t: SystemTime) -> DateTime<Local>774     fn from(t: SystemTime) -> DateTime<Local> {
775         DateTime::<Utc>::from(t).with_timezone(&Local)
776     }
777 }
778 
779 #[cfg(any(feature = "std", test))]
780 impl<Tz: TimeZone> From<DateTime<Tz>> for SystemTime {
from(dt: DateTime<Tz>) -> SystemTime781     fn from(dt: DateTime<Tz>) -> SystemTime {
782         use std::time::Duration;
783 
784         let sec = dt.timestamp();
785         let nsec = dt.timestamp_subsec_nanos();
786         if sec < 0 {
787             // unlikely but should be handled
788             UNIX_EPOCH - Duration::new(-sec as u64, 0) + Duration::new(0, nsec)
789         } else {
790             UNIX_EPOCH + Duration::new(sec as u64, nsec)
791         }
792     }
793 }
794 
795 #[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))]
796 impl From<js_sys::Date> for DateTime<Utc> {
from(date: js_sys::Date) -> DateTime<Utc>797     fn from(date: js_sys::Date) -> DateTime<Utc> {
798         DateTime::<Utc>::from(&date)
799     }
800 }
801 
802 #[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))]
803 impl From<&js_sys::Date> for DateTime<Utc> {
from(date: &js_sys::Date) -> DateTime<Utc>804     fn from(date: &js_sys::Date) -> DateTime<Utc> {
805         let millisecs_since_unix_epoch: u64 = date.get_time() as u64;
806         let secs = millisecs_since_unix_epoch / 1000;
807         let nanos = 1_000_000 * (millisecs_since_unix_epoch % 1000);
808         let naive = NaiveDateTime::from_timestamp(secs as i64, nanos as u32);
809         DateTime::from_utc(naive, Utc)
810     }
811 }
812 
813 #[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))]
814 impl From<DateTime<Utc>> for js_sys::Date {
from(date: DateTime<Utc>) -> js_sys::Date815     fn from(date: DateTime<Utc>) -> js_sys::Date {
816         let js_date = js_sys::Date::new_0();
817 
818         js_date.set_utc_full_year_with_month_date(
819             date.year() as u32,
820             date.month0() as i32,
821             date.day() as i32,
822         );
823 
824         js_date.set_utc_hours(date.hour());
825         js_date.set_utc_minutes(date.minute());
826         js_date.set_utc_seconds(date.second());
827 
828         js_date
829     }
830 }
831 
832 #[test]
test_auto_conversion()833 fn test_auto_conversion() {
834     let utc_dt = Utc.ymd(2018, 9, 5).and_hms(23, 58, 0);
835     let cdt_dt = FixedOffset::west(5 * 60 * 60).ymd(2018, 9, 5).and_hms(18, 58, 0);
836     let utc_dt2: DateTime<Utc> = cdt_dt.into();
837     assert_eq!(utc_dt, utc_dt2);
838 }
839 
840 #[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))]
test_encodable_json<FUtc, FFixed, E>(to_string_utc: FUtc, to_string_fixed: FFixed) where FUtc: Fn(&DateTime<Utc>) -> Result<String, E>, FFixed: Fn(&DateTime<FixedOffset>) -> Result<String, E>, E: ::core::fmt::Debug,841 fn test_encodable_json<FUtc, FFixed, E>(to_string_utc: FUtc, to_string_fixed: FFixed)
842 where
843     FUtc: Fn(&DateTime<Utc>) -> Result<String, E>,
844     FFixed: Fn(&DateTime<FixedOffset>) -> Result<String, E>,
845     E: ::core::fmt::Debug,
846 {
847     assert_eq!(
848         to_string_utc(&Utc.ymd(2014, 7, 24).and_hms(12, 34, 6)).ok(),
849         Some(r#""2014-07-24T12:34:06Z""#.into())
850     );
851 
852     assert_eq!(
853         to_string_fixed(&FixedOffset::east(3660).ymd(2014, 7, 24).and_hms(12, 34, 6)).ok(),
854         Some(r#""2014-07-24T12:34:06+01:01""#.into())
855     );
856     assert_eq!(
857         to_string_fixed(&FixedOffset::east(3650).ymd(2014, 7, 24).and_hms(12, 34, 6)).ok(),
858         Some(r#""2014-07-24T12:34:06+01:00:50""#.into())
859     );
860 }
861 
862 #[cfg(all(test, feature = "clock", any(feature = "rustc-serialize", feature = "serde")))]
test_decodable_json<FUtc, FFixed, FLocal, E>( utc_from_str: FUtc, fixed_from_str: FFixed, local_from_str: FLocal, ) where FUtc: Fn(&str) -> Result<DateTime<Utc>, E>, FFixed: Fn(&str) -> Result<DateTime<FixedOffset>, E>, FLocal: Fn(&str) -> Result<DateTime<Local>, E>, E: ::core::fmt::Debug,863 fn test_decodable_json<FUtc, FFixed, FLocal, E>(
864     utc_from_str: FUtc,
865     fixed_from_str: FFixed,
866     local_from_str: FLocal,
867 ) where
868     FUtc: Fn(&str) -> Result<DateTime<Utc>, E>,
869     FFixed: Fn(&str) -> Result<DateTime<FixedOffset>, E>,
870     FLocal: Fn(&str) -> Result<DateTime<Local>, E>,
871     E: ::core::fmt::Debug,
872 {
873     // should check against the offset as well (the normal DateTime comparison will ignore them)
874     fn norm<Tz: TimeZone>(dt: &Option<DateTime<Tz>>) -> Option<(&DateTime<Tz>, &Tz::Offset)> {
875         dt.as_ref().map(|dt| (dt, dt.offset()))
876     }
877 
878     assert_eq!(
879         norm(&utc_from_str(r#""2014-07-24T12:34:06Z""#).ok()),
880         norm(&Some(Utc.ymd(2014, 7, 24).and_hms(12, 34, 6)))
881     );
882     assert_eq!(
883         norm(&utc_from_str(r#""2014-07-24T13:57:06+01:23""#).ok()),
884         norm(&Some(Utc.ymd(2014, 7, 24).and_hms(12, 34, 6)))
885     );
886 
887     assert_eq!(
888         norm(&fixed_from_str(r#""2014-07-24T12:34:06Z""#).ok()),
889         norm(&Some(FixedOffset::east(0).ymd(2014, 7, 24).and_hms(12, 34, 6)))
890     );
891     assert_eq!(
892         norm(&fixed_from_str(r#""2014-07-24T13:57:06+01:23""#).ok()),
893         norm(&Some(FixedOffset::east(60 * 60 + 23 * 60).ymd(2014, 7, 24).and_hms(13, 57, 6)))
894     );
895 
896     // we don't know the exact local offset but we can check that
897     // the conversion didn't change the instant itself
898     assert_eq!(
899         local_from_str(r#""2014-07-24T12:34:06Z""#).expect("local shouuld parse"),
900         Utc.ymd(2014, 7, 24).and_hms(12, 34, 6)
901     );
902     assert_eq!(
903         local_from_str(r#""2014-07-24T13:57:06+01:23""#).expect("local should parse with offset"),
904         Utc.ymd(2014, 7, 24).and_hms(12, 34, 6)
905     );
906 
907     assert!(utc_from_str(r#""2014-07-32T12:34:06Z""#).is_err());
908     assert!(fixed_from_str(r#""2014-07-32T12:34:06Z""#).is_err());
909 }
910 
911 #[cfg(all(test, feature = "clock", feature = "rustc-serialize"))]
test_decodable_json_timestamps<FUtc, FFixed, FLocal, E>( utc_from_str: FUtc, fixed_from_str: FFixed, local_from_str: FLocal, ) where FUtc: Fn(&str) -> Result<rustc_serialize::TsSeconds<Utc>, E>, FFixed: Fn(&str) -> Result<rustc_serialize::TsSeconds<FixedOffset>, E>, FLocal: Fn(&str) -> Result<rustc_serialize::TsSeconds<Local>, E>, E: ::core::fmt::Debug,912 fn test_decodable_json_timestamps<FUtc, FFixed, FLocal, E>(
913     utc_from_str: FUtc,
914     fixed_from_str: FFixed,
915     local_from_str: FLocal,
916 ) where
917     FUtc: Fn(&str) -> Result<rustc_serialize::TsSeconds<Utc>, E>,
918     FFixed: Fn(&str) -> Result<rustc_serialize::TsSeconds<FixedOffset>, E>,
919     FLocal: Fn(&str) -> Result<rustc_serialize::TsSeconds<Local>, E>,
920     E: ::core::fmt::Debug,
921 {
922     fn norm<Tz: TimeZone>(dt: &Option<DateTime<Tz>>) -> Option<(&DateTime<Tz>, &Tz::Offset)> {
923         dt.as_ref().map(|dt| (dt, dt.offset()))
924     }
925 
926     assert_eq!(
927         norm(&utc_from_str("0").ok().map(DateTime::from)),
928         norm(&Some(Utc.ymd(1970, 1, 1).and_hms(0, 0, 0)))
929     );
930     assert_eq!(
931         norm(&utc_from_str("-1").ok().map(DateTime::from)),
932         norm(&Some(Utc.ymd(1969, 12, 31).and_hms(23, 59, 59)))
933     );
934 
935     assert_eq!(
936         norm(&fixed_from_str("0").ok().map(DateTime::from)),
937         norm(&Some(FixedOffset::east(0).ymd(1970, 1, 1).and_hms(0, 0, 0)))
938     );
939     assert_eq!(
940         norm(&fixed_from_str("-1").ok().map(DateTime::from)),
941         norm(&Some(FixedOffset::east(0).ymd(1969, 12, 31).and_hms(23, 59, 59)))
942     );
943 
944     assert_eq!(
945         *fixed_from_str("0").expect("0 timestamp should parse"),
946         Utc.ymd(1970, 1, 1).and_hms(0, 0, 0)
947     );
948     assert_eq!(
949         *local_from_str("-1").expect("-1 timestamp should parse"),
950         Utc.ymd(1969, 12, 31).and_hms(23, 59, 59)
951     );
952 }
953 
954 #[cfg(feature = "rustc-serialize")]
955 pub mod rustc_serialize {
956     use super::DateTime;
957     use core::fmt;
958     use core::ops::Deref;
959     #[cfg(feature = "clock")]
960     use offset::Local;
961     use offset::{FixedOffset, LocalResult, TimeZone, Utc};
962     use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
963 
964     impl<Tz: TimeZone> Encodable for DateTime<Tz> {
encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>965         fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
966             format!("{:?}", self).encode(s)
967         }
968     }
969 
970     // lik? function to convert a LocalResult into a serde-ish Result
from<T, D>(me: LocalResult<T>, d: &mut D) -> Result<T, D::Error> where D: Decoder, T: fmt::Display,971     fn from<T, D>(me: LocalResult<T>, d: &mut D) -> Result<T, D::Error>
972     where
973         D: Decoder,
974         T: fmt::Display,
975     {
976         match me {
977             LocalResult::None => Err(d.error("value is not a legal timestamp")),
978             LocalResult::Ambiguous(..) => Err(d.error("value is an ambiguous timestamp")),
979             LocalResult::Single(val) => Ok(val),
980         }
981     }
982 
983     impl Decodable for DateTime<FixedOffset> {
decode<D: Decoder>(d: &mut D) -> Result<DateTime<FixedOffset>, D::Error>984         fn decode<D: Decoder>(d: &mut D) -> Result<DateTime<FixedOffset>, D::Error> {
985             d.read_str()?
986                 .parse::<DateTime<FixedOffset>>()
987                 .map_err(|_| d.error("invalid date and time"))
988         }
989     }
990 
991     #[allow(deprecated)]
992     impl Decodable for TsSeconds<FixedOffset> {
993         #[allow(deprecated)]
decode<D: Decoder>(d: &mut D) -> Result<TsSeconds<FixedOffset>, D::Error>994         fn decode<D: Decoder>(d: &mut D) -> Result<TsSeconds<FixedOffset>, D::Error> {
995             from(FixedOffset::east(0).timestamp_opt(d.read_i64()?, 0), d).map(TsSeconds)
996         }
997     }
998 
999     impl Decodable for DateTime<Utc> {
decode<D: Decoder>(d: &mut D) -> Result<DateTime<Utc>, D::Error>1000         fn decode<D: Decoder>(d: &mut D) -> Result<DateTime<Utc>, D::Error> {
1001             d.read_str()?
1002                 .parse::<DateTime<FixedOffset>>()
1003                 .map(|dt| dt.with_timezone(&Utc))
1004                 .map_err(|_| d.error("invalid date and time"))
1005         }
1006     }
1007 
1008     /// A `DateTime` that can be deserialized from a timestamp
1009     ///
1010     /// A timestamp here is seconds since the epoch
1011     #[derive(Debug)]
1012     pub struct TsSeconds<Tz: TimeZone>(DateTime<Tz>);
1013 
1014     #[allow(deprecated)]
1015     impl<Tz: TimeZone> From<TsSeconds<Tz>> for DateTime<Tz> {
1016         /// Pull the inner DateTime<Tz> out
1017         #[allow(deprecated)]
from(obj: TsSeconds<Tz>) -> DateTime<Tz>1018         fn from(obj: TsSeconds<Tz>) -> DateTime<Tz> {
1019             obj.0
1020         }
1021     }
1022 
1023     #[allow(deprecated)]
1024     impl<Tz: TimeZone> Deref for TsSeconds<Tz> {
1025         type Target = DateTime<Tz>;
1026 
deref(&self) -> &Self::Target1027         fn deref(&self) -> &Self::Target {
1028             &self.0
1029         }
1030     }
1031 
1032     #[allow(deprecated)]
1033     impl Decodable for TsSeconds<Utc> {
decode<D: Decoder>(d: &mut D) -> Result<TsSeconds<Utc>, D::Error>1034         fn decode<D: Decoder>(d: &mut D) -> Result<TsSeconds<Utc>, D::Error> {
1035             from(Utc.timestamp_opt(d.read_i64()?, 0), d).map(TsSeconds)
1036         }
1037     }
1038 
1039     #[cfg(feature = "clock")]
1040     impl Decodable for DateTime<Local> {
decode<D: Decoder>(d: &mut D) -> Result<DateTime<Local>, D::Error>1041         fn decode<D: Decoder>(d: &mut D) -> Result<DateTime<Local>, D::Error> {
1042             match d.read_str()?.parse::<DateTime<FixedOffset>>() {
1043                 Ok(dt) => Ok(dt.with_timezone(&Local)),
1044                 Err(_) => Err(d.error("invalid date and time")),
1045             }
1046         }
1047     }
1048 
1049     #[cfg(feature = "clock")]
1050     #[allow(deprecated)]
1051     impl Decodable for TsSeconds<Local> {
1052         #[allow(deprecated)]
decode<D: Decoder>(d: &mut D) -> Result<TsSeconds<Local>, D::Error>1053         fn decode<D: Decoder>(d: &mut D) -> Result<TsSeconds<Local>, D::Error> {
1054             from(Utc.timestamp_opt(d.read_i64()?, 0), d)
1055                 .map(|dt| TsSeconds(dt.with_timezone(&Local)))
1056         }
1057     }
1058 
1059     #[cfg(test)]
1060     use rustc_serialize::json;
1061 
1062     #[test]
test_encodable()1063     fn test_encodable() {
1064         super::test_encodable_json(json::encode, json::encode);
1065     }
1066 
1067     #[cfg(feature = "clock")]
1068     #[test]
test_decodable()1069     fn test_decodable() {
1070         super::test_decodable_json(json::decode, json::decode, json::decode);
1071     }
1072 
1073     #[cfg(feature = "clock")]
1074     #[test]
test_decodable_timestamps()1075     fn test_decodable_timestamps() {
1076         super::test_decodable_json_timestamps(json::decode, json::decode, json::decode);
1077     }
1078 }
1079 
1080 /// documented at re-export site
1081 #[cfg(feature = "serde")]
1082 pub mod serde {
1083     use super::DateTime;
1084     use core::fmt;
1085     #[cfg(feature = "clock")]
1086     use offset::Local;
1087     use offset::{FixedOffset, LocalResult, TimeZone, Utc};
1088     use serdelib::{de, ser};
1089     use {ne_timestamp, SerdeError};
1090 
1091     #[doc(hidden)]
1092     #[derive(Debug)]
1093     pub struct SecondsTimestampVisitor;
1094 
1095     #[doc(hidden)]
1096     #[derive(Debug)]
1097     pub struct NanoSecondsTimestampVisitor;
1098 
1099     #[doc(hidden)]
1100     #[derive(Debug)]
1101     pub struct MilliSecondsTimestampVisitor;
1102 
1103     // lik? function to convert a LocalResult into a serde-ish Result
serde_from<T, E, V>(me: LocalResult<T>, ts: &V) -> Result<T, E> where E: de::Error, V: fmt::Display, T: fmt::Display,1104     fn serde_from<T, E, V>(me: LocalResult<T>, ts: &V) -> Result<T, E>
1105     where
1106         E: de::Error,
1107         V: fmt::Display,
1108         T: fmt::Display,
1109     {
1110         match me {
1111             LocalResult::None => Err(E::custom(ne_timestamp(ts))),
1112             LocalResult::Ambiguous(min, max) => {
1113                 Err(E::custom(SerdeError::Ambiguous { timestamp: ts, min: min, max: max }))
1114             }
1115             LocalResult::Single(val) => Ok(val),
1116         }
1117     }
1118 
1119     /// Ser/de to/from timestamps in nanoseconds
1120     ///
1121     /// Intended for use with `serde`'s `with` attribute.
1122     ///
1123     /// # Example:
1124     ///
1125     /// ```rust
1126     /// # // We mark this ignored so that we can test on 1.13 (which does not
1127     /// # // support custom derive), and run tests with --ignored on beta and
1128     /// # // nightly to actually trigger these.
1129     /// #
1130     /// # #[macro_use] extern crate serde_derive;
1131     /// # #[macro_use] extern crate serde_json;
1132     /// # extern crate chrono;
1133     /// # use chrono::{TimeZone, DateTime, Utc};
1134     /// use chrono::serde::ts_nanoseconds;
1135     /// #[derive(Deserialize, Serialize)]
1136     /// struct S {
1137     ///     #[serde(with = "ts_nanoseconds")]
1138     ///     time: DateTime<Utc>
1139     /// }
1140     ///
1141     /// # fn example() -> Result<S, serde_json::Error> {
1142     /// let time = Utc.ymd(2018, 5, 17).and_hms_nano(02, 04, 59, 918355733);
1143     /// let my_s = S {
1144     ///     time: time.clone(),
1145     /// };
1146     ///
1147     /// let as_string = serde_json::to_string(&my_s)?;
1148     /// assert_eq!(as_string, r#"{"time":1526522699918355733}"#);
1149     /// let my_s: S = serde_json::from_str(&as_string)?;
1150     /// assert_eq!(my_s.time, time);
1151     /// # Ok(my_s)
1152     /// # }
1153     /// # fn main() { example().unwrap(); }
1154     /// ```
1155     pub mod ts_nanoseconds {
1156         use core::fmt;
1157         use serdelib::{de, ser};
1158 
1159         use offset::TimeZone;
1160         use {DateTime, Utc};
1161 
1162         use super::{serde_from, NanoSecondsTimestampVisitor};
1163 
1164         /// Serialize a UTC datetime into an integer number of nanoseconds since the epoch
1165         ///
1166         /// Intended for use with `serde`s `serialize_with` attribute.
1167         ///
1168         /// # Example:
1169         ///
1170         /// ```rust
1171         /// # // We mark this ignored so that we can test on 1.13 (which does not
1172         /// # // support custom derive), and run tests with --ignored on beta and
1173         /// # // nightly to actually trigger these.
1174         /// #
1175         /// # #[macro_use] extern crate serde_derive;
1176         /// # #[macro_use] extern crate serde_json;
1177         /// # extern crate chrono;
1178         /// # use chrono::{TimeZone, DateTime, Utc};
1179         /// use chrono::serde::ts_nanoseconds::serialize as to_nano_ts;
1180         /// #[derive(Serialize)]
1181         /// struct S {
1182         ///     #[serde(serialize_with = "to_nano_ts")]
1183         ///     time: DateTime<Utc>
1184         /// }
1185         ///
1186         /// # fn example() -> Result<String, serde_json::Error> {
1187         /// let my_s = S {
1188         ///     time: Utc.ymd(2018, 5, 17).and_hms_nano(02, 04, 59, 918355733),
1189         /// };
1190         /// let as_string = serde_json::to_string(&my_s)?;
1191         /// assert_eq!(as_string, r#"{"time":1526522699918355733}"#);
1192         /// # Ok(as_string)
1193         /// # }
1194         /// # fn main() { example().unwrap(); }
1195         /// ```
serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error> where S: ser::Serializer,1196         pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
1197         where
1198             S: ser::Serializer,
1199         {
1200             serializer.serialize_i64(dt.timestamp_nanos())
1201         }
1202 
1203         /// Deserialize a `DateTime` from a nanosecond timestamp
1204         ///
1205         /// Intended for use with `serde`s `deserialize_with` attribute.
1206         ///
1207         /// # Example:
1208         ///
1209         /// ```rust
1210         /// # // We mark this ignored so that we can test on 1.13 (which does not
1211         /// # // support custom derive), and run tests with --ignored on beta and
1212         /// # // nightly to actually trigger these.
1213         /// #
1214         /// # #[macro_use] extern crate serde_derive;
1215         /// # #[macro_use] extern crate serde_json;
1216         /// # extern crate chrono;
1217         /// # use chrono::{DateTime, Utc};
1218         /// use chrono::serde::ts_nanoseconds::deserialize as from_nano_ts;
1219         /// #[derive(Deserialize)]
1220         /// struct S {
1221         ///     #[serde(deserialize_with = "from_nano_ts")]
1222         ///     time: DateTime<Utc>
1223         /// }
1224         ///
1225         /// # fn example() -> Result<S, serde_json::Error> {
1226         /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355733 }"#)?;
1227         /// # Ok(my_s)
1228         /// # }
1229         /// # fn main() { example().unwrap(); }
1230         /// ```
deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error> where D: de::Deserializer<'de>,1231         pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
1232         where
1233             D: de::Deserializer<'de>,
1234         {
1235             Ok(d.deserialize_i64(NanoSecondsTimestampVisitor)?)
1236         }
1237 
1238         impl<'de> de::Visitor<'de> for NanoSecondsTimestampVisitor {
1239             type Value = DateTime<Utc>;
1240 
expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result1241             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1242                 write!(formatter, "a unix timestamp in nanoseconds")
1243             }
1244 
1245             /// Deserialize a timestamp in nanoseconds since the epoch
visit_i64<E>(self, value: i64) -> Result<DateTime<Utc>, E> where E: de::Error,1246             fn visit_i64<E>(self, value: i64) -> Result<DateTime<Utc>, E>
1247             where
1248                 E: de::Error,
1249             {
1250                 serde_from(
1251                     Utc.timestamp_opt(value / 1_000_000_000, (value % 1_000_000_000) as u32),
1252                     &value,
1253                 )
1254             }
1255 
1256             /// Deserialize a timestamp in nanoseconds since the epoch
visit_u64<E>(self, value: u64) -> Result<DateTime<Utc>, E> where E: de::Error,1257             fn visit_u64<E>(self, value: u64) -> Result<DateTime<Utc>, E>
1258             where
1259                 E: de::Error,
1260             {
1261                 serde_from(
1262                     Utc.timestamp_opt(
1263                         (value / 1_000_000_000) as i64,
1264                         (value % 1_000_000_000) as u32,
1265                     ),
1266                     &value,
1267                 )
1268             }
1269         }
1270     }
1271 
1272     /// Ser/de to/from optional timestamps in nanoseconds
1273     ///
1274     /// Intended for use with `serde`'s `with` attribute.
1275     ///
1276     /// # Example:
1277     ///
1278     /// ```rust
1279     /// # // We mark this ignored so that we can test on 1.13 (which does not
1280     /// # // support custom derive), and run tests with --ignored on beta and
1281     /// # // nightly to actually trigger these.
1282     /// #
1283     /// # #[macro_use] extern crate serde_derive;
1284     /// # #[macro_use] extern crate serde_json;
1285     /// # extern crate chrono;
1286     /// # use chrono::{TimeZone, DateTime, Utc};
1287     /// use chrono::serde::ts_nanoseconds_option;
1288     /// #[derive(Deserialize, Serialize)]
1289     /// struct S {
1290     ///     #[serde(with = "ts_nanoseconds_option")]
1291     ///     time: Option<DateTime<Utc>>
1292     /// }
1293     ///
1294     /// # fn example() -> Result<S, serde_json::Error> {
1295     /// let time = Some(Utc.ymd(2018, 5, 17).and_hms_nano(02, 04, 59, 918355733));
1296     /// let my_s = S {
1297     ///     time: time.clone(),
1298     /// };
1299     ///
1300     /// let as_string = serde_json::to_string(&my_s)?;
1301     /// assert_eq!(as_string, r#"{"time":1526522699918355733}"#);
1302     /// let my_s: S = serde_json::from_str(&as_string)?;
1303     /// assert_eq!(my_s.time, time);
1304     /// # Ok(my_s)
1305     /// # }
1306     /// # fn main() { example().unwrap(); }
1307     /// ```
1308     pub mod ts_nanoseconds_option {
1309         use core::fmt;
1310         use serdelib::{de, ser};
1311 
1312         use {DateTime, Utc};
1313 
1314         use super::NanoSecondsTimestampVisitor;
1315 
1316         /// Serialize a UTC datetime into an integer number of nanoseconds since the epoch or none
1317         ///
1318         /// Intended for use with `serde`s `serialize_with` attribute.
1319         ///
1320         /// # Example:
1321         ///
1322         /// ```rust
1323         /// # // We mark this ignored so that we can test on 1.13 (which does not
1324         /// # // support custom derive), and run tests with --ignored on beta and
1325         /// # // nightly to actually trigger these.
1326         /// #
1327         /// # #[macro_use] extern crate serde_derive;
1328         /// # #[macro_use] extern crate serde_json;
1329         /// # extern crate chrono;
1330         /// # use chrono::{TimeZone, DateTime, Utc};
1331         /// use chrono::serde::ts_nanoseconds_option::serialize as to_nano_tsopt;
1332         /// #[derive(Serialize)]
1333         /// struct S {
1334         ///     #[serde(serialize_with = "to_nano_tsopt")]
1335         ///     time: Option<DateTime<Utc>>
1336         /// }
1337         ///
1338         /// # fn example() -> Result<String, serde_json::Error> {
1339         /// let my_s = S {
1340         ///     time: Some(Utc.ymd(2018, 5, 17).and_hms_nano(02, 04, 59, 918355733)),
1341         /// };
1342         /// let as_string = serde_json::to_string(&my_s)?;
1343         /// assert_eq!(as_string, r#"{"time":1526522699918355733}"#);
1344         /// # Ok(as_string)
1345         /// # }
1346         /// # fn main() { example().unwrap(); }
1347         /// ```
serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error> where S: ser::Serializer,1348         pub fn serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
1349         where
1350             S: ser::Serializer,
1351         {
1352             match *opt {
1353                 Some(ref dt) => serializer.serialize_some(&dt.timestamp_nanos()),
1354                 None => serializer.serialize_none(),
1355             }
1356         }
1357 
1358         /// Deserialize a `DateTime` from a nanosecond timestamp or none
1359         ///
1360         /// Intended for use with `serde`s `deserialize_with` attribute.
1361         ///
1362         /// # Example:
1363         ///
1364         /// ```rust
1365         /// # // We mark this ignored so that we can test on 1.13 (which does not
1366         /// # // support custom derive), and run tests with --ignored on beta and
1367         /// # // nightly to actually trigger these.
1368         /// #
1369         /// # #[macro_use] extern crate serde_derive;
1370         /// # #[macro_use] extern crate serde_json;
1371         /// # extern crate chrono;
1372         /// # use chrono::{DateTime, Utc};
1373         /// use chrono::serde::ts_nanoseconds_option::deserialize as from_nano_tsopt;
1374         /// #[derive(Deserialize)]
1375         /// struct S {
1376         ///     #[serde(deserialize_with = "from_nano_tsopt")]
1377         ///     time: Option<DateTime<Utc>>
1378         /// }
1379         ///
1380         /// # fn example() -> Result<S, serde_json::Error> {
1381         /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355733 }"#)?;
1382         /// # Ok(my_s)
1383         /// # }
1384         /// # fn main() { example().unwrap(); }
1385         /// ```
deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error> where D: de::Deserializer<'de>,1386         pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
1387         where
1388             D: de::Deserializer<'de>,
1389         {
1390             Ok(d.deserialize_option(OptionNanoSecondsTimestampVisitor)?)
1391         }
1392 
1393         struct OptionNanoSecondsTimestampVisitor;
1394 
1395         impl<'de> de::Visitor<'de> for OptionNanoSecondsTimestampVisitor {
1396             type Value = Option<DateTime<Utc>>;
1397 
expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result1398             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1399                 formatter.write_str("a unix timestamp in nanoseconds or none")
1400             }
1401 
1402             /// Deserialize a timestamp in seconds since the epoch
visit_some<D>(self, d: D) -> Result<Option<DateTime<Utc>>, D::Error> where D: de::Deserializer<'de>,1403             fn visit_some<D>(self, d: D) -> Result<Option<DateTime<Utc>>, D::Error>
1404             where
1405                 D: de::Deserializer<'de>,
1406             {
1407                 d.deserialize_i64(NanoSecondsTimestampVisitor).map(Some)
1408             }
1409 
1410             /// Deserialize a timestamp in seconds since the epoch
visit_none<E>(self) -> Result<Option<DateTime<Utc>>, E> where E: de::Error,1411             fn visit_none<E>(self) -> Result<Option<DateTime<Utc>>, E>
1412             where
1413                 E: de::Error,
1414             {
1415                 Ok(None)
1416             }
1417 
1418             /// Deserialize a timestamp in seconds since the epoch
visit_unit<E>(self) -> Result<Option<DateTime<Utc>>, E> where E: de::Error,1419             fn visit_unit<E>(self) -> Result<Option<DateTime<Utc>>, E>
1420             where
1421                 E: de::Error,
1422             {
1423                 Ok(None)
1424             }
1425         }
1426     }
1427 
1428     /// Ser/de to/from timestamps in milliseconds
1429     ///
1430     /// Intended for use with `serde`s `with` attribute.
1431     ///
1432     /// # Example
1433     ///
1434     /// ```rust
1435     /// # // We mark this ignored so that we can test on 1.13 (which does not
1436     /// # // support custom derive), and run tests with --ignored on beta and
1437     /// # // nightly to actually trigger these.
1438     /// #
1439     /// # #[macro_use] extern crate serde_derive;
1440     /// # #[macro_use] extern crate serde_json;
1441     /// # extern crate chrono;
1442     /// # use chrono::{TimeZone, DateTime, Utc};
1443     /// use chrono::serde::ts_milliseconds;
1444     /// #[derive(Deserialize, Serialize)]
1445     /// struct S {
1446     ///     #[serde(with = "ts_milliseconds")]
1447     ///     time: DateTime<Utc>
1448     /// }
1449     ///
1450     /// # fn example() -> Result<S, serde_json::Error> {
1451     /// let time = Utc.ymd(2018, 5, 17).and_hms_milli(02, 04, 59, 918);
1452     /// let my_s = S {
1453     ///     time: time.clone(),
1454     /// };
1455     ///
1456     /// let as_string = serde_json::to_string(&my_s)?;
1457     /// assert_eq!(as_string, r#"{"time":1526522699918}"#);
1458     /// let my_s: S = serde_json::from_str(&as_string)?;
1459     /// assert_eq!(my_s.time, time);
1460     /// # Ok(my_s)
1461     /// # }
1462     /// # fn main() { example().unwrap(); }
1463     /// ```
1464     pub mod ts_milliseconds {
1465         use core::fmt;
1466         use serdelib::{de, ser};
1467 
1468         use offset::TimeZone;
1469         use {DateTime, Utc};
1470 
1471         use super::{serde_from, MilliSecondsTimestampVisitor};
1472 
1473         /// Serialize a UTC datetime into an integer number of milliseconds since the epoch
1474         ///
1475         /// Intended for use with `serde`s `serialize_with` attribute.
1476         ///
1477         /// # Example:
1478         ///
1479         /// ```rust
1480         /// # // We mark this ignored so that we can test on 1.13 (which does not
1481         /// # // support custom derive), and run tests with --ignored on beta and
1482         /// # // nightly to actually trigger these.
1483         /// #
1484         /// # #[macro_use] extern crate serde_derive;
1485         /// # #[macro_use] extern crate serde_json;
1486         /// # extern crate chrono;
1487         /// # use chrono::{TimeZone, DateTime, Utc};
1488         /// use chrono::serde::ts_milliseconds::serialize as to_milli_ts;
1489         /// #[derive(Serialize)]
1490         /// struct S {
1491         ///     #[serde(serialize_with = "to_milli_ts")]
1492         ///     time: DateTime<Utc>
1493         /// }
1494         ///
1495         /// # fn example() -> Result<String, serde_json::Error> {
1496         /// let my_s = S {
1497         ///     time: Utc.ymd(2018, 5, 17).and_hms_milli(02, 04, 59, 918),
1498         /// };
1499         /// let as_string = serde_json::to_string(&my_s)?;
1500         /// assert_eq!(as_string, r#"{"time":1526522699918}"#);
1501         /// # Ok(as_string)
1502         /// # }
1503         /// # fn main() { example().unwrap(); }
1504         /// ```
serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error> where S: ser::Serializer,1505         pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
1506         where
1507             S: ser::Serializer,
1508         {
1509             serializer.serialize_i64(dt.timestamp_millis())
1510         }
1511 
1512         /// Deserialize a `DateTime` from a millisecond timestamp
1513         ///
1514         /// Intended for use with `serde`s `deserialize_with` attribute.
1515         ///
1516         /// # Example:
1517         ///
1518         /// ```rust
1519         /// # // We mark this ignored so that we can test on 1.13 (which does not
1520         /// # // support custom derive), and run tests with --ignored on beta and
1521         /// # // nightly to actually trigger these.
1522         /// #
1523         /// # #[macro_use] extern crate serde_derive;
1524         /// # #[macro_use] extern crate serde_json;
1525         /// # extern crate chrono;
1526         /// # use chrono::{DateTime, Utc};
1527         /// use chrono::serde::ts_milliseconds::deserialize as from_milli_ts;
1528         /// #[derive(Deserialize)]
1529         /// struct S {
1530         ///     #[serde(deserialize_with = "from_milli_ts")]
1531         ///     time: DateTime<Utc>
1532         /// }
1533         ///
1534         /// # fn example() -> Result<S, serde_json::Error> {
1535         /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918 }"#)?;
1536         /// # Ok(my_s)
1537         /// # }
1538         /// # fn main() { example().unwrap(); }
1539         /// ```
deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error> where D: de::Deserializer<'de>,1540         pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
1541         where
1542             D: de::Deserializer<'de>,
1543         {
1544             Ok(d.deserialize_i64(MilliSecondsTimestampVisitor).map(|dt| dt.with_timezone(&Utc))?)
1545         }
1546 
1547         impl<'de> de::Visitor<'de> for MilliSecondsTimestampVisitor {
1548             type Value = DateTime<Utc>;
1549 
expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result1550             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1551                 formatter.write_str("a unix timestamp in milliseconds")
1552             }
1553 
1554             /// Deserialize a timestamp in milliseconds since the epoch
visit_i64<E>(self, value: i64) -> Result<DateTime<Utc>, E> where E: de::Error,1555             fn visit_i64<E>(self, value: i64) -> Result<DateTime<Utc>, E>
1556             where
1557                 E: de::Error,
1558             {
1559                 serde_from(
1560                     Utc.timestamp_opt(value / 1000, ((value % 1000) * 1_000_000) as u32),
1561                     &value,
1562                 )
1563             }
1564 
1565             /// Deserialize a timestamp in milliseconds since the epoch
visit_u64<E>(self, value: u64) -> Result<DateTime<Utc>, E> where E: de::Error,1566             fn visit_u64<E>(self, value: u64) -> Result<DateTime<Utc>, E>
1567             where
1568                 E: de::Error,
1569             {
1570                 serde_from(
1571                     Utc.timestamp_opt((value / 1000) as i64, ((value % 1000) * 1_000_000) as u32),
1572                     &value,
1573                 )
1574             }
1575         }
1576     }
1577 
1578     /// Ser/de to/from optional timestamps in milliseconds
1579     ///
1580     /// Intended for use with `serde`s `with` attribute.
1581     ///
1582     /// # Example
1583     ///
1584     /// ```rust
1585     /// # // We mark this ignored so that we can test on 1.13 (which does not
1586     /// # // support custom derive), and run tests with --ignored on beta and
1587     /// # // nightly to actually trigger these.
1588     /// #
1589     /// # #[macro_use] extern crate serde_derive;
1590     /// # #[macro_use] extern crate serde_json;
1591     /// # extern crate chrono;
1592     /// # use chrono::{TimeZone, DateTime, Utc};
1593     /// use chrono::serde::ts_milliseconds_option;
1594     /// #[derive(Deserialize, Serialize)]
1595     /// struct S {
1596     ///     #[serde(with = "ts_milliseconds_option")]
1597     ///     time: Option<DateTime<Utc>>
1598     /// }
1599     ///
1600     /// # fn example() -> Result<S, serde_json::Error> {
1601     /// let time = Some(Utc.ymd(2018, 5, 17).and_hms_milli(02, 04, 59, 918));
1602     /// let my_s = S {
1603     ///     time: time.clone(),
1604     /// };
1605     ///
1606     /// let as_string = serde_json::to_string(&my_s)?;
1607     /// assert_eq!(as_string, r#"{"time":1526522699918}"#);
1608     /// let my_s: S = serde_json::from_str(&as_string)?;
1609     /// assert_eq!(my_s.time, time);
1610     /// # Ok(my_s)
1611     /// # }
1612     /// # fn main() { example().unwrap(); }
1613     /// ```
1614     pub mod ts_milliseconds_option {
1615         use core::fmt;
1616         use serdelib::{de, ser};
1617 
1618         use {DateTime, Utc};
1619 
1620         use super::MilliSecondsTimestampVisitor;
1621 
1622         /// Serialize a UTC datetime into an integer number of milliseconds since the epoch or none
1623         ///
1624         /// Intended for use with `serde`s `serialize_with` attribute.
1625         ///
1626         /// # Example:
1627         ///
1628         /// ```rust
1629         /// # // We mark this ignored so that we can test on 1.13 (which does not
1630         /// # // support custom derive), and run tests with --ignored on beta and
1631         /// # // nightly to actually trigger these.
1632         /// #
1633         /// # #[macro_use] extern crate serde_derive;
1634         /// # #[macro_use] extern crate serde_json;
1635         /// # extern crate chrono;
1636         /// # use chrono::{TimeZone, DateTime, Utc};
1637         /// use chrono::serde::ts_milliseconds_option::serialize as to_milli_tsopt;
1638         /// #[derive(Serialize)]
1639         /// struct S {
1640         ///     #[serde(serialize_with = "to_milli_tsopt")]
1641         ///     time: Option<DateTime<Utc>>
1642         /// }
1643         ///
1644         /// # fn example() -> Result<String, serde_json::Error> {
1645         /// let my_s = S {
1646         ///     time: Some(Utc.ymd(2018, 5, 17).and_hms_milli(02, 04, 59, 918)),
1647         /// };
1648         /// let as_string = serde_json::to_string(&my_s)?;
1649         /// assert_eq!(as_string, r#"{"time":1526522699918}"#);
1650         /// # Ok(as_string)
1651         /// # }
1652         /// # fn main() { example().unwrap(); }
1653         /// ```
serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error> where S: ser::Serializer,1654         pub fn serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
1655         where
1656             S: ser::Serializer,
1657         {
1658             match *opt {
1659                 Some(ref dt) => serializer.serialize_some(&dt.timestamp_millis()),
1660                 None => serializer.serialize_none(),
1661             }
1662         }
1663 
1664         /// Deserialize a `DateTime` from a millisecond timestamp or none
1665         ///
1666         /// Intended for use with `serde`s `deserialize_with` attribute.
1667         ///
1668         /// # Example:
1669         ///
1670         /// ```rust
1671         /// # // We mark this ignored so that we can test on 1.13 (which does not
1672         /// # // support custom derive), and run tests with --ignored on beta and
1673         /// # // nightly to actually trigger these.
1674         /// #
1675         /// # #[macro_use] extern crate serde_derive;
1676         /// # #[macro_use] extern crate serde_json;
1677         /// # extern crate chrono;
1678         /// # use chrono::prelude::*;
1679         /// use chrono::serde::ts_milliseconds_option::deserialize as from_milli_tsopt;
1680         ///
1681         /// #[derive(Deserialize, PartialEq, Debug)]
1682         /// #[serde(untagged)]
1683         /// enum E<T> {
1684         ///     V(T),
1685         /// }
1686         ///
1687         /// #[derive(Deserialize, PartialEq, Debug)]
1688         /// struct S {
1689         ///     #[serde(default, deserialize_with = "from_milli_tsopt")]
1690         ///     time: Option<DateTime<Utc>>
1691         /// }
1692         ///
1693         /// # fn example() -> Result<(), serde_json::Error> {
1694         /// let my_s: E<S> = serde_json::from_str(r#"{ "time": 1526522699918 }"#)?;
1695         /// assert_eq!(my_s, E::V(S { time: Some(Utc.timestamp(1526522699, 918000000)) }));
1696         /// let s: E<S> = serde_json::from_str(r#"{ "time": null }"#)?;
1697         /// assert_eq!(s, E::V(S { time: None }));
1698         /// let t: E<S> = serde_json::from_str(r#"{}"#)?;
1699         /// assert_eq!(t, E::V(S { time: None }));
1700         /// # Ok(())
1701         /// # }
1702         /// # fn main() { example().unwrap(); }
1703         /// ```
deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error> where D: de::Deserializer<'de>,1704         pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
1705         where
1706             D: de::Deserializer<'de>,
1707         {
1708             Ok(d.deserialize_option(OptionMilliSecondsTimestampVisitor)
1709                 .map(|opt| opt.map(|dt| dt.with_timezone(&Utc)))?)
1710         }
1711 
1712         struct OptionMilliSecondsTimestampVisitor;
1713 
1714         impl<'de> de::Visitor<'de> for OptionMilliSecondsTimestampVisitor {
1715             type Value = Option<DateTime<Utc>>;
1716 
expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result1717             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1718                 formatter.write_str("a unix timestamp in milliseconds or none")
1719             }
1720 
1721             /// Deserialize a timestamp in seconds since the epoch
visit_some<D>(self, d: D) -> Result<Option<DateTime<Utc>>, D::Error> where D: de::Deserializer<'de>,1722             fn visit_some<D>(self, d: D) -> Result<Option<DateTime<Utc>>, D::Error>
1723             where
1724                 D: de::Deserializer<'de>,
1725             {
1726                 d.deserialize_i64(MilliSecondsTimestampVisitor).map(Some)
1727             }
1728 
1729             /// Deserialize a timestamp in seconds since the epoch
visit_none<E>(self) -> Result<Option<DateTime<Utc>>, E> where E: de::Error,1730             fn visit_none<E>(self) -> Result<Option<DateTime<Utc>>, E>
1731             where
1732                 E: de::Error,
1733             {
1734                 Ok(None)
1735             }
1736 
1737             /// Deserialize a timestamp in seconds since the epoch
visit_unit<E>(self) -> Result<Option<DateTime<Utc>>, E> where E: de::Error,1738             fn visit_unit<E>(self) -> Result<Option<DateTime<Utc>>, E>
1739             where
1740                 E: de::Error,
1741             {
1742                 Ok(None)
1743             }
1744         }
1745     }
1746 
1747     /// Ser/de to/from timestamps in seconds
1748     ///
1749     /// Intended for use with `serde`'s `with` attribute.
1750     ///
1751     /// # Example:
1752     ///
1753     /// ```rust
1754     /// # // We mark this ignored so that we can test on 1.13 (which does not
1755     /// # // support custom derive), and run tests with --ignored on beta and
1756     /// # // nightly to actually trigger these.
1757     /// #
1758     /// # #[macro_use] extern crate serde_derive;
1759     /// # #[macro_use] extern crate serde_json;
1760     /// # extern crate chrono;
1761     /// # use chrono::{TimeZone, DateTime, Utc};
1762     /// use chrono::serde::ts_seconds;
1763     /// #[derive(Deserialize, Serialize)]
1764     /// struct S {
1765     ///     #[serde(with = "ts_seconds")]
1766     ///     time: DateTime<Utc>
1767     /// }
1768     ///
1769     /// # fn example() -> Result<S, serde_json::Error> {
1770     /// let time = Utc.ymd(2015, 5, 15).and_hms(10, 0, 0);
1771     /// let my_s = S {
1772     ///     time: time.clone(),
1773     /// };
1774     ///
1775     /// let as_string = serde_json::to_string(&my_s)?;
1776     /// assert_eq!(as_string, r#"{"time":1431684000}"#);
1777     /// let my_s: S = serde_json::from_str(&as_string)?;
1778     /// assert_eq!(my_s.time, time);
1779     /// # Ok(my_s)
1780     /// # }
1781     /// # fn main() { example().unwrap(); }
1782     /// ```
1783     pub mod ts_seconds {
1784         use core::fmt;
1785         use serdelib::{de, ser};
1786 
1787         use offset::TimeZone;
1788         use {DateTime, Utc};
1789 
1790         use super::{serde_from, SecondsTimestampVisitor};
1791 
1792         /// Serialize a UTC datetime into an integer number of seconds since the epoch
1793         ///
1794         /// Intended for use with `serde`s `serialize_with` attribute.
1795         ///
1796         /// # Example:
1797         ///
1798         /// ```rust
1799         /// # // We mark this ignored so that we can test on 1.13 (which does not
1800         /// # // support custom derive), and run tests with --ignored on beta and
1801         /// # // nightly to actually trigger these.
1802         /// #
1803         /// # #[macro_use] extern crate serde_derive;
1804         /// # #[macro_use] extern crate serde_json;
1805         /// # extern crate chrono;
1806         /// # use chrono::{TimeZone, DateTime, Utc};
1807         /// use chrono::serde::ts_seconds::serialize as to_ts;
1808         /// #[derive(Serialize)]
1809         /// struct S {
1810         ///     #[serde(serialize_with = "to_ts")]
1811         ///     time: DateTime<Utc>
1812         /// }
1813         ///
1814         /// # fn example() -> Result<String, serde_json::Error> {
1815         /// let my_s = S {
1816         ///     time: Utc.ymd(2015, 5, 15).and_hms(10, 0, 0),
1817         /// };
1818         /// let as_string = serde_json::to_string(&my_s)?;
1819         /// assert_eq!(as_string, r#"{"time":1431684000}"#);
1820         /// # Ok(as_string)
1821         /// # }
1822         /// # fn main() { example().unwrap(); }
1823         /// ```
serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error> where S: ser::Serializer,1824         pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
1825         where
1826             S: ser::Serializer,
1827         {
1828             serializer.serialize_i64(dt.timestamp())
1829         }
1830 
1831         /// Deserialize a `DateTime` from a seconds timestamp
1832         ///
1833         /// Intended for use with `serde`s `deserialize_with` attribute.
1834         ///
1835         /// # Example:
1836         ///
1837         /// ```rust
1838         /// # // We mark this ignored so that we can test on 1.13 (which does not
1839         /// # // support custom derive), and run tests with --ignored on beta and
1840         /// # // nightly to actually trigger these.
1841         /// #
1842         /// # #[macro_use] extern crate serde_derive;
1843         /// # #[macro_use] extern crate serde_json;
1844         /// # extern crate chrono;
1845         /// # use chrono::{DateTime, Utc};
1846         /// use chrono::serde::ts_seconds::deserialize as from_ts;
1847         /// #[derive(Deserialize)]
1848         /// struct S {
1849         ///     #[serde(deserialize_with = "from_ts")]
1850         ///     time: DateTime<Utc>
1851         /// }
1852         ///
1853         /// # fn example() -> Result<S, serde_json::Error> {
1854         /// let my_s: S = serde_json::from_str(r#"{ "time": 1431684000 }"#)?;
1855         /// # Ok(my_s)
1856         /// # }
1857         /// # fn main() { example().unwrap(); }
1858         /// ```
deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error> where D: de::Deserializer<'de>,1859         pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
1860         where
1861             D: de::Deserializer<'de>,
1862         {
1863             Ok(d.deserialize_i64(SecondsTimestampVisitor)?)
1864         }
1865 
1866         impl<'de> de::Visitor<'de> for SecondsTimestampVisitor {
1867             type Value = DateTime<Utc>;
1868 
expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result1869             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1870                 formatter.write_str("a unix timestamp in seconds")
1871             }
1872 
1873             /// Deserialize a timestamp in seconds since the epoch
visit_i64<E>(self, value: i64) -> Result<DateTime<Utc>, E> where E: de::Error,1874             fn visit_i64<E>(self, value: i64) -> Result<DateTime<Utc>, E>
1875             where
1876                 E: de::Error,
1877             {
1878                 serde_from(Utc.timestamp_opt(value, 0), &value)
1879             }
1880 
1881             /// Deserialize a timestamp in seconds since the epoch
visit_u64<E>(self, value: u64) -> Result<DateTime<Utc>, E> where E: de::Error,1882             fn visit_u64<E>(self, value: u64) -> Result<DateTime<Utc>, E>
1883             where
1884                 E: de::Error,
1885             {
1886                 serde_from(Utc.timestamp_opt(value as i64, 0), &value)
1887             }
1888         }
1889     }
1890 
1891     /// Ser/de to/from optional timestamps in seconds
1892     ///
1893     /// Intended for use with `serde`'s `with` attribute.
1894     ///
1895     /// # Example:
1896     ///
1897     /// ```rust
1898     /// # // We mark this ignored so that we can test on 1.13 (which does not
1899     /// # // support custom derive), and run tests with --ignored on beta and
1900     /// # // nightly to actually trigger these.
1901     /// #
1902     /// # #[macro_use] extern crate serde_derive;
1903     /// # #[macro_use] extern crate serde_json;
1904     /// # extern crate chrono;
1905     /// # use chrono::{TimeZone, DateTime, Utc};
1906     /// use chrono::serde::ts_seconds_option;
1907     /// #[derive(Deserialize, Serialize)]
1908     /// struct S {
1909     ///     #[serde(with = "ts_seconds_option")]
1910     ///     time: Option<DateTime<Utc>>
1911     /// }
1912     ///
1913     /// # fn example() -> Result<S, serde_json::Error> {
1914     /// let time = Some(Utc.ymd(2015, 5, 15).and_hms(10, 0, 0));
1915     /// let my_s = S {
1916     ///     time: time.clone(),
1917     /// };
1918     ///
1919     /// let as_string = serde_json::to_string(&my_s)?;
1920     /// assert_eq!(as_string, r#"{"time":1431684000}"#);
1921     /// let my_s: S = serde_json::from_str(&as_string)?;
1922     /// assert_eq!(my_s.time, time);
1923     /// # Ok(my_s)
1924     /// # }
1925     /// # fn main() { example().unwrap(); }
1926     /// ```
1927     pub mod ts_seconds_option {
1928         use core::fmt;
1929         use serdelib::{de, ser};
1930 
1931         use {DateTime, Utc};
1932 
1933         use super::SecondsTimestampVisitor;
1934 
1935         /// Serialize a UTC datetime into an integer number of seconds since the epoch or none
1936         ///
1937         /// Intended for use with `serde`s `serialize_with` attribute.
1938         ///
1939         /// # Example:
1940         ///
1941         /// ```rust
1942         /// # // We mark this ignored so that we can test on 1.13 (which does not
1943         /// # // support custom derive), and run tests with --ignored on beta and
1944         /// # // nightly to actually trigger these.
1945         /// #
1946         /// # #[macro_use] extern crate serde_derive;
1947         /// # #[macro_use] extern crate serde_json;
1948         /// # extern crate chrono;
1949         /// # use chrono::{TimeZone, DateTime, Utc};
1950         /// use chrono::serde::ts_seconds_option::serialize as to_tsopt;
1951         /// #[derive(Serialize)]
1952         /// struct S {
1953         ///     #[serde(serialize_with = "to_tsopt")]
1954         ///     time: Option<DateTime<Utc>>
1955         /// }
1956         ///
1957         /// # fn example() -> Result<String, serde_json::Error> {
1958         /// let my_s = S {
1959         ///     time: Some(Utc.ymd(2015, 5, 15).and_hms(10, 0, 0)),
1960         /// };
1961         /// let as_string = serde_json::to_string(&my_s)?;
1962         /// assert_eq!(as_string, r#"{"time":1431684000}"#);
1963         /// # Ok(as_string)
1964         /// # }
1965         /// # fn main() { example().unwrap(); }
1966         /// ```
serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error> where S: ser::Serializer,1967         pub fn serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
1968         where
1969             S: ser::Serializer,
1970         {
1971             match *opt {
1972                 Some(ref dt) => serializer.serialize_some(&dt.timestamp()),
1973                 None => serializer.serialize_none(),
1974             }
1975         }
1976 
1977         /// Deserialize a `DateTime` from a seconds timestamp or none
1978         ///
1979         /// Intended for use with `serde`s `deserialize_with` attribute.
1980         ///
1981         /// # Example:
1982         ///
1983         /// ```rust
1984         /// # // We mark this ignored so that we can test on 1.13 (which does not
1985         /// # // support custom derive), and run tests with --ignored on beta and
1986         /// # // nightly to actually trigger these.
1987         /// #
1988         /// # #[macro_use] extern crate serde_derive;
1989         /// # #[macro_use] extern crate serde_json;
1990         /// # extern crate chrono;
1991         /// # use chrono::{DateTime, Utc};
1992         /// use chrono::serde::ts_seconds_option::deserialize as from_tsopt;
1993         /// #[derive(Deserialize)]
1994         /// struct S {
1995         ///     #[serde(deserialize_with = "from_tsopt")]
1996         ///     time: Option<DateTime<Utc>>
1997         /// }
1998         ///
1999         /// # fn example() -> Result<S, serde_json::Error> {
2000         /// let my_s: S = serde_json::from_str(r#"{ "time": 1431684000 }"#)?;
2001         /// # Ok(my_s)
2002         /// # }
2003         /// # fn main() { example().unwrap(); }
2004         /// ```
deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error> where D: de::Deserializer<'de>,2005         pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
2006         where
2007             D: de::Deserializer<'de>,
2008         {
2009             Ok(d.deserialize_option(OptionSecondsTimestampVisitor)?)
2010         }
2011 
2012         struct OptionSecondsTimestampVisitor;
2013 
2014         impl<'de> de::Visitor<'de> for OptionSecondsTimestampVisitor {
2015             type Value = Option<DateTime<Utc>>;
2016 
expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result2017             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2018                 formatter.write_str("a unix timestamp in seconds or none")
2019             }
2020 
2021             /// Deserialize a timestamp in seconds since the epoch
visit_some<D>(self, d: D) -> Result<Option<DateTime<Utc>>, D::Error> where D: de::Deserializer<'de>,2022             fn visit_some<D>(self, d: D) -> Result<Option<DateTime<Utc>>, D::Error>
2023             where
2024                 D: de::Deserializer<'de>,
2025             {
2026                 d.deserialize_i64(SecondsTimestampVisitor).map(Some)
2027             }
2028 
2029             /// Deserialize a timestamp in seconds since the epoch
visit_none<E>(self) -> Result<Option<DateTime<Utc>>, E> where E: de::Error,2030             fn visit_none<E>(self) -> Result<Option<DateTime<Utc>>, E>
2031             where
2032                 E: de::Error,
2033             {
2034                 Ok(None)
2035             }
2036 
2037             /// Deserialize a timestamp in seconds since the epoch
visit_unit<E>(self) -> Result<Option<DateTime<Utc>>, E> where E: de::Error,2038             fn visit_unit<E>(self) -> Result<Option<DateTime<Utc>>, E>
2039             where
2040                 E: de::Error,
2041             {
2042                 Ok(None)
2043             }
2044         }
2045     }
2046 
2047     impl<Tz: TimeZone> ser::Serialize for DateTime<Tz> {
2048         /// Serialize into a rfc3339 time string
2049         ///
2050         /// See [the `serde` module](./serde/index.html) for alternate
2051         /// serializations.
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: ser::Serializer,2052         fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2053         where
2054             S: ser::Serializer,
2055         {
2056             struct FormatWrapped<'a, D: 'a> {
2057                 inner: &'a D,
2058             }
2059 
2060             impl<'a, D: fmt::Debug> fmt::Display for FormatWrapped<'a, D> {
2061                 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2062                     self.inner.fmt(f)
2063                 }
2064             }
2065 
2066             // Debug formatting is correct RFC3339, and it allows Zulu.
2067             serializer.collect_str(&FormatWrapped { inner: &self })
2068         }
2069     }
2070 
2071     struct DateTimeVisitor;
2072 
2073     impl<'de> de::Visitor<'de> for DateTimeVisitor {
2074         type Value = DateTime<FixedOffset>;
2075 
expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result2076         fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2077             write!(formatter, "a formatted date and time string or a unix timestamp")
2078         }
2079 
visit_str<E>(self, value: &str) -> Result<DateTime<FixedOffset>, E> where E: de::Error,2080         fn visit_str<E>(self, value: &str) -> Result<DateTime<FixedOffset>, E>
2081         where
2082             E: de::Error,
2083         {
2084             value.parse().map_err(|err: ::format::ParseError| E::custom(err))
2085         }
2086     }
2087 
2088     /// Deserialize a value that optionally includes a timezone offset in its
2089     /// string representation
2090     ///
2091     /// The value to be deserialized must be an rfc3339 string.
2092     ///
2093     /// See [the `serde` module](./serde/index.html) for alternate
2094     /// deserialization formats.
2095     impl<'de> de::Deserialize<'de> for DateTime<FixedOffset> {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: de::Deserializer<'de>,2096         fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2097         where
2098             D: de::Deserializer<'de>,
2099         {
2100             deserializer.deserialize_str(DateTimeVisitor)
2101         }
2102     }
2103 
2104     /// Deserialize into a UTC value
2105     ///
2106     /// The value to be deserialized must be an rfc3339 string.
2107     ///
2108     /// See [the `serde` module](./serde/index.html) for alternate
2109     /// deserialization formats.
2110     impl<'de> de::Deserialize<'de> for DateTime<Utc> {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: de::Deserializer<'de>,2111         fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2112         where
2113             D: de::Deserializer<'de>,
2114         {
2115             deserializer.deserialize_str(DateTimeVisitor).map(|dt| dt.with_timezone(&Utc))
2116         }
2117     }
2118 
2119     /// Deserialize a value that includes no timezone in its string
2120     /// representation
2121     ///
2122     /// The value to be deserialized must be an rfc3339 string.
2123     ///
2124     /// See [the `serde` module](./serde/index.html) for alternate
2125     /// serialization formats.
2126     #[cfg(feature = "clock")]
2127     impl<'de> de::Deserialize<'de> for DateTime<Local> {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: de::Deserializer<'de>,2128         fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2129         where
2130             D: de::Deserializer<'de>,
2131         {
2132             deserializer.deserialize_str(DateTimeVisitor).map(|dt| dt.with_timezone(&Local))
2133         }
2134     }
2135 
2136     #[cfg(test)]
2137     extern crate bincode;
2138     #[cfg(test)]
2139     extern crate serde_json;
2140 
2141     #[test]
test_serde_serialize()2142     fn test_serde_serialize() {
2143         super::test_encodable_json(self::serde_json::to_string, self::serde_json::to_string);
2144     }
2145 
2146     #[cfg(feature = "clock")]
2147     #[test]
test_serde_deserialize()2148     fn test_serde_deserialize() {
2149         super::test_decodable_json(
2150             |input| self::serde_json::from_str(&input),
2151             |input| self::serde_json::from_str(&input),
2152             |input| self::serde_json::from_str(&input),
2153         );
2154     }
2155 
2156     #[test]
test_serde_bincode()2157     fn test_serde_bincode() {
2158         // Bincode is relevant to test separately from JSON because
2159         // it is not self-describing.
2160         use self::bincode::{deserialize, serialize, Infinite};
2161 
2162         let dt = Utc.ymd(2014, 7, 24).and_hms(12, 34, 6);
2163         let encoded = serialize(&dt, Infinite).unwrap();
2164         let decoded: DateTime<Utc> = deserialize(&encoded).unwrap();
2165         assert_eq!(dt, decoded);
2166         assert_eq!(dt.offset(), decoded.offset());
2167     }
2168 }
2169 
2170 #[cfg(test)]
2171 mod tests {
2172     use super::DateTime;
2173     use naive::{NaiveDate, NaiveTime};
2174     #[cfg(feature = "clock")]
2175     use offset::Local;
2176     use offset::{FixedOffset, TimeZone, Utc};
2177     use oldtime::Duration;
2178     use std::time::{SystemTime, UNIX_EPOCH};
2179     #[cfg(feature = "clock")]
2180     use Datelike;
2181 
2182     #[test]
2183     #[allow(non_snake_case)]
test_datetime_offset()2184     fn test_datetime_offset() {
2185         let Est = FixedOffset::west(5 * 60 * 60);
2186         let Edt = FixedOffset::west(4 * 60 * 60);
2187         let Kst = FixedOffset::east(9 * 60 * 60);
2188 
2189         assert_eq!(format!("{}", Utc.ymd(2014, 5, 6).and_hms(7, 8, 9)), "2014-05-06 07:08:09 UTC");
2190         assert_eq!(
2191             format!("{}", Edt.ymd(2014, 5, 6).and_hms(7, 8, 9)),
2192             "2014-05-06 07:08:09 -04:00"
2193         );
2194         assert_eq!(
2195             format!("{}", Kst.ymd(2014, 5, 6).and_hms(7, 8, 9)),
2196             "2014-05-06 07:08:09 +09:00"
2197         );
2198         assert_eq!(format!("{:?}", Utc.ymd(2014, 5, 6).and_hms(7, 8, 9)), "2014-05-06T07:08:09Z");
2199         assert_eq!(
2200             format!("{:?}", Edt.ymd(2014, 5, 6).and_hms(7, 8, 9)),
2201             "2014-05-06T07:08:09-04:00"
2202         );
2203         assert_eq!(
2204             format!("{:?}", Kst.ymd(2014, 5, 6).and_hms(7, 8, 9)),
2205             "2014-05-06T07:08:09+09:00"
2206         );
2207 
2208         // edge cases
2209         assert_eq!(format!("{:?}", Utc.ymd(2014, 5, 6).and_hms(0, 0, 0)), "2014-05-06T00:00:00Z");
2210         assert_eq!(
2211             format!("{:?}", Edt.ymd(2014, 5, 6).and_hms(0, 0, 0)),
2212             "2014-05-06T00:00:00-04:00"
2213         );
2214         assert_eq!(
2215             format!("{:?}", Kst.ymd(2014, 5, 6).and_hms(0, 0, 0)),
2216             "2014-05-06T00:00:00+09:00"
2217         );
2218         assert_eq!(
2219             format!("{:?}", Utc.ymd(2014, 5, 6).and_hms(23, 59, 59)),
2220             "2014-05-06T23:59:59Z"
2221         );
2222         assert_eq!(
2223             format!("{:?}", Edt.ymd(2014, 5, 6).and_hms(23, 59, 59)),
2224             "2014-05-06T23:59:59-04:00"
2225         );
2226         assert_eq!(
2227             format!("{:?}", Kst.ymd(2014, 5, 6).and_hms(23, 59, 59)),
2228             "2014-05-06T23:59:59+09:00"
2229         );
2230 
2231         let dt = Utc.ymd(2014, 5, 6).and_hms(7, 8, 9);
2232         assert_eq!(dt, Edt.ymd(2014, 5, 6).and_hms(3, 8, 9));
2233         assert_eq!(dt + Duration::seconds(3600 + 60 + 1), Utc.ymd(2014, 5, 6).and_hms(8, 9, 10));
2234         assert_eq!(
2235             dt.signed_duration_since(Edt.ymd(2014, 5, 6).and_hms(10, 11, 12)),
2236             Duration::seconds(-7 * 3600 - 3 * 60 - 3)
2237         );
2238 
2239         assert_eq!(*Utc.ymd(2014, 5, 6).and_hms(7, 8, 9).offset(), Utc);
2240         assert_eq!(*Edt.ymd(2014, 5, 6).and_hms(7, 8, 9).offset(), Edt);
2241         assert!(*Edt.ymd(2014, 5, 6).and_hms(7, 8, 9).offset() != Est);
2242     }
2243 
2244     #[test]
test_datetime_date_and_time()2245     fn test_datetime_date_and_time() {
2246         let tz = FixedOffset::east(5 * 60 * 60);
2247         let d = tz.ymd(2014, 5, 6).and_hms(7, 8, 9);
2248         assert_eq!(d.time(), NaiveTime::from_hms(7, 8, 9));
2249         assert_eq!(d.date(), tz.ymd(2014, 5, 6));
2250         assert_eq!(d.date().naive_local(), NaiveDate::from_ymd(2014, 5, 6));
2251         assert_eq!(d.date().and_time(d.time()), Some(d));
2252 
2253         let tz = FixedOffset::east(4 * 60 * 60);
2254         let d = tz.ymd(2016, 5, 4).and_hms(3, 2, 1);
2255         assert_eq!(d.time(), NaiveTime::from_hms(3, 2, 1));
2256         assert_eq!(d.date(), tz.ymd(2016, 5, 4));
2257         assert_eq!(d.date().naive_local(), NaiveDate::from_ymd(2016, 5, 4));
2258         assert_eq!(d.date().and_time(d.time()), Some(d));
2259 
2260         let tz = FixedOffset::west(13 * 60 * 60);
2261         let d = tz.ymd(2017, 8, 9).and_hms(12, 34, 56);
2262         assert_eq!(d.time(), NaiveTime::from_hms(12, 34, 56));
2263         assert_eq!(d.date(), tz.ymd(2017, 8, 9));
2264         assert_eq!(d.date().naive_local(), NaiveDate::from_ymd(2017, 8, 9));
2265         assert_eq!(d.date().and_time(d.time()), Some(d));
2266 
2267         let utc_d = Utc.ymd(2017, 8, 9).and_hms(12, 34, 56);
2268         assert!(utc_d < d);
2269     }
2270 
2271     #[test]
2272     #[cfg(feature = "clock")]
test_datetime_with_timezone()2273     fn test_datetime_with_timezone() {
2274         let local_now = Local::now();
2275         let utc_now = local_now.with_timezone(&Utc);
2276         let local_now2 = utc_now.with_timezone(&Local);
2277         assert_eq!(local_now, local_now2);
2278     }
2279 
2280     #[test]
2281     #[allow(non_snake_case)]
test_datetime_rfc2822_and_rfc3339()2282     fn test_datetime_rfc2822_and_rfc3339() {
2283         let EDT = FixedOffset::east(5 * 60 * 60);
2284         assert_eq!(
2285             Utc.ymd(2015, 2, 18).and_hms(23, 16, 9).to_rfc2822(),
2286             "Wed, 18 Feb 2015 23:16:09 +0000"
2287         );
2288         assert_eq!(
2289             Utc.ymd(2015, 2, 18).and_hms(23, 16, 9).to_rfc3339(),
2290             "2015-02-18T23:16:09+00:00"
2291         );
2292         assert_eq!(
2293             EDT.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150).to_rfc2822(),
2294             "Wed, 18 Feb 2015 23:16:09 +0500"
2295         );
2296         assert_eq!(
2297             EDT.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150).to_rfc3339(),
2298             "2015-02-18T23:16:09.150+05:00"
2299         );
2300         assert_eq!(
2301             EDT.ymd(2015, 2, 18).and_hms_micro(23, 59, 59, 1_234_567).to_rfc2822(),
2302             "Wed, 18 Feb 2015 23:59:60 +0500"
2303         );
2304         assert_eq!(
2305             EDT.ymd(2015, 2, 18).and_hms_micro(23, 59, 59, 1_234_567).to_rfc3339(),
2306             "2015-02-18T23:59:60.234567+05:00"
2307         );
2308 
2309         assert_eq!(
2310             DateTime::parse_from_rfc2822("Wed, 18 Feb 2015 23:16:09 +0000"),
2311             Ok(FixedOffset::east(0).ymd(2015, 2, 18).and_hms(23, 16, 9))
2312         );
2313         assert_eq!(
2314             DateTime::parse_from_rfc2822("Wed, 18 Feb 2015 23:16:09 -0000"),
2315             Ok(FixedOffset::east(0).ymd(2015, 2, 18).and_hms(23, 16, 9))
2316         );
2317         assert_eq!(
2318             DateTime::parse_from_rfc3339("2015-02-18T23:16:09Z"),
2319             Ok(FixedOffset::east(0).ymd(2015, 2, 18).and_hms(23, 16, 9))
2320         );
2321         assert_eq!(
2322             DateTime::parse_from_rfc2822("Wed, 18 Feb 2015 23:59:60 +0500"),
2323             Ok(EDT.ymd(2015, 2, 18).and_hms_milli(23, 59, 59, 1_000))
2324         );
2325         assert_eq!(
2326             DateTime::parse_from_rfc3339("2015-02-18T23:59:60.234567+05:00"),
2327             Ok(EDT.ymd(2015, 2, 18).and_hms_micro(23, 59, 59, 1_234_567))
2328         );
2329     }
2330 
2331     #[test]
test_rfc3339_opts()2332     fn test_rfc3339_opts() {
2333         use SecondsFormat::*;
2334         let pst = FixedOffset::east(8 * 60 * 60);
2335         let dt = pst.ymd(2018, 1, 11).and_hms_nano(10, 5, 13, 084_660_000);
2336         assert_eq!(dt.to_rfc3339_opts(Secs, false), "2018-01-11T10:05:13+08:00");
2337         assert_eq!(dt.to_rfc3339_opts(Secs, true), "2018-01-11T10:05:13+08:00");
2338         assert_eq!(dt.to_rfc3339_opts(Millis, false), "2018-01-11T10:05:13.084+08:00");
2339         assert_eq!(dt.to_rfc3339_opts(Micros, false), "2018-01-11T10:05:13.084660+08:00");
2340         assert_eq!(dt.to_rfc3339_opts(Nanos, false), "2018-01-11T10:05:13.084660000+08:00");
2341         assert_eq!(dt.to_rfc3339_opts(AutoSi, false), "2018-01-11T10:05:13.084660+08:00");
2342 
2343         let ut = DateTime::<Utc>::from_utc(dt.naive_utc(), Utc);
2344         assert_eq!(ut.to_rfc3339_opts(Secs, false), "2018-01-11T02:05:13+00:00");
2345         assert_eq!(ut.to_rfc3339_opts(Secs, true), "2018-01-11T02:05:13Z");
2346         assert_eq!(ut.to_rfc3339_opts(Millis, false), "2018-01-11T02:05:13.084+00:00");
2347         assert_eq!(ut.to_rfc3339_opts(Millis, true), "2018-01-11T02:05:13.084Z");
2348         assert_eq!(ut.to_rfc3339_opts(Micros, true), "2018-01-11T02:05:13.084660Z");
2349         assert_eq!(ut.to_rfc3339_opts(Nanos, true), "2018-01-11T02:05:13.084660000Z");
2350         assert_eq!(ut.to_rfc3339_opts(AutoSi, true), "2018-01-11T02:05:13.084660Z");
2351     }
2352 
2353     #[test]
2354     #[should_panic]
test_rfc3339_opts_nonexhaustive()2355     fn test_rfc3339_opts_nonexhaustive() {
2356         use SecondsFormat;
2357         let dt = Utc.ymd(1999, 10, 9).and_hms(1, 2, 3);
2358         dt.to_rfc3339_opts(SecondsFormat::__NonExhaustive, true);
2359     }
2360 
2361     #[test]
test_datetime_from_str()2362     fn test_datetime_from_str() {
2363         assert_eq!(
2364             "2015-02-18T23:16:9.15Z".parse::<DateTime<FixedOffset>>(),
2365             Ok(FixedOffset::east(0).ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150))
2366         );
2367         assert_eq!(
2368             "2015-02-18T23:16:9.15Z".parse::<DateTime<Utc>>(),
2369             Ok(Utc.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150))
2370         );
2371         assert_eq!(
2372             "2015-02-18T23:16:9.15 UTC".parse::<DateTime<Utc>>(),
2373             Ok(Utc.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150))
2374         );
2375         assert_eq!(
2376             "2015-02-18T23:16:9.15UTC".parse::<DateTime<Utc>>(),
2377             Ok(Utc.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150))
2378         );
2379 
2380         assert_eq!(
2381             "2015-2-18T23:16:9.15Z".parse::<DateTime<FixedOffset>>(),
2382             Ok(FixedOffset::east(0).ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150))
2383         );
2384         assert_eq!(
2385             "2015-2-18T13:16:9.15-10:00".parse::<DateTime<FixedOffset>>(),
2386             Ok(FixedOffset::west(10 * 3600).ymd(2015, 2, 18).and_hms_milli(13, 16, 9, 150))
2387         );
2388         assert!("2015-2-18T23:16:9.15".parse::<DateTime<FixedOffset>>().is_err());
2389 
2390         assert_eq!(
2391             "2015-2-18T23:16:9.15Z".parse::<DateTime<Utc>>(),
2392             Ok(Utc.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150))
2393         );
2394         assert_eq!(
2395             "2015-2-18T13:16:9.15-10:00".parse::<DateTime<Utc>>(),
2396             Ok(Utc.ymd(2015, 2, 18).and_hms_milli(23, 16, 9, 150))
2397         );
2398         assert!("2015-2-18T23:16:9.15".parse::<DateTime<Utc>>().is_err());
2399 
2400         // no test for `DateTime<Local>`, we cannot verify that much.
2401     }
2402 
2403     #[test]
test_datetime_parse_from_str()2404     fn test_datetime_parse_from_str() {
2405         let ymdhms = |y, m, d, h, n, s, off| FixedOffset::east(off).ymd(y, m, d).and_hms(h, n, s);
2406         assert_eq!(
2407             DateTime::parse_from_str("2014-5-7T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"),
2408             Ok(ymdhms(2014, 5, 7, 12, 34, 56, 570 * 60))
2409         ); // ignore offset
2410         assert!(DateTime::parse_from_str("20140507000000", "%Y%m%d%H%M%S").is_err()); // no offset
2411         assert!(DateTime::parse_from_str(
2412             "Fri, 09 Aug 2013 23:54:35 GMT",
2413             "%a, %d %b %Y %H:%M:%S GMT"
2414         )
2415         .is_err());
2416         assert_eq!(
2417             Utc.datetime_from_str("Fri, 09 Aug 2013 23:54:35 GMT", "%a, %d %b %Y %H:%M:%S GMT"),
2418             Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35))
2419         );
2420     }
2421 
2422     #[test]
test_to_string_round_trip()2423     fn test_to_string_round_trip() {
2424         let dt = Utc.ymd(2000, 1, 1).and_hms(0, 0, 0);
2425         let _dt: DateTime<Utc> = dt.to_string().parse().unwrap();
2426 
2427         let ndt_fixed = dt.with_timezone(&FixedOffset::east(3600));
2428         let _dt: DateTime<FixedOffset> = ndt_fixed.to_string().parse().unwrap();
2429 
2430         let ndt_fixed = dt.with_timezone(&FixedOffset::east(0));
2431         let _dt: DateTime<FixedOffset> = ndt_fixed.to_string().parse().unwrap();
2432     }
2433 
2434     #[test]
2435     #[cfg(feature = "clock")]
test_to_string_round_trip_with_local()2436     fn test_to_string_round_trip_with_local() {
2437         let ndt = Local::now();
2438         let _dt: DateTime<FixedOffset> = ndt.to_string().parse().unwrap();
2439     }
2440 
2441     #[test]
2442     #[cfg(feature = "clock")]
test_datetime_format_with_local()2443     fn test_datetime_format_with_local() {
2444         // if we are not around the year boundary, local and UTC date should have the same year
2445         let dt = Local::now().with_month(5).unwrap();
2446         assert_eq!(dt.format("%Y").to_string(), dt.with_timezone(&Utc).format("%Y").to_string());
2447     }
2448 
2449     #[test]
2450     #[cfg(feature = "clock")]
test_datetime_is_copy()2451     fn test_datetime_is_copy() {
2452         // UTC is known to be `Copy`.
2453         let a = Utc::now();
2454         let b = a;
2455         assert_eq!(a, b);
2456     }
2457 
2458     #[test]
2459     #[cfg(feature = "clock")]
test_datetime_is_send()2460     fn test_datetime_is_send() {
2461         use std::thread;
2462 
2463         // UTC is known to be `Send`.
2464         let a = Utc::now();
2465         thread::spawn(move || {
2466             let _ = a;
2467         })
2468         .join()
2469         .unwrap();
2470     }
2471 
2472     #[test]
test_subsecond_part()2473     fn test_subsecond_part() {
2474         let datetime = Utc.ymd(2014, 7, 8).and_hms_nano(9, 10, 11, 1234567);
2475 
2476         assert_eq!(1, datetime.timestamp_subsec_millis());
2477         assert_eq!(1234, datetime.timestamp_subsec_micros());
2478         assert_eq!(1234567, datetime.timestamp_subsec_nanos());
2479     }
2480 
2481     #[test]
2482     #[cfg(not(target_os = "windows"))]
test_from_system_time()2483     fn test_from_system_time() {
2484         use std::time::Duration;
2485 
2486         let epoch = Utc.ymd(1970, 1, 1).and_hms(0, 0, 0);
2487         let nanos = 999_999_999;
2488 
2489         // SystemTime -> DateTime<Utc>
2490         assert_eq!(DateTime::<Utc>::from(UNIX_EPOCH), epoch);
2491         assert_eq!(
2492             DateTime::<Utc>::from(UNIX_EPOCH + Duration::new(999_999_999, nanos)),
2493             Utc.ymd(2001, 9, 9).and_hms_nano(1, 46, 39, nanos)
2494         );
2495         assert_eq!(
2496             DateTime::<Utc>::from(UNIX_EPOCH - Duration::new(999_999_999, nanos)),
2497             Utc.ymd(1938, 4, 24).and_hms_nano(22, 13, 20, 1)
2498         );
2499 
2500         // DateTime<Utc> -> SystemTime
2501         assert_eq!(SystemTime::from(epoch), UNIX_EPOCH);
2502         assert_eq!(
2503             SystemTime::from(Utc.ymd(2001, 9, 9).and_hms_nano(1, 46, 39, nanos)),
2504             UNIX_EPOCH + Duration::new(999_999_999, nanos)
2505         );
2506         assert_eq!(
2507             SystemTime::from(Utc.ymd(1938, 4, 24).and_hms_nano(22, 13, 20, 1)),
2508             UNIX_EPOCH - Duration::new(999_999_999, 999_999_999)
2509         );
2510 
2511         // DateTime<any tz> -> SystemTime (via `with_timezone`)
2512         #[cfg(feature = "clock")]
2513         {
2514             assert_eq!(SystemTime::from(epoch.with_timezone(&Local)), UNIX_EPOCH);
2515         }
2516         assert_eq!(SystemTime::from(epoch.with_timezone(&FixedOffset::east(32400))), UNIX_EPOCH);
2517         assert_eq!(SystemTime::from(epoch.with_timezone(&FixedOffset::west(28800))), UNIX_EPOCH);
2518     }
2519 
2520     #[test]
2521     #[cfg(target_os = "windows")]
test_from_system_time()2522     fn test_from_system_time() {
2523         use std::time::Duration;
2524 
2525         let nanos = 999_999_000;
2526 
2527         let epoch = Utc.ymd(1970, 1, 1).and_hms(0, 0, 0);
2528 
2529         // SystemTime -> DateTime<Utc>
2530         assert_eq!(DateTime::<Utc>::from(UNIX_EPOCH), epoch);
2531         assert_eq!(
2532             DateTime::<Utc>::from(UNIX_EPOCH + Duration::new(999_999_999, nanos)),
2533             Utc.ymd(2001, 9, 9).and_hms_nano(1, 46, 39, nanos)
2534         );
2535         assert_eq!(
2536             DateTime::<Utc>::from(UNIX_EPOCH - Duration::new(999_999_999, nanos)),
2537             Utc.ymd(1938, 4, 24).and_hms_nano(22, 13, 20, 1_000)
2538         );
2539 
2540         // DateTime<Utc> -> SystemTime
2541         assert_eq!(SystemTime::from(epoch), UNIX_EPOCH);
2542         assert_eq!(
2543             SystemTime::from(Utc.ymd(2001, 9, 9).and_hms_nano(1, 46, 39, nanos)),
2544             UNIX_EPOCH + Duration::new(999_999_999, nanos)
2545         );
2546         assert_eq!(
2547             SystemTime::from(Utc.ymd(1938, 4, 24).and_hms_nano(22, 13, 20, 1_000)),
2548             UNIX_EPOCH - Duration::new(999_999_999, nanos)
2549         );
2550 
2551         // DateTime<any tz> -> SystemTime (via `with_timezone`)
2552         #[cfg(feature = "clock")]
2553         {
2554             assert_eq!(SystemTime::from(epoch.with_timezone(&Local)), UNIX_EPOCH);
2555         }
2556         assert_eq!(SystemTime::from(epoch.with_timezone(&FixedOffset::east(32400))), UNIX_EPOCH);
2557         assert_eq!(SystemTime::from(epoch.with_timezone(&FixedOffset::west(28800))), UNIX_EPOCH);
2558     }
2559 
2560     #[test]
test_datetime_format_alignment()2561     fn test_datetime_format_alignment() {
2562         let datetime = Utc.ymd(2007, 01, 02);
2563 
2564         // Item::Literal
2565         let percent = datetime.format("%%");
2566         assert_eq!("  %", format!("{:>3}", percent));
2567         assert_eq!("%  ", format!("{:<3}", percent));
2568         assert_eq!(" % ", format!("{:^3}", percent));
2569 
2570         // Item::Numeric
2571         let year = datetime.format("%Y");
2572         assert_eq!("  2007", format!("{:>6}", year));
2573         assert_eq!("2007  ", format!("{:<6}", year));
2574         assert_eq!(" 2007 ", format!("{:^6}", year));
2575 
2576         // Item::Fixed
2577         let tz = datetime.format("%Z");
2578         assert_eq!("  UTC", format!("{:>5}", tz));
2579         assert_eq!("UTC  ", format!("{:<5}", tz));
2580         assert_eq!(" UTC ", format!("{:^5}", tz));
2581 
2582         // [Item::Numeric, Item::Space, Item::Literal, Item::Space, Item::Numeric]
2583         let ymd = datetime.format("%Y %B %d");
2584         let ymd_formatted = "2007 January 02";
2585         assert_eq!(format!("  {}", ymd_formatted), format!("{:>17}", ymd));
2586         assert_eq!(format!("{}  ", ymd_formatted), format!("{:<17}", ymd));
2587         assert_eq!(format!(" {} ", ymd_formatted), format!("{:^17}", ymd));
2588     }
2589 }
2590