chrono/
datetime.rs

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