1 // This is a part of Chrono.
2 // See README.md and LICENSE.txt for details.
3 
4 //! A collection of parsed date and time items.
5 //! They can be constructed incrementally while being checked for consistency.
6 
7 use num_traits::ToPrimitive;
8 use oldtime::Duration as OldDuration;
9 
10 use {Datelike, Timelike};
11 use Weekday;
12 use div::div_rem;
13 use offset::{TimeZone, Offset, LocalResult, FixedOffset};
14 use naive::{NaiveDate, NaiveTime, NaiveDateTime};
15 use DateTime;
16 use super::{ParseResult, OUT_OF_RANGE, IMPOSSIBLE, NOT_ENOUGH};
17 
18 /// Parsed parts of date and time. There are two classes of methods:
19 ///
20 /// - `set_*` methods try to set given field(s) while checking for the consistency.
21 ///   It may or may not check for the range constraint immediately (for efficiency reasons).
22 ///
23 /// - `to_*` methods try to make a concrete date and time value out of set fields.
24 ///   It fully checks any remaining out-of-range conditions and inconsistent/impossible fields.
25 #[allow(missing_copy_implementations)]
26 #[derive(Clone, PartialEq, Debug)]
27 pub struct Parsed {
28     /// Year.
29     ///
30     /// This can be negative unlike [`year_div_100`](#structfield.year_div_100)
31     /// and [`year_mod_100`](#structfield.year_mod_100) fields.
32     pub year: Option<i32>,
33 
34     /// Year divided by 100. Implies that the year is >= 1 BCE when set.
35     ///
36     /// Due to the common usage, if this field is missing but
37     /// [`year_mod_100`](#structfield.year_mod_100) is present,
38     /// it is inferred to 19 when `year_mod_100 >= 70` and 20 otherwise.
39     pub year_div_100: Option<i32>,
40 
41     /// Year modulo 100. Implies that the year is >= 1 BCE when set.
42     pub year_mod_100: Option<i32>,
43 
44     /// Year in the [ISO week date](../naive/struct.NaiveDate.html#week-date).
45     ///
46     /// This can be negative unlike [`isoyear_div_100`](#structfield.isoyear_div_100) and
47     /// [`isoyear_mod_100`](#structfield.isoyear_mod_100) fields.
48     pub isoyear: Option<i32>,
49 
50     /// Year in the [ISO week date](../naive/struct.NaiveDate.html#week-date), divided by 100.
51     /// Implies that the year is >= 1 BCE when set.
52     ///
53     /// Due to the common usage, if this field is missing but
54     /// [`isoyear_mod_100`](#structfield.isoyear_mod_100) is present,
55     /// it is inferred to 19 when `isoyear_mod_100 >= 70` and 20 otherwise.
56     pub isoyear_div_100: Option<i32>,
57 
58     /// Year in the [ISO week date](../naive/struct.NaiveDate.html#week-date), modulo 100.
59     /// Implies that the year is >= 1 BCE when set.
60     pub isoyear_mod_100: Option<i32>,
61 
62     /// Month (1--12).
63     pub month: Option<u32>,
64 
65     /// Week number, where the week 1 starts at the first Sunday of January
66     /// (0--53, 1--53 or 1--52 depending on the year).
67     pub week_from_sun: Option<u32>,
68 
69     /// Week number, where the week 1 starts at the first Monday of January
70     /// (0--53, 1--53 or 1--52 depending on the year).
71     pub week_from_mon: Option<u32>,
72 
73     /// [ISO week number](../naive/struct.NaiveDate.html#week-date)
74     /// (1--52 or 1--53 depending on the year).
75     pub isoweek: Option<u32>,
76 
77     /// Day of the week.
78     pub weekday: Option<Weekday>,
79 
80     /// Day of the year (1--365 or 1--366 depending on the year).
81     pub ordinal: Option<u32>,
82 
83     /// Day of the month (1--28, 1--29, 1--30 or 1--31 depending on the month).
84     pub day: Option<u32>,
85 
86     /// Hour number divided by 12 (0--1). 0 indicates AM and 1 indicates PM.
87     pub hour_div_12: Option<u32>,
88 
89     /// Hour number modulo 12 (0--11).
90     pub hour_mod_12: Option<u32>,
91 
92     /// Minute number (0--59).
93     pub minute: Option<u32>,
94 
95     /// Second number (0--60, accounting for leap seconds).
96     pub second: Option<u32>,
97 
98     /// The number of nanoseconds since the whole second (0--999,999,999).
99     pub nanosecond: Option<u32>,
100 
101     /// The number of non-leap seconds since the midnight UTC on January 1, 1970.
102     ///
103     /// This can be off by one if [`second`](#structfield.second) is 60 (a leap second).
104     pub timestamp: Option<i64>,
105 
106     /// Offset from the local time to UTC, in seconds.
107     pub offset: Option<i32>,
108 
109     /// A dummy field to make this type not fully destructible (required for API stability).
110     _dummy: (),
111 }
112 
113 /// Checks if `old` is either empty or has the same value to `new` (i.e. "consistent"),
114 /// and if it is empty, set `old` to `new` as well.
set_if_consistent<T: PartialEq>(old: &mut Option<T>, new: T) -> ParseResult<()>115 fn set_if_consistent<T: PartialEq>(old: &mut Option<T>, new: T) -> ParseResult<()> {
116     if let Some(ref old) = *old {
117         if *old == new {Ok(())} else {Err(IMPOSSIBLE)}
118     } else {
119         *old = Some(new);
120         Ok(())
121     }
122 }
123 
124 impl Default for Parsed {
default() -> Parsed125     fn default() -> Parsed {
126         Parsed {
127             year: None, year_div_100: None, year_mod_100: None, isoyear: None,
128             isoyear_div_100: None, isoyear_mod_100: None, month: None,
129             week_from_sun: None, week_from_mon: None, isoweek: None, weekday: None,
130             ordinal: None, day: None, hour_div_12: None, hour_mod_12: None, minute: None,
131             second: None, nanosecond: None, timestamp: None, offset: None,
132             _dummy: (),
133         }
134     }
135 }
136 
137 impl Parsed {
138     /// Returns the initial value of parsed parts.
new() -> Parsed139     pub fn new() -> Parsed {
140         Parsed::default()
141     }
142 
143     /// Tries to set the [`year`](#structfield.year) field from given value.
set_year(&mut self, value: i64) -> ParseResult<()>144     pub fn set_year(&mut self, value: i64) -> ParseResult<()> {
145         set_if_consistent(&mut self.year, try!(value.to_i32().ok_or(OUT_OF_RANGE)))
146     }
147 
148     /// Tries to set the [`year_div_100`](#structfield.year_div_100) field from given value.
set_year_div_100(&mut self, value: i64) -> ParseResult<()>149     pub fn set_year_div_100(&mut self, value: i64) -> ParseResult<()> {
150         if value < 0 { return Err(OUT_OF_RANGE); }
151         set_if_consistent(&mut self.year_div_100, try!(value.to_i32().ok_or(OUT_OF_RANGE)))
152     }
153 
154     /// Tries to set the [`year_mod_100`](#structfield.year_mod_100) field from given value.
set_year_mod_100(&mut self, value: i64) -> ParseResult<()>155     pub fn set_year_mod_100(&mut self, value: i64) -> ParseResult<()> {
156         if value < 0 { return Err(OUT_OF_RANGE); }
157         set_if_consistent(&mut self.year_mod_100, try!(value.to_i32().ok_or(OUT_OF_RANGE)))
158     }
159 
160     /// Tries to set the [`isoyear`](#structfield.isoyear) field from given value.
set_isoyear(&mut self, value: i64) -> ParseResult<()>161     pub fn set_isoyear(&mut self, value: i64) -> ParseResult<()> {
162         set_if_consistent(&mut self.isoyear, try!(value.to_i32().ok_or(OUT_OF_RANGE)))
163     }
164 
165     /// Tries to set the [`isoyear_div_100`](#structfield.isoyear_div_100) field from given value.
set_isoyear_div_100(&mut self, value: i64) -> ParseResult<()>166     pub fn set_isoyear_div_100(&mut self, value: i64) -> ParseResult<()> {
167         if value < 0 { return Err(OUT_OF_RANGE); }
168         set_if_consistent(&mut self.isoyear_div_100, try!(value.to_i32().ok_or(OUT_OF_RANGE)))
169     }
170 
171     /// Tries to set the [`isoyear_mod_100`](#structfield.isoyear_mod_100) field from given value.
set_isoyear_mod_100(&mut self, value: i64) -> ParseResult<()>172     pub fn set_isoyear_mod_100(&mut self, value: i64) -> ParseResult<()> {
173         if value < 0 { return Err(OUT_OF_RANGE); }
174         set_if_consistent(&mut self.isoyear_mod_100, try!(value.to_i32().ok_or(OUT_OF_RANGE)))
175     }
176 
177     /// Tries to set the [`month`](#structfield.month) field from given value.
set_month(&mut self, value: i64) -> ParseResult<()>178     pub fn set_month(&mut self, value: i64) -> ParseResult<()> {
179         set_if_consistent(&mut self.month, try!(value.to_u32().ok_or(OUT_OF_RANGE)))
180     }
181 
182     /// Tries to set the [`week_from_sun`](#structfield.week_from_sun) field from given value.
set_week_from_sun(&mut self, value: i64) -> ParseResult<()>183     pub fn set_week_from_sun(&mut self, value: i64) -> ParseResult<()> {
184         set_if_consistent(&mut self.week_from_sun, try!(value.to_u32().ok_or(OUT_OF_RANGE)))
185     }
186 
187     /// Tries to set the [`week_from_mon`](#structfield.week_from_mon) field from given value.
set_week_from_mon(&mut self, value: i64) -> ParseResult<()>188     pub fn set_week_from_mon(&mut self, value: i64) -> ParseResult<()> {
189         set_if_consistent(&mut self.week_from_mon, try!(value.to_u32().ok_or(OUT_OF_RANGE)))
190     }
191 
192     /// Tries to set the [`isoweek`](#structfield.isoweek) field from given value.
set_isoweek(&mut self, value: i64) -> ParseResult<()>193     pub fn set_isoweek(&mut self, value: i64) -> ParseResult<()> {
194         set_if_consistent(&mut self.isoweek, try!(value.to_u32().ok_or(OUT_OF_RANGE)))
195     }
196 
197     /// Tries to set the [`weekday`](#structfield.weekday) field from given value.
set_weekday(&mut self, value: Weekday) -> ParseResult<()>198     pub fn set_weekday(&mut self, value: Weekday) -> ParseResult<()> {
199         set_if_consistent(&mut self.weekday, value)
200     }
201 
202     /// Tries to set the [`ordinal`](#structfield.ordinal) field from given value.
set_ordinal(&mut self, value: i64) -> ParseResult<()>203     pub fn set_ordinal(&mut self, value: i64) -> ParseResult<()> {
204         set_if_consistent(&mut self.ordinal, try!(value.to_u32().ok_or(OUT_OF_RANGE)))
205     }
206 
207     /// Tries to set the [`day`](#structfield.day) field from given value.
set_day(&mut self, value: i64) -> ParseResult<()>208     pub fn set_day(&mut self, value: i64) -> ParseResult<()> {
209         set_if_consistent(&mut self.day, try!(value.to_u32().ok_or(OUT_OF_RANGE)))
210     }
211 
212     /// Tries to set the [`hour_div_12`](#structfield.hour_div_12) field from given value.
213     /// (`false` for AM, `true` for PM)
set_ampm(&mut self, value: bool) -> ParseResult<()>214     pub fn set_ampm(&mut self, value: bool) -> ParseResult<()> {
215         set_if_consistent(&mut self.hour_div_12, if value {1} else {0})
216     }
217 
218     /// Tries to set the [`hour_mod_12`](#structfield.hour_mod_12) field from
219     /// given hour number in 12-hour clocks.
set_hour12(&mut self, value: i64) -> ParseResult<()>220     pub fn set_hour12(&mut self, value: i64) -> ParseResult<()> {
221         if value < 1 || value > 12 { return Err(OUT_OF_RANGE); }
222         set_if_consistent(&mut self.hour_mod_12, value as u32 % 12)
223     }
224 
225     /// Tries to set both [`hour_div_12`](#structfield.hour_div_12) and
226     /// [`hour_mod_12`](#structfield.hour_mod_12) fields from given value.
set_hour(&mut self, value: i64) -> ParseResult<()>227     pub fn set_hour(&mut self, value: i64) -> ParseResult<()> {
228         let v = try!(value.to_u32().ok_or(OUT_OF_RANGE));
229         try!(set_if_consistent(&mut self.hour_div_12, v / 12));
230         try!(set_if_consistent(&mut self.hour_mod_12, v % 12));
231         Ok(())
232     }
233 
234     /// Tries to set the [`minute`](#structfield.minute) field from given value.
set_minute(&mut self, value: i64) -> ParseResult<()>235     pub fn set_minute(&mut self, value: i64) -> ParseResult<()> {
236         set_if_consistent(&mut self.minute, try!(value.to_u32().ok_or(OUT_OF_RANGE)))
237     }
238 
239     /// Tries to set the [`second`](#structfield.second) field from given value.
set_second(&mut self, value: i64) -> ParseResult<()>240     pub fn set_second(&mut self, value: i64) -> ParseResult<()> {
241         set_if_consistent(&mut self.second, try!(value.to_u32().ok_or(OUT_OF_RANGE)))
242     }
243 
244     /// Tries to set the [`nanosecond`](#structfield.nanosecond) field from given value.
set_nanosecond(&mut self, value: i64) -> ParseResult<()>245     pub fn set_nanosecond(&mut self, value: i64) -> ParseResult<()> {
246         set_if_consistent(&mut self.nanosecond, try!(value.to_u32().ok_or(OUT_OF_RANGE)))
247     }
248 
249     /// Tries to set the [`timestamp`](#structfield.timestamp) field from given value.
set_timestamp(&mut self, value: i64) -> ParseResult<()>250     pub fn set_timestamp(&mut self, value: i64) -> ParseResult<()> {
251         set_if_consistent(&mut self.timestamp, value)
252     }
253 
254     /// Tries to set the [`offset`](#structfield.offset) field from given value.
set_offset(&mut self, value: i64) -> ParseResult<()>255     pub fn set_offset(&mut self, value: i64) -> ParseResult<()> {
256         set_if_consistent(&mut self.offset, try!(value.to_i32().ok_or(OUT_OF_RANGE)))
257     }
258 
259     /// Returns a parsed naive date out of given fields.
260     ///
261     /// This method is able to determine the date from given subset of fields:
262     ///
263     /// - Year, month, day.
264     /// - Year, day of the year (ordinal).
265     /// - Year, week number counted from Sunday or Monday, day of the week.
266     /// - ISO week date.
267     ///
268     /// Gregorian year and ISO week date year can have their century number (`*_div_100`) omitted,
269     /// the two-digit year is used to guess the century number then.
to_naive_date(&self) -> ParseResult<NaiveDate>270     pub fn to_naive_date(&self) -> ParseResult<NaiveDate> {
271         fn resolve_year(y: Option<i32>, q: Option<i32>,
272                         r: Option<i32>) -> ParseResult<Option<i32>> {
273             match (y, q, r) {
274                 // if there is no further information, simply return the given full year.
275                 // this is a common case, so let's avoid division here.
276                 (y, None, None) => Ok(y),
277 
278                 // if there is a full year *and* also quotient and/or modulo,
279                 // check if present quotient and/or modulo is consistent to the full year.
280                 // since the presence of those fields means a positive full year,
281                 // we should filter a negative full year first.
282                 (Some(y), q, r @ Some(0...99)) | (Some(y), q, r @ None) => {
283                     if y < 0 { return Err(OUT_OF_RANGE); }
284                     let (q_, r_) = div_rem(y, 100);
285                     if q.unwrap_or(q_) == q_ && r.unwrap_or(r_) == r_ {
286                         Ok(Some(y))
287                     } else {
288                         Err(IMPOSSIBLE)
289                     }
290                 },
291 
292                 // the full year is missing but we have quotient and modulo.
293                 // reconstruct the full year. make sure that the result is always positive.
294                 (None, Some(q), Some(r @ 0...99)) => {
295                     if q < 0 { return Err(OUT_OF_RANGE); }
296                     let y = q.checked_mul(100).and_then(|v| v.checked_add(r));
297                     Ok(Some(try!(y.ok_or(OUT_OF_RANGE))))
298                 },
299 
300                 // we only have modulo. try to interpret a modulo as a conventional two-digit year.
301                 // note: we are affected by Rust issue #18060. avoid multiple range patterns.
302                 (None, None, Some(r @ 0...99)) => Ok(Some(r + if r < 70 {2000} else {1900})),
303 
304                 // otherwise it is an out-of-bound or insufficient condition.
305                 (None, Some(_), None) => Err(NOT_ENOUGH),
306                 (_, _, Some(_)) => Err(OUT_OF_RANGE),
307             }
308         }
309 
310         let given_year =
311             try!(resolve_year(self.year, self.year_div_100, self.year_mod_100));
312         let given_isoyear =
313             try!(resolve_year(self.isoyear, self.isoyear_div_100, self.isoyear_mod_100));
314 
315         // verify the normal year-month-day date.
316         let verify_ymd = |date: NaiveDate| {
317             let year = date.year();
318             let (year_div_100, year_mod_100) = if year >= 0 {
319                 let (q, r) = div_rem(year, 100);
320                 (Some(q), Some(r))
321             } else {
322                 (None, None) // they should be empty to be consistent
323             };
324             let month = date.month();
325             let day = date.day();
326             (self.year.unwrap_or(year) == year &&
327              self.year_div_100.or(year_div_100) == year_div_100 &&
328              self.year_mod_100.or(year_mod_100) == year_mod_100 &&
329              self.month.unwrap_or(month) == month &&
330              self.day.unwrap_or(day) == day)
331         };
332 
333         // verify the ISO week date.
334         let verify_isoweekdate = |date: NaiveDate| {
335             let week = date.iso_week();
336             let isoyear = week.year();
337             let isoweek = week.week();
338             let weekday = date.weekday();
339             let (isoyear_div_100, isoyear_mod_100) = if isoyear >= 0 {
340                 let (q, r) = div_rem(isoyear, 100);
341                 (Some(q), Some(r))
342             } else {
343                 (None, None) // they should be empty to be consistent
344             };
345             (self.isoyear.unwrap_or(isoyear) == isoyear &&
346              self.isoyear_div_100.or(isoyear_div_100) == isoyear_div_100 &&
347              self.isoyear_mod_100.or(isoyear_mod_100) == isoyear_mod_100 &&
348              self.isoweek.unwrap_or(isoweek) == isoweek &&
349              self.weekday.unwrap_or(weekday) == weekday)
350         };
351 
352         // verify the ordinal and other (non-ISO) week dates.
353         let verify_ordinal = |date: NaiveDate| {
354             let ordinal = date.ordinal();
355             let weekday = date.weekday();
356             let week_from_sun = (ordinal as i32 - weekday.num_days_from_sunday() as i32 + 7) / 7;
357             let week_from_mon = (ordinal as i32 - weekday.num_days_from_monday() as i32 + 7) / 7;
358             (self.ordinal.unwrap_or(ordinal) == ordinal &&
359              self.week_from_sun.map_or(week_from_sun, |v| v as i32) == week_from_sun &&
360              self.week_from_mon.map_or(week_from_mon, |v| v as i32) == week_from_mon)
361         };
362 
363         // test several possibilities.
364         // tries to construct a full `NaiveDate` as much as possible, then verifies that
365         // it is consistent with other given fields.
366         let (verified, parsed_date) = match (given_year, given_isoyear, self) {
367             (Some(year), _, &Parsed { month: Some(month), day: Some(day), .. }) => {
368                 // year, month, day
369                 let date = try!(NaiveDate::from_ymd_opt(year, month, day).ok_or(OUT_OF_RANGE));
370                 (verify_isoweekdate(date) && verify_ordinal(date), date)
371             },
372 
373             (Some(year), _, &Parsed { ordinal: Some(ordinal), .. }) => {
374                 // year, day of the year
375                 let date = try!(NaiveDate::from_yo_opt(year, ordinal).ok_or(OUT_OF_RANGE));
376                 (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
377             },
378 
379             (Some(year), _, &Parsed { week_from_sun: Some(week_from_sun),
380                                       weekday: Some(weekday), .. }) => {
381                 // year, week (starting at 1st Sunday), day of the week
382                 let newyear = try!(NaiveDate::from_yo_opt(year, 1).ok_or(OUT_OF_RANGE));
383                 let firstweek = match newyear.weekday() {
384                     Weekday::Sun => 0,
385                     Weekday::Mon => 6,
386                     Weekday::Tue => 5,
387                     Weekday::Wed => 4,
388                     Weekday::Thu => 3,
389                     Weekday::Fri => 2,
390                     Weekday::Sat => 1,
391                 };
392 
393                 // `firstweek+1`-th day of January is the beginning of the week 1.
394                 if week_from_sun > 53 { return Err(OUT_OF_RANGE); } // can it overflow?
395                 let ndays = firstweek + (week_from_sun as i32 - 1) * 7 +
396                             weekday.num_days_from_sunday() as i32;
397                 let date = try!(newyear.checked_add_signed(OldDuration::days(i64::from(ndays)))
398                                        .ok_or(OUT_OF_RANGE));
399                 if date.year() != year { return Err(OUT_OF_RANGE); } // early exit for correct error
400 
401                 (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
402             },
403 
404             (Some(year), _, &Parsed { week_from_mon: Some(week_from_mon),
405                                       weekday: Some(weekday), .. }) => {
406                 // year, week (starting at 1st Monday), day of the week
407                 let newyear = try!(NaiveDate::from_yo_opt(year, 1).ok_or(OUT_OF_RANGE));
408                 let firstweek = match newyear.weekday() {
409                     Weekday::Sun => 1,
410                     Weekday::Mon => 0,
411                     Weekday::Tue => 6,
412                     Weekday::Wed => 5,
413                     Weekday::Thu => 4,
414                     Weekday::Fri => 3,
415                     Weekday::Sat => 2,
416                 };
417 
418                 // `firstweek+1`-th day of January is the beginning of the week 1.
419                 if week_from_mon > 53 { return Err(OUT_OF_RANGE); } // can it overflow?
420                 let ndays = firstweek + (week_from_mon as i32 - 1) * 7 +
421                             weekday.num_days_from_monday() as i32;
422                 let date = try!(newyear.checked_add_signed(OldDuration::days(i64::from(ndays)))
423                                        .ok_or(OUT_OF_RANGE));
424                 if date.year() != year { return Err(OUT_OF_RANGE); } // early exit for correct error
425 
426                 (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
427             },
428 
429             (_, Some(isoyear), &Parsed { isoweek: Some(isoweek), weekday: Some(weekday), .. }) => {
430                 // ISO year, week, day of the week
431                 let date = NaiveDate::from_isoywd_opt(isoyear, isoweek, weekday);
432                 let date = try!(date.ok_or(OUT_OF_RANGE));
433                 (verify_ymd(date) && verify_ordinal(date), date)
434             },
435 
436             (_, _, _) => return Err(NOT_ENOUGH)
437         };
438 
439         if verified {
440             Ok(parsed_date)
441         } else {
442             Err(IMPOSSIBLE)
443         }
444     }
445 
446     /// Returns a parsed naive time out of given fields.
447     ///
448     /// This method is able to determine the time from given subset of fields:
449     ///
450     /// - Hour, minute. (second and nanosecond assumed to be 0)
451     /// - Hour, minute, second. (nanosecond assumed to be 0)
452     /// - Hour, minute, second, nanosecond.
453     ///
454     /// It is able to handle leap seconds when given second is 60.
to_naive_time(&self) -> ParseResult<NaiveTime>455     pub fn to_naive_time(&self) -> ParseResult<NaiveTime> {
456         let hour_div_12 = match self.hour_div_12 {
457             Some(v @ 0...1) => v,
458             Some(_) => return Err(OUT_OF_RANGE),
459             None => return Err(NOT_ENOUGH),
460         };
461         let hour_mod_12 = match self.hour_mod_12 {
462             Some(v @ 0...11) => v,
463             Some(_) => return Err(OUT_OF_RANGE),
464             None => return Err(NOT_ENOUGH),
465         };
466         let hour = hour_div_12 * 12 + hour_mod_12;
467 
468         let minute = match self.minute {
469             Some(v @ 0...59) => v,
470             Some(_) => return Err(OUT_OF_RANGE),
471             None => return Err(NOT_ENOUGH),
472         };
473 
474         // we allow omitting seconds or nanoseconds, but they should be in the range.
475         let (second, mut nano) = match self.second.unwrap_or(0) {
476             v @ 0...59 => (v, 0),
477             60 => (59, 1_000_000_000),
478             _ => return Err(OUT_OF_RANGE),
479         };
480         nano += match self.nanosecond {
481             Some(v @ 0...999_999_999) if self.second.is_some() => v,
482             Some(0...999_999_999) => return Err(NOT_ENOUGH), // second is missing
483             Some(_) => return Err(OUT_OF_RANGE),
484             None => 0,
485         };
486 
487         NaiveTime::from_hms_nano_opt(hour, minute, second, nano).ok_or(OUT_OF_RANGE)
488     }
489 
490     /// Returns a parsed naive date and time out of given fields,
491     /// except for the [`offset`](#structfield.offset) field (assumed to have a given value).
492     /// This is required for parsing a local time or other known-timezone inputs.
493     ///
494     /// This method is able to determine the combined date and time
495     /// from date and time fields or a single [`timestamp`](#structfield.timestamp) field.
496     /// Either way those fields have to be consistent to each other.
to_naive_datetime_with_offset(&self, offset: i32) -> ParseResult<NaiveDateTime>497     pub fn to_naive_datetime_with_offset(&self, offset: i32) -> ParseResult<NaiveDateTime> {
498         let date = self.to_naive_date();
499         let time = self.to_naive_time();
500         if let (Ok(date), Ok(time)) = (date, time) {
501             let datetime = date.and_time(time);
502 
503             // verify the timestamp field if any
504             // the following is safe, `timestamp` is very limited in range
505             let timestamp = datetime.timestamp() - i64::from(offset);
506             if let Some(given_timestamp) = self.timestamp {
507                 // if `datetime` represents a leap second, it might be off by one second.
508                 if given_timestamp != timestamp &&
509                    !(datetime.nanosecond() >= 1_000_000_000 && given_timestamp == timestamp + 1) {
510                     return Err(IMPOSSIBLE);
511                 }
512             }
513 
514             Ok(datetime)
515         } else if let Some(timestamp) = self.timestamp {
516             use super::ParseError as PE;
517             use super::ParseErrorKind::{OutOfRange, Impossible};
518 
519             // if date and time is problematic already, there is no point proceeding.
520             // we at least try to give a correct error though.
521             match (date, time) {
522                 (Err(PE(OutOfRange)), _) | (_, Err(PE(OutOfRange))) => return Err(OUT_OF_RANGE),
523                 (Err(PE(Impossible)), _) | (_, Err(PE(Impossible))) => return Err(IMPOSSIBLE),
524                 (_, _) => {} // one of them is insufficient
525             }
526 
527             // reconstruct date and time fields from timestamp
528             let ts = try!(timestamp.checked_add(i64::from(offset)).ok_or(OUT_OF_RANGE));
529             let datetime = NaiveDateTime::from_timestamp_opt(ts, 0);
530             let mut datetime = try!(datetime.ok_or(OUT_OF_RANGE));
531 
532             // fill year, ordinal, hour, minute and second fields from timestamp.
533             // if existing fields are consistent, this will allow the full date/time reconstruction.
534             let mut parsed = self.clone();
535             if parsed.second == Some(60) {
536                 // `datetime.second()` cannot be 60, so this is the only case for a leap second.
537                 match datetime.second() {
538                     // it's okay, just do not try to overwrite the existing field.
539                     59 => {}
540                     // `datetime` is known to be off by one second.
541                     0 => { datetime -= OldDuration::seconds(1); }
542                     // otherwise it is impossible.
543                     _ => return Err(IMPOSSIBLE)
544                 }
545                 // ...and we have the correct candidates for other fields.
546             } else {
547                 try!(parsed.set_second(i64::from(datetime.second())));
548             }
549             try!(parsed.set_year   (i64::from(datetime.year())));
550             try!(parsed.set_ordinal(i64::from(datetime.ordinal()))); // more efficient than ymd
551             try!(parsed.set_hour   (i64::from(datetime.hour())));
552             try!(parsed.set_minute (i64::from(datetime.minute())));
553 
554             // validate other fields (e.g. week) and return
555             let date = try!(parsed.to_naive_date());
556             let time = try!(parsed.to_naive_time());
557             Ok(date.and_time(time))
558         } else {
559             // reproduce the previous error(s)
560             try!(date);
561             try!(time);
562             unreachable!()
563         }
564     }
565 
566     /// Returns a parsed fixed time zone offset out of given fields.
to_fixed_offset(&self) -> ParseResult<FixedOffset>567     pub fn to_fixed_offset(&self) -> ParseResult<FixedOffset> {
568         self.offset.and_then(FixedOffset::east_opt).ok_or(OUT_OF_RANGE)
569     }
570 
571     /// Returns a parsed timezone-aware date and time out of given fields.
572     ///
573     /// This method is able to determine the combined date and time
574     /// from date and time fields or a single [`timestamp`](#structfield.timestamp) field,
575     /// plus a time zone offset.
576     /// Either way those fields have to be consistent to each other.
to_datetime(&self) -> ParseResult<DateTime<FixedOffset>>577     pub fn to_datetime(&self) -> ParseResult<DateTime<FixedOffset>> {
578         let offset = try!(self.offset.ok_or(NOT_ENOUGH));
579         let datetime = try!(self.to_naive_datetime_with_offset(offset));
580         let offset = try!(FixedOffset::east_opt(offset).ok_or(OUT_OF_RANGE));
581         match offset.from_local_datetime(&datetime) {
582             LocalResult::None => Err(IMPOSSIBLE),
583             LocalResult::Single(t) => Ok(t),
584             LocalResult::Ambiguous(..) => Err(NOT_ENOUGH),
585         }
586     }
587 
588     /// Returns a parsed timezone-aware date and time out of given fields,
589     /// with an additional `TimeZone` used to interpret and validate the local date.
590     ///
591     /// This method is able to determine the combined date and time
592     /// from date and time fields or a single [`timestamp`](#structfield.timestamp) field,
593     /// plus a time zone offset.
594     /// Either way those fields have to be consistent to each other.
595     /// If parsed fields include an UTC offset, it also has to be consistent to
596     /// [`offset`](#structfield.offset).
to_datetime_with_timezone<Tz: TimeZone>(&self, tz: &Tz) -> ParseResult<DateTime<Tz>>597     pub fn to_datetime_with_timezone<Tz: TimeZone>(&self, tz: &Tz) -> ParseResult<DateTime<Tz>> {
598         // if we have `timestamp` specified, guess an offset from that.
599         let mut guessed_offset = 0;
600         if let Some(timestamp) = self.timestamp {
601             // make a naive `DateTime` from given timestamp and (if any) nanosecond.
602             // an empty `nanosecond` is always equal to zero, so missing nanosecond is fine.
603             let nanosecond = self.nanosecond.unwrap_or(0);
604             let dt = NaiveDateTime::from_timestamp_opt(timestamp, nanosecond);
605             let dt = try!(dt.ok_or(OUT_OF_RANGE));
606             guessed_offset = tz.offset_from_utc_datetime(&dt).fix().local_minus_utc();
607         }
608 
609         // checks if the given `DateTime` has a consistent `Offset` with given `self.offset`.
610         let check_offset = |dt: &DateTime<Tz>| {
611             if let Some(offset) = self.offset {
612                 dt.offset().fix().local_minus_utc() == offset
613             } else {
614                 true
615             }
616         };
617 
618         // `guessed_offset` should be correct when `self.timestamp` is given.
619         // it will be 0 otherwise, but this is fine as the algorithm ignores offset for that case.
620         let datetime = try!(self.to_naive_datetime_with_offset(guessed_offset));
621         match tz.from_local_datetime(&datetime) {
622             LocalResult::None => Err(IMPOSSIBLE),
623             LocalResult::Single(t) => if check_offset(&t) {Ok(t)} else {Err(IMPOSSIBLE)},
624             LocalResult::Ambiguous(min, max) => {
625                 // try to disambiguate two possible local dates by offset.
626                 match (check_offset(&min), check_offset(&max)) {
627                     (false, false) => Err(IMPOSSIBLE),
628                     (false, true) => Ok(max),
629                     (true, false) => Ok(min),
630                     (true, true) => Err(NOT_ENOUGH),
631                 }
632             }
633         }
634     }
635 }
636 
637 #[cfg(test)]
638 mod tests {
639     use super::Parsed;
640     use super::super::{OUT_OF_RANGE, IMPOSSIBLE, NOT_ENOUGH};
641     use Datelike;
642     use Weekday::*;
643     use naive::{MIN_DATE, MAX_DATE, NaiveDate, NaiveTime};
644     use offset::{TimeZone, Utc, FixedOffset};
645 
646     #[test]
test_parsed_set_fields()647     fn test_parsed_set_fields() {
648         // year*, isoyear*
649         let mut p = Parsed::new();
650         assert_eq!(p.set_year(1987), Ok(()));
651         assert_eq!(p.set_year(1986), Err(IMPOSSIBLE));
652         assert_eq!(p.set_year(1988), Err(IMPOSSIBLE));
653         assert_eq!(p.set_year(1987), Ok(()));
654         assert_eq!(p.set_year_div_100(20), Ok(())); // independent to `year`
655         assert_eq!(p.set_year_div_100(21), Err(IMPOSSIBLE));
656         assert_eq!(p.set_year_div_100(19), Err(IMPOSSIBLE));
657         assert_eq!(p.set_year_mod_100(37), Ok(())); // ditto
658         assert_eq!(p.set_year_mod_100(38), Err(IMPOSSIBLE));
659         assert_eq!(p.set_year_mod_100(36), Err(IMPOSSIBLE));
660 
661         let mut p = Parsed::new();
662         assert_eq!(p.set_year(0), Ok(()));
663         assert_eq!(p.set_year_div_100(0), Ok(()));
664         assert_eq!(p.set_year_mod_100(0), Ok(()));
665 
666         let mut p = Parsed::new();
667         assert_eq!(p.set_year_div_100(-1), Err(OUT_OF_RANGE));
668         assert_eq!(p.set_year_mod_100(-1), Err(OUT_OF_RANGE));
669         assert_eq!(p.set_year(-1), Ok(()));
670         assert_eq!(p.set_year(-2), Err(IMPOSSIBLE));
671         assert_eq!(p.set_year(0), Err(IMPOSSIBLE));
672 
673         let mut p = Parsed::new();
674         assert_eq!(p.set_year_div_100(0x1_0000_0008), Err(OUT_OF_RANGE));
675         assert_eq!(p.set_year_div_100(8), Ok(()));
676         assert_eq!(p.set_year_div_100(0x1_0000_0008), Err(OUT_OF_RANGE));
677 
678         // month, week*, isoweek, ordinal, day, minute, second, nanosecond, offset
679         let mut p = Parsed::new();
680         assert_eq!(p.set_month(7), Ok(()));
681         assert_eq!(p.set_month(1), Err(IMPOSSIBLE));
682         assert_eq!(p.set_month(6), Err(IMPOSSIBLE));
683         assert_eq!(p.set_month(8), Err(IMPOSSIBLE));
684         assert_eq!(p.set_month(12), Err(IMPOSSIBLE));
685 
686         let mut p = Parsed::new();
687         assert_eq!(p.set_month(8), Ok(()));
688         assert_eq!(p.set_month(0x1_0000_0008), Err(OUT_OF_RANGE));
689 
690         // hour
691         let mut p = Parsed::new();
692         assert_eq!(p.set_hour(12), Ok(()));
693         assert_eq!(p.set_hour(11), Err(IMPOSSIBLE));
694         assert_eq!(p.set_hour(13), Err(IMPOSSIBLE));
695         assert_eq!(p.set_hour(12), Ok(()));
696         assert_eq!(p.set_ampm(false), Err(IMPOSSIBLE));
697         assert_eq!(p.set_ampm(true), Ok(()));
698         assert_eq!(p.set_hour12(12), Ok(()));
699         assert_eq!(p.set_hour12(0), Err(OUT_OF_RANGE)); // requires canonical representation
700         assert_eq!(p.set_hour12(1), Err(IMPOSSIBLE));
701         assert_eq!(p.set_hour12(11), Err(IMPOSSIBLE));
702 
703         let mut p = Parsed::new();
704         assert_eq!(p.set_ampm(true), Ok(()));
705         assert_eq!(p.set_hour12(7), Ok(()));
706         assert_eq!(p.set_hour(7), Err(IMPOSSIBLE));
707         assert_eq!(p.set_hour(18), Err(IMPOSSIBLE));
708         assert_eq!(p.set_hour(19), Ok(()));
709 
710         // timestamp
711         let mut p = Parsed::new();
712         assert_eq!(p.set_timestamp(1_234_567_890), Ok(()));
713         assert_eq!(p.set_timestamp(1_234_567_889), Err(IMPOSSIBLE));
714         assert_eq!(p.set_timestamp(1_234_567_891), Err(IMPOSSIBLE));
715     }
716 
717     #[test]
test_parsed_to_naive_date()718     fn test_parsed_to_naive_date() {
719         macro_rules! parse {
720             ($($k:ident: $v:expr),*) => (
721                 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_naive_date()
722             )
723         }
724 
725         let ymd = |y,m,d| Ok(NaiveDate::from_ymd(y, m, d));
726 
727         // ymd: omission of fields
728         assert_eq!(parse!(), Err(NOT_ENOUGH));
729         assert_eq!(parse!(year: 1984), Err(NOT_ENOUGH));
730         assert_eq!(parse!(year: 1984, month: 1), Err(NOT_ENOUGH));
731         assert_eq!(parse!(year: 1984, month: 1, day: 2), ymd(1984, 1, 2));
732         assert_eq!(parse!(year: 1984, day: 2), Err(NOT_ENOUGH));
733         assert_eq!(parse!(year_div_100: 19), Err(NOT_ENOUGH));
734         assert_eq!(parse!(year_div_100: 19, year_mod_100: 84), Err(NOT_ENOUGH));
735         assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, month: 1), Err(NOT_ENOUGH));
736         assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, month: 1, day: 2), ymd(1984, 1, 2));
737         assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, day: 2), Err(NOT_ENOUGH));
738         assert_eq!(parse!(year_div_100: 19, month: 1, day: 2), Err(NOT_ENOUGH));
739         assert_eq!(parse!(year_mod_100: 70, month: 1, day: 2), ymd(1970, 1, 2));
740         assert_eq!(parse!(year_mod_100: 69, month: 1, day: 2), ymd(2069, 1, 2));
741 
742         // ymd: out-of-range conditions
743         assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, month: 2, day: 29),
744                    ymd(1984, 2, 29));
745         assert_eq!(parse!(year_div_100: 19, year_mod_100: 83, month: 2, day: 29),
746                    Err(OUT_OF_RANGE));
747         assert_eq!(parse!(year_div_100: 19, year_mod_100: 83, month: 13, day: 1),
748                    Err(OUT_OF_RANGE));
749         assert_eq!(parse!(year_div_100: 19, year_mod_100: 83, month: 12, day: 31),
750                    ymd(1983, 12, 31));
751         assert_eq!(parse!(year_div_100: 19, year_mod_100: 83, month: 12, day: 32),
752                    Err(OUT_OF_RANGE));
753         assert_eq!(parse!(year_div_100: 19, year_mod_100: 83, month: 12, day: 0),
754                    Err(OUT_OF_RANGE));
755         assert_eq!(parse!(year_div_100: 19, year_mod_100: 100, month: 1, day: 1),
756                    Err(OUT_OF_RANGE));
757         assert_eq!(parse!(year_div_100: 19, year_mod_100: -1, month: 1, day: 1),
758                    Err(OUT_OF_RANGE));
759         assert_eq!(parse!(year_div_100: 0, year_mod_100: 0, month: 1, day: 1),
760                    ymd(0, 1, 1));
761         assert_eq!(parse!(year_div_100: -1, year_mod_100: 42, month: 1, day: 1),
762                    Err(OUT_OF_RANGE));
763         let max_year = MAX_DATE.year();
764         assert_eq!(parse!(year_div_100: max_year / 100,
765                           year_mod_100: max_year % 100, month: 1, day: 1),
766                    ymd(max_year, 1, 1));
767         assert_eq!(parse!(year_div_100: (max_year + 1) / 100,
768                           year_mod_100: (max_year + 1) % 100, month: 1, day: 1),
769                    Err(OUT_OF_RANGE));
770 
771         // ymd: conflicting inputs
772         assert_eq!(parse!(year: 1984, year_div_100: 19, month: 1, day: 1), ymd(1984, 1, 1));
773         assert_eq!(parse!(year: 1984, year_div_100: 20, month: 1, day: 1), Err(IMPOSSIBLE));
774         assert_eq!(parse!(year: 1984, year_mod_100: 84, month: 1, day: 1), ymd(1984, 1, 1));
775         assert_eq!(parse!(year: 1984, year_mod_100: 83, month: 1, day: 1), Err(IMPOSSIBLE));
776         assert_eq!(parse!(year: 1984, year_div_100: 19, year_mod_100: 84, month: 1, day: 1),
777                    ymd(1984, 1, 1));
778         assert_eq!(parse!(year: 1984, year_div_100: 18, year_mod_100: 94, month: 1, day: 1),
779                    Err(IMPOSSIBLE));
780         assert_eq!(parse!(year: 1984, year_div_100: 18, year_mod_100: 184, month: 1, day: 1),
781                    Err(OUT_OF_RANGE));
782         assert_eq!(parse!(year: -1, year_div_100: 0, year_mod_100: -1, month: 1, day: 1),
783                    Err(OUT_OF_RANGE));
784         assert_eq!(parse!(year: -1, year_div_100: -1, year_mod_100: 99, month: 1, day: 1),
785                    Err(OUT_OF_RANGE));
786         assert_eq!(parse!(year: -1, year_div_100: 0, month: 1, day: 1), Err(OUT_OF_RANGE));
787         assert_eq!(parse!(year: -1, year_mod_100: 99, month: 1, day: 1), Err(OUT_OF_RANGE));
788 
789         // weekdates
790         assert_eq!(parse!(year: 2000, week_from_mon: 0), Err(NOT_ENOUGH));
791         assert_eq!(parse!(year: 2000, week_from_sun: 0), Err(NOT_ENOUGH));
792         assert_eq!(parse!(year: 2000, weekday: Sun), Err(NOT_ENOUGH));
793         assert_eq!(parse!(year: 2000, week_from_mon: 0, weekday: Fri), Err(OUT_OF_RANGE));
794         assert_eq!(parse!(year: 2000, week_from_sun: 0, weekday: Fri), Err(OUT_OF_RANGE));
795         assert_eq!(parse!(year: 2000, week_from_mon: 0, weekday: Sat), ymd(2000, 1, 1));
796         assert_eq!(parse!(year: 2000, week_from_sun: 0, weekday: Sat), ymd(2000, 1, 1));
797         assert_eq!(parse!(year: 2000, week_from_mon: 0, weekday: Sun), ymd(2000, 1, 2));
798         assert_eq!(parse!(year: 2000, week_from_sun: 1, weekday: Sun), ymd(2000, 1, 2));
799         assert_eq!(parse!(year: 2000, week_from_mon: 1, weekday: Mon), ymd(2000, 1, 3));
800         assert_eq!(parse!(year: 2000, week_from_sun: 1, weekday: Mon), ymd(2000, 1, 3));
801         assert_eq!(parse!(year: 2000, week_from_mon: 1, weekday: Sat), ymd(2000, 1, 8));
802         assert_eq!(parse!(year: 2000, week_from_sun: 1, weekday: Sat), ymd(2000, 1, 8));
803         assert_eq!(parse!(year: 2000, week_from_mon: 1, weekday: Sun), ymd(2000, 1, 9));
804         assert_eq!(parse!(year: 2000, week_from_sun: 2, weekday: Sun), ymd(2000, 1, 9));
805         assert_eq!(parse!(year: 2000, week_from_mon: 2, weekday: Mon), ymd(2000, 1, 10));
806         assert_eq!(parse!(year: 2000, week_from_sun: 52, weekday: Sat), ymd(2000, 12, 30));
807         assert_eq!(parse!(year: 2000, week_from_sun: 53, weekday: Sun), ymd(2000, 12, 31));
808         assert_eq!(parse!(year: 2000, week_from_sun: 53, weekday: Mon), Err(OUT_OF_RANGE));
809         assert_eq!(parse!(year: 2000, week_from_sun: 0xffffffff, weekday: Mon), Err(OUT_OF_RANGE));
810         assert_eq!(parse!(year: 2006, week_from_sun: 0, weekday: Sat), Err(OUT_OF_RANGE));
811         assert_eq!(parse!(year: 2006, week_from_sun: 1, weekday: Sun), ymd(2006, 1, 1));
812 
813         // weekdates: conflicting inputs
814         assert_eq!(parse!(year: 2000, week_from_mon: 1, week_from_sun: 1, weekday: Sat),
815                    ymd(2000, 1, 8));
816         assert_eq!(parse!(year: 2000, week_from_mon: 1, week_from_sun: 2, weekday: Sun),
817                    ymd(2000, 1, 9));
818         assert_eq!(parse!(year: 2000, week_from_mon: 1, week_from_sun: 1, weekday: Sun),
819                    Err(IMPOSSIBLE));
820         assert_eq!(parse!(year: 2000, week_from_mon: 2, week_from_sun: 2, weekday: Sun),
821                    Err(IMPOSSIBLE));
822 
823         // ISO weekdates
824         assert_eq!(parse!(isoyear: 2004, isoweek: 53), Err(NOT_ENOUGH));
825         assert_eq!(parse!(isoyear: 2004, isoweek: 53, weekday: Fri), ymd(2004, 12, 31));
826         assert_eq!(parse!(isoyear: 2004, isoweek: 53, weekday: Sat), ymd(2005, 1, 1));
827         assert_eq!(parse!(isoyear: 2004, isoweek: 0xffffffff, weekday: Sat), Err(OUT_OF_RANGE));
828         assert_eq!(parse!(isoyear: 2005, isoweek: 0, weekday: Thu), Err(OUT_OF_RANGE));
829         assert_eq!(parse!(isoyear: 2005, isoweek: 5, weekday: Thu), ymd(2005, 2, 3));
830         assert_eq!(parse!(isoyear: 2005, weekday: Thu), Err(NOT_ENOUGH));
831 
832         // year and ordinal
833         assert_eq!(parse!(ordinal: 123), Err(NOT_ENOUGH));
834         assert_eq!(parse!(year: 2000, ordinal: 0), Err(OUT_OF_RANGE));
835         assert_eq!(parse!(year: 2000, ordinal: 1), ymd(2000, 1, 1));
836         assert_eq!(parse!(year: 2000, ordinal: 60), ymd(2000, 2, 29));
837         assert_eq!(parse!(year: 2000, ordinal: 61), ymd(2000, 3, 1));
838         assert_eq!(parse!(year: 2000, ordinal: 366), ymd(2000, 12, 31));
839         assert_eq!(parse!(year: 2000, ordinal: 367), Err(OUT_OF_RANGE));
840         assert_eq!(parse!(year: 2000, ordinal: 0xffffffff), Err(OUT_OF_RANGE));
841         assert_eq!(parse!(year: 2100, ordinal: 0), Err(OUT_OF_RANGE));
842         assert_eq!(parse!(year: 2100, ordinal: 1), ymd(2100, 1, 1));
843         assert_eq!(parse!(year: 2100, ordinal: 59), ymd(2100, 2, 28));
844         assert_eq!(parse!(year: 2100, ordinal: 60), ymd(2100, 3, 1));
845         assert_eq!(parse!(year: 2100, ordinal: 365), ymd(2100, 12, 31));
846         assert_eq!(parse!(year: 2100, ordinal: 366), Err(OUT_OF_RANGE));
847         assert_eq!(parse!(year: 2100, ordinal: 0xffffffff), Err(OUT_OF_RANGE));
848 
849         // more complex cases
850         assert_eq!(parse!(year: 2014, month: 12, day: 31, ordinal: 365, isoyear: 2015, isoweek: 1,
851                           week_from_sun: 52, week_from_mon: 52, weekday: Wed),
852                    ymd(2014, 12, 31));
853         assert_eq!(parse!(year: 2014, month: 12, ordinal: 365, isoyear: 2015, isoweek: 1,
854                           week_from_sun: 52, week_from_mon: 52),
855                    ymd(2014, 12, 31));
856         assert_eq!(parse!(year: 2014, month: 12, day: 31, ordinal: 365, isoyear: 2014, isoweek: 53,
857                           week_from_sun: 52, week_from_mon: 52, weekday: Wed),
858                    Err(IMPOSSIBLE)); // no ISO week date 2014-W53-3
859         assert_eq!(parse!(year: 2012, isoyear: 2015, isoweek: 1,
860                           week_from_sun: 52, week_from_mon: 52),
861                    Err(NOT_ENOUGH)); // ambiguous (2014-12-29, 2014-12-30, 2014-12-31)
862         assert_eq!(parse!(year_div_100: 20, isoyear_mod_100: 15, ordinal: 366),
863                    Err(NOT_ENOUGH)); // technically unique (2014-12-31) but Chrono gives up
864     }
865 
866     #[test]
test_parsed_to_naive_time()867     fn test_parsed_to_naive_time() {
868         macro_rules! parse {
869             ($($k:ident: $v:expr),*) => (
870                 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_naive_time()
871             )
872         }
873 
874         let hms = |h,m,s| Ok(NaiveTime::from_hms(h, m, s));
875         let hmsn = |h,m,s,n| Ok(NaiveTime::from_hms_nano(h, m, s, n));
876 
877         // omission of fields
878         assert_eq!(parse!(), Err(NOT_ENOUGH));
879         assert_eq!(parse!(hour_div_12: 0), Err(NOT_ENOUGH));
880         assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1), Err(NOT_ENOUGH));
881         assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23), hms(1,23,0));
882         assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 45), hms(1,23,45));
883         assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 45,
884                           nanosecond: 678_901_234),
885                    hmsn(1,23,45,678_901_234));
886         assert_eq!(parse!(hour_div_12: 1, hour_mod_12: 11, minute: 45, second: 6), hms(23,45,6));
887         assert_eq!(parse!(hour_mod_12: 1, minute: 23), Err(NOT_ENOUGH));
888         assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, nanosecond: 456_789_012),
889                    Err(NOT_ENOUGH));
890 
891         // out-of-range conditions
892         assert_eq!(parse!(hour_div_12: 2, hour_mod_12: 0, minute: 0), Err(OUT_OF_RANGE));
893         assert_eq!(parse!(hour_div_12: 1, hour_mod_12: 12, minute: 0), Err(OUT_OF_RANGE));
894         assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 60), Err(OUT_OF_RANGE));
895         assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 61),
896                    Err(OUT_OF_RANGE));
897         assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 34,
898                           nanosecond: 1_000_000_000),
899                    Err(OUT_OF_RANGE));
900 
901         // leap seconds
902         assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 60),
903                    hmsn(1,23,59,1_000_000_000));
904         assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 60,
905                           nanosecond: 999_999_999),
906                    hmsn(1,23,59,1_999_999_999));
907     }
908 
909     #[test]
test_parsed_to_naive_datetime_with_offset()910     fn test_parsed_to_naive_datetime_with_offset() {
911         macro_rules! parse {
912             (offset = $offset:expr; $($k:ident: $v:expr),*) => (
913                 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_naive_datetime_with_offset($offset)
914             );
915             ($($k:ident: $v:expr),*) => (parse!(offset = 0; $($k: $v),*))
916         }
917 
918         let ymdhms = |y,m,d,h,n,s| Ok(NaiveDate::from_ymd(y, m, d).and_hms(h, n, s));
919         let ymdhmsn =
920             |y,m,d,h,n,s,nano| Ok(NaiveDate::from_ymd(y, m, d).and_hms_nano(h, n, s, nano));
921 
922         // omission of fields
923         assert_eq!(parse!(), Err(NOT_ENOUGH));
924         assert_eq!(parse!(year: 2015, month: 1, day: 30,
925                           hour_div_12: 1, hour_mod_12: 2, minute: 38),
926                    ymdhms(2015,1,30, 14,38,0));
927         assert_eq!(parse!(year: 1997, month: 1, day: 30,
928                           hour_div_12: 1, hour_mod_12: 2, minute: 38, second: 5),
929                    ymdhms(1997,1,30, 14,38,5));
930         assert_eq!(parse!(year: 2012, ordinal: 34, hour_div_12: 0, hour_mod_12: 5,
931                           minute: 6, second: 7, nanosecond: 890_123_456),
932                    ymdhmsn(2012,2,3, 5,6,7,890_123_456));
933         assert_eq!(parse!(timestamp: 0), ymdhms(1970,1,1, 0,0,0));
934         assert_eq!(parse!(timestamp: 1, nanosecond: 0), ymdhms(1970,1,1, 0,0,1));
935         assert_eq!(parse!(timestamp: 1, nanosecond: 1), ymdhmsn(1970,1,1, 0,0,1, 1));
936         assert_eq!(parse!(timestamp: 1_420_000_000), ymdhms(2014,12,31, 4,26,40));
937         assert_eq!(parse!(timestamp: -0x1_0000_0000), ymdhms(1833,11,24, 17,31,44));
938 
939         // full fields
940         assert_eq!(parse!(year: 2014, year_div_100: 20, year_mod_100: 14, month: 12, day: 31,
941                           ordinal: 365, isoyear: 2015, isoyear_div_100: 20, isoyear_mod_100: 15,
942                           isoweek: 1, week_from_sun: 52, week_from_mon: 52, weekday: Wed,
943                           hour_div_12: 0, hour_mod_12: 4, minute: 26, second: 40,
944                           nanosecond: 12_345_678, timestamp: 1_420_000_000),
945                    ymdhmsn(2014,12,31, 4,26,40,12_345_678));
946         assert_eq!(parse!(year: 2014, year_div_100: 20, year_mod_100: 14, month: 12, day: 31,
947                           ordinal: 365, isoyear: 2015, isoyear_div_100: 20, isoyear_mod_100: 15,
948                           isoweek: 1, week_from_sun: 52, week_from_mon: 52, weekday: Wed,
949                           hour_div_12: 0, hour_mod_12: 4, minute: 26, second: 40,
950                           nanosecond: 12_345_678, timestamp: 1_419_999_999),
951                    Err(IMPOSSIBLE));
952         assert_eq!(parse!(offset = 32400;
953                           year: 2014, year_div_100: 20, year_mod_100: 14, month: 12, day: 31,
954                           ordinal: 365, isoyear: 2015, isoyear_div_100: 20, isoyear_mod_100: 15,
955                           isoweek: 1, week_from_sun: 52, week_from_mon: 52, weekday: Wed,
956                           hour_div_12: 0, hour_mod_12: 4, minute: 26, second: 40,
957                           nanosecond: 12_345_678, timestamp: 1_419_967_600),
958                    ymdhmsn(2014,12,31, 4,26,40,12_345_678));
959 
960         // more timestamps
961         let max_days_from_year_1970 =
962             MAX_DATE.signed_duration_since(NaiveDate::from_ymd(1970,1,1));
963         let year_0_from_year_1970 =
964             NaiveDate::from_ymd(0,1,1).signed_duration_since(NaiveDate::from_ymd(1970,1,1));
965         let min_days_from_year_1970 =
966             MIN_DATE.signed_duration_since(NaiveDate::from_ymd(1970,1,1));
967         assert_eq!(parse!(timestamp: min_days_from_year_1970.num_seconds()),
968                    ymdhms(MIN_DATE.year(),1,1, 0,0,0));
969         assert_eq!(parse!(timestamp: year_0_from_year_1970.num_seconds()),
970                    ymdhms(0,1,1, 0,0,0));
971         assert_eq!(parse!(timestamp: max_days_from_year_1970.num_seconds() + 86399),
972                    ymdhms(MAX_DATE.year(),12,31, 23,59,59));
973 
974         // leap seconds #1: partial fields
975         assert_eq!(parse!(second: 59, timestamp: 1_341_100_798), Err(IMPOSSIBLE));
976         assert_eq!(parse!(second: 59, timestamp: 1_341_100_799), ymdhms(2012,6,30, 23,59,59));
977         assert_eq!(parse!(second: 59, timestamp: 1_341_100_800), Err(IMPOSSIBLE));
978         assert_eq!(parse!(second: 60, timestamp: 1_341_100_799),
979                    ymdhmsn(2012,6,30, 23,59,59,1_000_000_000));
980         assert_eq!(parse!(second: 60, timestamp: 1_341_100_800),
981                    ymdhmsn(2012,6,30, 23,59,59,1_000_000_000));
982         assert_eq!(parse!(second: 0, timestamp: 1_341_100_800), ymdhms(2012,7,1, 0,0,0));
983         assert_eq!(parse!(second: 1, timestamp: 1_341_100_800), Err(IMPOSSIBLE));
984         assert_eq!(parse!(second: 60, timestamp: 1_341_100_801), Err(IMPOSSIBLE));
985 
986         // leap seconds #2: full fields
987         // we need to have separate tests for them since it uses another control flow.
988         assert_eq!(parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
989                           minute: 59, second: 59, timestamp: 1_341_100_798),
990                    Err(IMPOSSIBLE));
991         assert_eq!(parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
992                           minute: 59, second: 59, timestamp: 1_341_100_799),
993                    ymdhms(2012,6,30, 23,59,59));
994         assert_eq!(parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
995                           minute: 59, second: 59, timestamp: 1_341_100_800),
996                    Err(IMPOSSIBLE));
997         assert_eq!(parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
998                           minute: 59, second: 60, timestamp: 1_341_100_799),
999                    ymdhmsn(2012,6,30, 23,59,59,1_000_000_000));
1000         assert_eq!(parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1001                           minute: 59, second: 60, timestamp: 1_341_100_800),
1002                    ymdhmsn(2012,6,30, 23,59,59,1_000_000_000));
1003         assert_eq!(parse!(year: 2012, ordinal: 183, hour_div_12: 0, hour_mod_12: 0,
1004                           minute: 0, second: 0, timestamp: 1_341_100_800),
1005                    ymdhms(2012,7,1, 0,0,0));
1006         assert_eq!(parse!(year: 2012, ordinal: 183, hour_div_12: 0, hour_mod_12: 0,
1007                           minute: 0, second: 1, timestamp: 1_341_100_800),
1008                    Err(IMPOSSIBLE));
1009         assert_eq!(parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1010                           minute: 59, second: 60, timestamp: 1_341_100_801),
1011                    Err(IMPOSSIBLE));
1012 
1013         // error codes
1014         assert_eq!(parse!(year: 2015, month: 1, day: 20, weekday: Tue,
1015                           hour_div_12: 2, hour_mod_12: 1, minute: 35, second: 20),
1016                    Err(OUT_OF_RANGE)); // `hour_div_12` is out of range
1017     }
1018 
1019     #[test]
test_parsed_to_datetime()1020     fn test_parsed_to_datetime() {
1021         macro_rules! parse {
1022             ($($k:ident: $v:expr),*) => (
1023                 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_datetime()
1024             )
1025         }
1026 
1027         let ymdhmsn = |y,m,d,h,n,s,nano,off| Ok(FixedOffset::east(off).ymd(y, m, d)
1028                                                                       .and_hms_nano(h, n, s, nano));
1029 
1030         assert_eq!(parse!(offset: 0), Err(NOT_ENOUGH));
1031         assert_eq!(parse!(year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1032                           minute: 26, second: 40, nanosecond: 12_345_678),
1033                    Err(NOT_ENOUGH));
1034         assert_eq!(parse!(year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1035                           minute: 26, second: 40, nanosecond: 12_345_678, offset: 0),
1036                    ymdhmsn(2014,12,31, 4,26,40,12_345_678, 0));
1037         assert_eq!(parse!(year: 2014, ordinal: 365, hour_div_12: 1, hour_mod_12: 1,
1038                           minute: 26, second: 40, nanosecond: 12_345_678, offset: 32400),
1039                    ymdhmsn(2014,12,31, 13,26,40,12_345_678, 32400));
1040         assert_eq!(parse!(year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 1,
1041                           minute: 42, second: 4, nanosecond: 12_345_678, offset: -9876),
1042                    ymdhmsn(2014,12,31, 1,42,4,12_345_678, -9876));
1043         assert_eq!(parse!(year: 2015, ordinal: 1, hour_div_12: 0, hour_mod_12: 4,
1044                           minute: 26, second: 40, nanosecond: 12_345_678, offset: 86_400),
1045                    Err(OUT_OF_RANGE)); // `FixedOffset` does not support such huge offset
1046     }
1047 
1048     #[test]
test_parsed_to_datetime_with_timezone()1049     fn test_parsed_to_datetime_with_timezone() {
1050         macro_rules! parse {
1051             ($tz:expr; $($k:ident: $v:expr),*) => (
1052                 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_datetime_with_timezone(&$tz)
1053             )
1054         }
1055 
1056         // single result from ymdhms
1057         assert_eq!(parse!(Utc;
1058                           year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1059                           minute: 26, second: 40, nanosecond: 12_345_678, offset: 0),
1060                    Ok(Utc.ymd(2014, 12, 31).and_hms_nano(4, 26, 40, 12_345_678)));
1061         assert_eq!(parse!(Utc;
1062                           year: 2014, ordinal: 365, hour_div_12: 1, hour_mod_12: 1,
1063                           minute: 26, second: 40, nanosecond: 12_345_678, offset: 32400),
1064                    Err(IMPOSSIBLE));
1065         assert_eq!(parse!(FixedOffset::east(32400);
1066                           year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1067                           minute: 26, second: 40, nanosecond: 12_345_678, offset: 0),
1068                    Err(IMPOSSIBLE));
1069         assert_eq!(parse!(FixedOffset::east(32400);
1070                           year: 2014, ordinal: 365, hour_div_12: 1, hour_mod_12: 1,
1071                           minute: 26, second: 40, nanosecond: 12_345_678, offset: 32400),
1072                    Ok(FixedOffset::east(32400).ymd(2014, 12, 31)
1073                                               .and_hms_nano(13, 26, 40, 12_345_678)));
1074 
1075         // single result from timestamp
1076         assert_eq!(parse!(Utc; timestamp: 1_420_000_000, offset: 0),
1077                    Ok(Utc.ymd(2014, 12, 31).and_hms(4, 26, 40)));
1078         assert_eq!(parse!(Utc; timestamp: 1_420_000_000, offset: 32400),
1079                    Err(IMPOSSIBLE));
1080         assert_eq!(parse!(FixedOffset::east(32400); timestamp: 1_420_000_000, offset: 0),
1081                    Err(IMPOSSIBLE));
1082         assert_eq!(parse!(FixedOffset::east(32400); timestamp: 1_420_000_000, offset: 32400),
1083                    Ok(FixedOffset::east(32400).ymd(2014, 12, 31).and_hms(13, 26, 40)));
1084 
1085         // TODO test with a variable time zone (for None and Ambiguous cases)
1086     }
1087 }
1088 
1089