1use super::{ParseResult, IMPOSSIBLE, NOT_ENOUGH, OUT_OF_RANGE};
8use crate::naive::{NaiveDate, NaiveDateTime, NaiveTime};
9use crate::offset::{FixedOffset, LocalResult, Offset, TimeZone};
10use crate::{DateTime, Datelike, TimeDelta, Timelike, Weekday};
11
12#[allow(clippy::manual_non_exhaustive)]
20#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
21pub struct Parsed {
22 pub year: Option<i32>,
27
28 pub year_div_100: Option<i32>,
34
35 pub year_mod_100: Option<i32>,
37
38 pub isoyear: Option<i32>,
43
44 pub isoyear_div_100: Option<i32>,
51
52 pub isoyear_mod_100: Option<i32>,
55
56 pub month: Option<u32>,
58
59 pub week_from_sun: Option<u32>,
62
63 pub week_from_mon: Option<u32>,
66
67 pub isoweek: Option<u32>,
70
71 pub weekday: Option<Weekday>,
73
74 pub ordinal: Option<u32>,
76
77 pub day: Option<u32>,
79
80 pub hour_div_12: Option<u32>,
82
83 pub hour_mod_12: Option<u32>,
85
86 pub minute: Option<u32>,
88
89 pub second: Option<u32>,
91
92 pub nanosecond: Option<u32>,
94
95 pub timestamp: Option<i64>,
99
100 pub offset: Option<i32>,
102
103 _dummy: (),
106}
107
108#[inline]
111fn set_if_consistent<T: PartialEq>(old: &mut Option<T>, new: T) -> ParseResult<()> {
112 if let Some(ref old) = *old {
113 if *old == new {
114 Ok(())
115 } else {
116 Err(IMPOSSIBLE)
117 }
118 } else {
119 *old = Some(new);
120 Ok(())
121 }
122}
123
124impl Parsed {
125 #[must_use]
127 pub fn new() -> Parsed {
128 Parsed::default()
129 }
130
131 #[inline]
133 pub fn set_year(&mut self, value: i64) -> ParseResult<()> {
134 set_if_consistent(&mut self.year, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
135 }
136
137 #[inline]
139 pub fn set_year_div_100(&mut self, value: i64) -> ParseResult<()> {
140 if value < 0 {
141 return Err(OUT_OF_RANGE);
142 }
143 set_if_consistent(&mut self.year_div_100, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
144 }
145
146 #[inline]
148 pub fn set_year_mod_100(&mut self, value: i64) -> ParseResult<()> {
149 if value < 0 {
150 return Err(OUT_OF_RANGE);
151 }
152 set_if_consistent(&mut self.year_mod_100, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
153 }
154
155 #[inline]
157 pub fn set_isoyear(&mut self, value: i64) -> ParseResult<()> {
158 set_if_consistent(&mut self.isoyear, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
159 }
160
161 #[inline]
163 pub fn set_isoyear_div_100(&mut self, value: i64) -> ParseResult<()> {
164 if value < 0 {
165 return Err(OUT_OF_RANGE);
166 }
167 set_if_consistent(
168 &mut self.isoyear_div_100,
169 i32::try_from(value).map_err(|_| OUT_OF_RANGE)?,
170 )
171 }
172
173 #[inline]
175 pub fn set_isoyear_mod_100(&mut self, value: i64) -> ParseResult<()> {
176 if value < 0 {
177 return Err(OUT_OF_RANGE);
178 }
179 set_if_consistent(
180 &mut self.isoyear_mod_100,
181 i32::try_from(value).map_err(|_| OUT_OF_RANGE)?,
182 )
183 }
184
185 #[inline]
187 pub fn set_month(&mut self, value: i64) -> ParseResult<()> {
188 set_if_consistent(&mut self.month, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
189 }
190
191 #[inline]
193 pub fn set_week_from_sun(&mut self, value: i64) -> ParseResult<()> {
194 set_if_consistent(&mut self.week_from_sun, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
195 }
196
197 #[inline]
199 pub fn set_week_from_mon(&mut self, value: i64) -> ParseResult<()> {
200 set_if_consistent(&mut self.week_from_mon, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
201 }
202
203 #[inline]
205 pub fn set_isoweek(&mut self, value: i64) -> ParseResult<()> {
206 set_if_consistent(&mut self.isoweek, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
207 }
208
209 #[inline]
211 pub fn set_weekday(&mut self, value: Weekday) -> ParseResult<()> {
212 set_if_consistent(&mut self.weekday, value)
213 }
214
215 #[inline]
217 pub fn set_ordinal(&mut self, value: i64) -> ParseResult<()> {
218 set_if_consistent(&mut self.ordinal, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
219 }
220
221 #[inline]
223 pub fn set_day(&mut self, value: i64) -> ParseResult<()> {
224 set_if_consistent(&mut self.day, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
225 }
226
227 #[inline]
230 pub fn set_ampm(&mut self, value: bool) -> ParseResult<()> {
231 set_if_consistent(&mut self.hour_div_12, u32::from(value))
232 }
233
234 #[inline]
237 pub fn set_hour12(&mut self, value: i64) -> ParseResult<()> {
238 if !(1..=12).contains(&value) {
239 return Err(OUT_OF_RANGE);
240 }
241 set_if_consistent(&mut self.hour_mod_12, value as u32 % 12)
242 }
243
244 #[inline]
247 pub fn set_hour(&mut self, value: i64) -> ParseResult<()> {
248 let v = u32::try_from(value).map_err(|_| OUT_OF_RANGE)?;
249 set_if_consistent(&mut self.hour_div_12, v / 12)?;
250 set_if_consistent(&mut self.hour_mod_12, v % 12)?;
251 Ok(())
252 }
253
254 #[inline]
256 pub fn set_minute(&mut self, value: i64) -> ParseResult<()> {
257 set_if_consistent(&mut self.minute, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
258 }
259
260 #[inline]
262 pub fn set_second(&mut self, value: i64) -> ParseResult<()> {
263 set_if_consistent(&mut self.second, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
264 }
265
266 #[inline]
268 pub fn set_nanosecond(&mut self, value: i64) -> ParseResult<()> {
269 set_if_consistent(&mut self.nanosecond, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
270 }
271
272 #[inline]
274 pub fn set_timestamp(&mut self, value: i64) -> ParseResult<()> {
275 set_if_consistent(&mut self.timestamp, value)
276 }
277
278 #[inline]
280 pub fn set_offset(&mut self, value: i64) -> ParseResult<()> {
281 set_if_consistent(&mut self.offset, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
282 }
283
284 pub fn to_naive_date(&self) -> ParseResult<NaiveDate> {
296 fn resolve_year(
297 y: Option<i32>,
298 q: Option<i32>,
299 r: Option<i32>,
300 ) -> ParseResult<Option<i32>> {
301 match (y, q, r) {
302 (y, None, None) => Ok(y),
305
306 (Some(y), q, r @ Some(0..=99)) | (Some(y), q, r @ None) => {
311 if y < 0 {
312 return Err(OUT_OF_RANGE);
313 }
314 let q_ = y / 100;
315 let r_ = y % 100;
316 if q.unwrap_or(q_) == q_ && r.unwrap_or(r_) == r_ {
317 Ok(Some(y))
318 } else {
319 Err(IMPOSSIBLE)
320 }
321 }
322
323 (None, Some(q), Some(r @ 0..=99)) => {
326 if q < 0 {
327 return Err(OUT_OF_RANGE);
328 }
329 let y = q.checked_mul(100).and_then(|v| v.checked_add(r));
330 Ok(Some(y.ok_or(OUT_OF_RANGE)?))
331 }
332
333 (None, None, Some(r @ 0..=99)) => Ok(Some(r + if r < 70 { 2000 } else { 1900 })),
336
337 (None, Some(_), None) => Err(NOT_ENOUGH),
339 (_, _, Some(_)) => Err(OUT_OF_RANGE),
340 }
341 }
342
343 let given_year = resolve_year(self.year, self.year_div_100, self.year_mod_100)?;
344 let given_isoyear = resolve_year(self.isoyear, self.isoyear_div_100, self.isoyear_mod_100)?;
345
346 let verify_ymd = |date: NaiveDate| {
348 let year = date.year();
349 let (year_div_100, year_mod_100) = if year >= 0 {
350 (Some(year / 100), Some(year % 100))
351 } else {
352 (None, None) };
354 let month = date.month();
355 let day = date.day();
356 self.year.unwrap_or(year) == year
357 && self.year_div_100.or(year_div_100) == year_div_100
358 && self.year_mod_100.or(year_mod_100) == year_mod_100
359 && self.month.unwrap_or(month) == month
360 && self.day.unwrap_or(day) == day
361 };
362
363 let verify_isoweekdate = |date: NaiveDate| {
365 let week = date.iso_week();
366 let isoyear = week.year();
367 let isoweek = week.week();
368 let weekday = date.weekday();
369 let (isoyear_div_100, isoyear_mod_100) = if isoyear >= 0 {
370 (Some(isoyear / 100), Some(isoyear % 100))
371 } else {
372 (None, None) };
374 self.isoyear.unwrap_or(isoyear) == isoyear
375 && self.isoyear_div_100.or(isoyear_div_100) == isoyear_div_100
376 && self.isoyear_mod_100.or(isoyear_mod_100) == isoyear_mod_100
377 && self.isoweek.unwrap_or(isoweek) == isoweek
378 && self.weekday.unwrap_or(weekday) == weekday
379 };
380
381 let verify_ordinal = |date: NaiveDate| {
383 let ordinal = date.ordinal();
384 let week_from_sun = date.weeks_from(Weekday::Sun);
385 let week_from_mon = date.weeks_from(Weekday::Mon);
386 self.ordinal.unwrap_or(ordinal) == ordinal
387 && self.week_from_sun.map_or(week_from_sun, |v| v as i32) == week_from_sun
388 && self.week_from_mon.map_or(week_from_mon, |v| v as i32) == week_from_mon
389 };
390
391 let (verified, parsed_date) = match (given_year, given_isoyear, self) {
395 (Some(year), _, &Parsed { month: Some(month), day: Some(day), .. }) => {
396 let date = NaiveDate::from_ymd_opt(year, month, day).ok_or(OUT_OF_RANGE)?;
398 (verify_isoweekdate(date) && verify_ordinal(date), date)
399 }
400
401 (Some(year), _, &Parsed { ordinal: Some(ordinal), .. }) => {
402 let date = NaiveDate::from_yo_opt(year, ordinal).ok_or(OUT_OF_RANGE)?;
404 (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
405 }
406
407 (
408 Some(year),
409 _,
410 &Parsed { week_from_sun: Some(week_from_sun), weekday: Some(weekday), .. },
411 ) => {
412 let newyear = NaiveDate::from_yo_opt(year, 1).ok_or(OUT_OF_RANGE)?;
414 let firstweek = match newyear.weekday() {
415 Weekday::Sun => 0,
416 Weekday::Mon => 6,
417 Weekday::Tue => 5,
418 Weekday::Wed => 4,
419 Weekday::Thu => 3,
420 Weekday::Fri => 2,
421 Weekday::Sat => 1,
422 };
423
424 if week_from_sun > 53 {
426 return Err(OUT_OF_RANGE);
427 } let ndays = firstweek
429 + (week_from_sun as i32 - 1) * 7
430 + weekday.num_days_from_sunday() as i32;
431 let date = newyear
432 .checked_add_signed(TimeDelta::days(i64::from(ndays)))
433 .ok_or(OUT_OF_RANGE)?;
434 if date.year() != year {
435 return Err(OUT_OF_RANGE);
436 } (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
439 }
440
441 (
442 Some(year),
443 _,
444 &Parsed { week_from_mon: Some(week_from_mon), weekday: Some(weekday), .. },
445 ) => {
446 let newyear = NaiveDate::from_yo_opt(year, 1).ok_or(OUT_OF_RANGE)?;
448 let firstweek = match newyear.weekday() {
449 Weekday::Sun => 1,
450 Weekday::Mon => 0,
451 Weekday::Tue => 6,
452 Weekday::Wed => 5,
453 Weekday::Thu => 4,
454 Weekday::Fri => 3,
455 Weekday::Sat => 2,
456 };
457
458 if week_from_mon > 53 {
460 return Err(OUT_OF_RANGE);
461 } let ndays = firstweek
463 + (week_from_mon as i32 - 1) * 7
464 + weekday.num_days_from_monday() as i32;
465 let date = newyear
466 .checked_add_signed(TimeDelta::days(i64::from(ndays)))
467 .ok_or(OUT_OF_RANGE)?;
468 if date.year() != year {
469 return Err(OUT_OF_RANGE);
470 } (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
473 }
474
475 (_, Some(isoyear), &Parsed { isoweek: Some(isoweek), weekday: Some(weekday), .. }) => {
476 let date = NaiveDate::from_isoywd_opt(isoyear, isoweek, weekday);
478 let date = date.ok_or(OUT_OF_RANGE)?;
479 (verify_ymd(date) && verify_ordinal(date), date)
480 }
481
482 (_, _, _) => return Err(NOT_ENOUGH),
483 };
484
485 if verified {
486 Ok(parsed_date)
487 } else {
488 Err(IMPOSSIBLE)
489 }
490 }
491
492 pub fn to_naive_time(&self) -> ParseResult<NaiveTime> {
502 let hour_div_12 = match self.hour_div_12 {
503 Some(v @ 0..=1) => v,
504 Some(_) => return Err(OUT_OF_RANGE),
505 None => return Err(NOT_ENOUGH),
506 };
507 let hour_mod_12 = match self.hour_mod_12 {
508 Some(v @ 0..=11) => v,
509 Some(_) => return Err(OUT_OF_RANGE),
510 None => return Err(NOT_ENOUGH),
511 };
512 let hour = hour_div_12 * 12 + hour_mod_12;
513
514 let minute = match self.minute {
515 Some(v @ 0..=59) => v,
516 Some(_) => return Err(OUT_OF_RANGE),
517 None => return Err(NOT_ENOUGH),
518 };
519
520 let (second, mut nano) = match self.second.unwrap_or(0) {
522 v @ 0..=59 => (v, 0),
523 60 => (59, 1_000_000_000),
524 _ => return Err(OUT_OF_RANGE),
525 };
526 nano += match self.nanosecond {
527 Some(v @ 0..=999_999_999) if self.second.is_some() => v,
528 Some(0..=999_999_999) => return Err(NOT_ENOUGH), Some(_) => return Err(OUT_OF_RANGE),
530 None => 0,
531 };
532
533 NaiveTime::from_hms_nano_opt(hour, minute, second, nano).ok_or(OUT_OF_RANGE)
534 }
535
536 pub fn to_naive_datetime_with_offset(&self, offset: i32) -> ParseResult<NaiveDateTime> {
544 let date = self.to_naive_date();
545 let time = self.to_naive_time();
546 if let (Ok(date), Ok(time)) = (date, time) {
547 let datetime = date.and_time(time);
548
549 let timestamp = datetime.timestamp() - i64::from(offset);
552 if let Some(given_timestamp) = self.timestamp {
553 if given_timestamp != timestamp
555 && !(datetime.nanosecond() >= 1_000_000_000 && given_timestamp == timestamp + 1)
556 {
557 return Err(IMPOSSIBLE);
558 }
559 }
560
561 Ok(datetime)
562 } else if let Some(timestamp) = self.timestamp {
563 use super::ParseError as PE;
564 use super::ParseErrorKind::{Impossible, OutOfRange};
565
566 match (date, time) {
569 (Err(PE(OutOfRange)), _) | (_, Err(PE(OutOfRange))) => return Err(OUT_OF_RANGE),
570 (Err(PE(Impossible)), _) | (_, Err(PE(Impossible))) => return Err(IMPOSSIBLE),
571 (_, _) => {} }
573
574 let ts = timestamp.checked_add(i64::from(offset)).ok_or(OUT_OF_RANGE)?;
576 let datetime = NaiveDateTime::from_timestamp_opt(ts, 0);
577 let mut datetime = datetime.ok_or(OUT_OF_RANGE)?;
578
579 let mut parsed = self.clone();
582 if parsed.second == Some(60) {
583 match datetime.second() {
585 59 => {}
587 0 => {
589 datetime -= TimeDelta::seconds(1);
590 }
591 _ => return Err(IMPOSSIBLE),
593 }
594 } else {
596 parsed.set_second(i64::from(datetime.second()))?;
597 }
598 parsed.set_year(i64::from(datetime.year()))?;
599 parsed.set_ordinal(i64::from(datetime.ordinal()))?; parsed.set_hour(i64::from(datetime.hour()))?;
601 parsed.set_minute(i64::from(datetime.minute()))?;
602
603 let date = parsed.to_naive_date()?;
605 let time = parsed.to_naive_time()?;
606 Ok(date.and_time(time))
607 } else {
608 date?;
610 time?;
611 unreachable!()
612 }
613 }
614
615 pub fn to_fixed_offset(&self) -> ParseResult<FixedOffset> {
617 self.offset.and_then(FixedOffset::east_opt).ok_or(OUT_OF_RANGE)
618 }
619
620 pub fn to_datetime(&self) -> ParseResult<DateTime<FixedOffset>> {
627 let offset = match (self.offset, self.timestamp) {
629 (Some(off), _) => off,
630 (None, Some(_)) => 0, (None, None) => return Err(NOT_ENOUGH),
632 };
633 let datetime = self.to_naive_datetime_with_offset(offset)?;
634 let offset = FixedOffset::east_opt(offset).ok_or(OUT_OF_RANGE)?;
635
636 match offset.from_local_datetime(&datetime) {
637 LocalResult::None => Err(IMPOSSIBLE),
638 LocalResult::Single(t) => Ok(t),
639 LocalResult::Ambiguous(..) => Err(NOT_ENOUGH),
640 }
641 }
642
643 pub fn to_datetime_with_timezone<Tz: TimeZone>(&self, tz: &Tz) -> ParseResult<DateTime<Tz>> {
653 let mut guessed_offset = 0;
655 if let Some(timestamp) = self.timestamp {
656 let nanosecond = self.nanosecond.unwrap_or(0);
659 let dt = NaiveDateTime::from_timestamp_opt(timestamp, nanosecond);
660 let dt = dt.ok_or(OUT_OF_RANGE)?;
661 guessed_offset = tz.offset_from_utc_datetime(&dt).fix().local_minus_utc();
662 }
663
664 let check_offset = |dt: &DateTime<Tz>| {
666 if let Some(offset) = self.offset {
667 dt.offset().fix().local_minus_utc() == offset
668 } else {
669 true
670 }
671 };
672
673 let datetime = self.to_naive_datetime_with_offset(guessed_offset)?;
676 match tz.from_local_datetime(&datetime) {
677 LocalResult::None => Err(IMPOSSIBLE),
678 LocalResult::Single(t) => {
679 if check_offset(&t) {
680 Ok(t)
681 } else {
682 Err(IMPOSSIBLE)
683 }
684 }
685 LocalResult::Ambiguous(min, max) => {
686 match (check_offset(&min), check_offset(&max)) {
688 (false, false) => Err(IMPOSSIBLE),
689 (false, true) => Ok(max),
690 (true, false) => Ok(min),
691 (true, true) => Err(NOT_ENOUGH),
692 }
693 }
694 }
695 }
696}
697
698#[cfg(test)]
699mod tests {
700 use super::super::{IMPOSSIBLE, NOT_ENOUGH, OUT_OF_RANGE};
701 use super::Parsed;
702 use crate::naive::{NaiveDate, NaiveTime};
703 use crate::offset::{FixedOffset, TimeZone, Utc};
704 use crate::Datelike;
705 use crate::Weekday::*;
706
707 #[test]
708 fn test_parsed_set_fields() {
709 let mut p = Parsed::new();
711 assert_eq!(p.set_year(1987), Ok(()));
712 assert_eq!(p.set_year(1986), Err(IMPOSSIBLE));
713 assert_eq!(p.set_year(1988), Err(IMPOSSIBLE));
714 assert_eq!(p.set_year(1987), Ok(()));
715 assert_eq!(p.set_year_div_100(20), Ok(())); assert_eq!(p.set_year_div_100(21), Err(IMPOSSIBLE));
717 assert_eq!(p.set_year_div_100(19), Err(IMPOSSIBLE));
718 assert_eq!(p.set_year_mod_100(37), Ok(())); assert_eq!(p.set_year_mod_100(38), Err(IMPOSSIBLE));
720 assert_eq!(p.set_year_mod_100(36), Err(IMPOSSIBLE));
721
722 let mut p = Parsed::new();
723 assert_eq!(p.set_year(0), Ok(()));
724 assert_eq!(p.set_year_div_100(0), Ok(()));
725 assert_eq!(p.set_year_mod_100(0), Ok(()));
726
727 let mut p = Parsed::new();
728 assert_eq!(p.set_year_div_100(-1), Err(OUT_OF_RANGE));
729 assert_eq!(p.set_year_mod_100(-1), Err(OUT_OF_RANGE));
730 assert_eq!(p.set_year(-1), Ok(()));
731 assert_eq!(p.set_year(-2), Err(IMPOSSIBLE));
732 assert_eq!(p.set_year(0), Err(IMPOSSIBLE));
733
734 let mut p = Parsed::new();
735 assert_eq!(p.set_year_div_100(0x1_0000_0008), Err(OUT_OF_RANGE));
736 assert_eq!(p.set_year_div_100(8), Ok(()));
737 assert_eq!(p.set_year_div_100(0x1_0000_0008), Err(OUT_OF_RANGE));
738
739 let mut p = Parsed::new();
741 assert_eq!(p.set_month(7), Ok(()));
742 assert_eq!(p.set_month(1), Err(IMPOSSIBLE));
743 assert_eq!(p.set_month(6), Err(IMPOSSIBLE));
744 assert_eq!(p.set_month(8), Err(IMPOSSIBLE));
745 assert_eq!(p.set_month(12), Err(IMPOSSIBLE));
746
747 let mut p = Parsed::new();
748 assert_eq!(p.set_month(8), Ok(()));
749 assert_eq!(p.set_month(0x1_0000_0008), Err(OUT_OF_RANGE));
750
751 let mut p = Parsed::new();
753 assert_eq!(p.set_hour(12), Ok(()));
754 assert_eq!(p.set_hour(11), Err(IMPOSSIBLE));
755 assert_eq!(p.set_hour(13), Err(IMPOSSIBLE));
756 assert_eq!(p.set_hour(12), Ok(()));
757 assert_eq!(p.set_ampm(false), Err(IMPOSSIBLE));
758 assert_eq!(p.set_ampm(true), Ok(()));
759 assert_eq!(p.set_hour12(12), Ok(()));
760 assert_eq!(p.set_hour12(0), Err(OUT_OF_RANGE)); assert_eq!(p.set_hour12(1), Err(IMPOSSIBLE));
762 assert_eq!(p.set_hour12(11), Err(IMPOSSIBLE));
763
764 let mut p = Parsed::new();
765 assert_eq!(p.set_ampm(true), Ok(()));
766 assert_eq!(p.set_hour12(7), Ok(()));
767 assert_eq!(p.set_hour(7), Err(IMPOSSIBLE));
768 assert_eq!(p.set_hour(18), Err(IMPOSSIBLE));
769 assert_eq!(p.set_hour(19), Ok(()));
770
771 let mut p = Parsed::new();
773 assert_eq!(p.set_timestamp(1_234_567_890), Ok(()));
774 assert_eq!(p.set_timestamp(1_234_567_889), Err(IMPOSSIBLE));
775 assert_eq!(p.set_timestamp(1_234_567_891), Err(IMPOSSIBLE));
776 }
777
778 #[test]
779 fn test_parsed_to_naive_date() {
780 macro_rules! parse {
781 ($($k:ident: $v:expr),*) => (
782 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_naive_date()
783 )
784 }
785
786 let ymd = |y, m, d| Ok(NaiveDate::from_ymd_opt(y, m, d).unwrap());
787
788 assert_eq!(parse!(), Err(NOT_ENOUGH));
790 assert_eq!(parse!(year: 1984), Err(NOT_ENOUGH));
791 assert_eq!(parse!(year: 1984, month: 1), Err(NOT_ENOUGH));
792 assert_eq!(parse!(year: 1984, month: 1, day: 2), ymd(1984, 1, 2));
793 assert_eq!(parse!(year: 1984, day: 2), Err(NOT_ENOUGH));
794 assert_eq!(parse!(year_div_100: 19), Err(NOT_ENOUGH));
795 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84), Err(NOT_ENOUGH));
796 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, month: 1), Err(NOT_ENOUGH));
797 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, month: 1, day: 2), ymd(1984, 1, 2));
798 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, day: 2), Err(NOT_ENOUGH));
799 assert_eq!(parse!(year_div_100: 19, month: 1, day: 2), Err(NOT_ENOUGH));
800 assert_eq!(parse!(year_mod_100: 70, month: 1, day: 2), ymd(1970, 1, 2));
801 assert_eq!(parse!(year_mod_100: 69, month: 1, day: 2), ymd(2069, 1, 2));
802
803 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, month: 2, day: 29), ymd(1984, 2, 29));
805 assert_eq!(
806 parse!(year_div_100: 19, year_mod_100: 83, month: 2, day: 29),
807 Err(OUT_OF_RANGE)
808 );
809 assert_eq!(
810 parse!(year_div_100: 19, year_mod_100: 83, month: 13, day: 1),
811 Err(OUT_OF_RANGE)
812 );
813 assert_eq!(
814 parse!(year_div_100: 19, year_mod_100: 83, month: 12, day: 31),
815 ymd(1983, 12, 31)
816 );
817 assert_eq!(
818 parse!(year_div_100: 19, year_mod_100: 83, month: 12, day: 32),
819 Err(OUT_OF_RANGE)
820 );
821 assert_eq!(
822 parse!(year_div_100: 19, year_mod_100: 83, month: 12, day: 0),
823 Err(OUT_OF_RANGE)
824 );
825 assert_eq!(
826 parse!(year_div_100: 19, year_mod_100: 100, month: 1, day: 1),
827 Err(OUT_OF_RANGE)
828 );
829 assert_eq!(parse!(year_div_100: 19, year_mod_100: -1, month: 1, day: 1), Err(OUT_OF_RANGE));
830 assert_eq!(parse!(year_div_100: 0, year_mod_100: 0, month: 1, day: 1), ymd(0, 1, 1));
831 assert_eq!(parse!(year_div_100: -1, year_mod_100: 42, month: 1, day: 1), Err(OUT_OF_RANGE));
832 let max_year = NaiveDate::MAX.year();
833 assert_eq!(
834 parse!(year_div_100: max_year / 100,
835 year_mod_100: max_year % 100, month: 1, day: 1),
836 ymd(max_year, 1, 1)
837 );
838 assert_eq!(
839 parse!(year_div_100: (max_year + 1) / 100,
840 year_mod_100: (max_year + 1) % 100, month: 1, day: 1),
841 Err(OUT_OF_RANGE)
842 );
843
844 assert_eq!(parse!(year: 1984, year_div_100: 19, month: 1, day: 1), ymd(1984, 1, 1));
846 assert_eq!(parse!(year: 1984, year_div_100: 20, month: 1, day: 1), Err(IMPOSSIBLE));
847 assert_eq!(parse!(year: 1984, year_mod_100: 84, month: 1, day: 1), ymd(1984, 1, 1));
848 assert_eq!(parse!(year: 1984, year_mod_100: 83, month: 1, day: 1), Err(IMPOSSIBLE));
849 assert_eq!(
850 parse!(year: 1984, year_div_100: 19, year_mod_100: 84, month: 1, day: 1),
851 ymd(1984, 1, 1)
852 );
853 assert_eq!(
854 parse!(year: 1984, year_div_100: 18, year_mod_100: 94, month: 1, day: 1),
855 Err(IMPOSSIBLE)
856 );
857 assert_eq!(
858 parse!(year: 1984, year_div_100: 18, year_mod_100: 184, month: 1, day: 1),
859 Err(OUT_OF_RANGE)
860 );
861 assert_eq!(
862 parse!(year: -1, year_div_100: 0, year_mod_100: -1, month: 1, day: 1),
863 Err(OUT_OF_RANGE)
864 );
865 assert_eq!(
866 parse!(year: -1, year_div_100: -1, year_mod_100: 99, month: 1, day: 1),
867 Err(OUT_OF_RANGE)
868 );
869 assert_eq!(parse!(year: -1, year_div_100: 0, month: 1, day: 1), Err(OUT_OF_RANGE));
870 assert_eq!(parse!(year: -1, year_mod_100: 99, month: 1, day: 1), Err(OUT_OF_RANGE));
871
872 assert_eq!(parse!(year: 2000, week_from_mon: 0), Err(NOT_ENOUGH));
874 assert_eq!(parse!(year: 2000, week_from_sun: 0), Err(NOT_ENOUGH));
875 assert_eq!(parse!(year: 2000, weekday: Sun), Err(NOT_ENOUGH));
876 assert_eq!(parse!(year: 2000, week_from_mon: 0, weekday: Fri), Err(OUT_OF_RANGE));
877 assert_eq!(parse!(year: 2000, week_from_sun: 0, weekday: Fri), Err(OUT_OF_RANGE));
878 assert_eq!(parse!(year: 2000, week_from_mon: 0, weekday: Sat), ymd(2000, 1, 1));
879 assert_eq!(parse!(year: 2000, week_from_sun: 0, weekday: Sat), ymd(2000, 1, 1));
880 assert_eq!(parse!(year: 2000, week_from_mon: 0, weekday: Sun), ymd(2000, 1, 2));
881 assert_eq!(parse!(year: 2000, week_from_sun: 1, weekday: Sun), ymd(2000, 1, 2));
882 assert_eq!(parse!(year: 2000, week_from_mon: 1, weekday: Mon), ymd(2000, 1, 3));
883 assert_eq!(parse!(year: 2000, week_from_sun: 1, weekday: Mon), ymd(2000, 1, 3));
884 assert_eq!(parse!(year: 2000, week_from_mon: 1, weekday: Sat), ymd(2000, 1, 8));
885 assert_eq!(parse!(year: 2000, week_from_sun: 1, weekday: Sat), ymd(2000, 1, 8));
886 assert_eq!(parse!(year: 2000, week_from_mon: 1, weekday: Sun), ymd(2000, 1, 9));
887 assert_eq!(parse!(year: 2000, week_from_sun: 2, weekday: Sun), ymd(2000, 1, 9));
888 assert_eq!(parse!(year: 2000, week_from_mon: 2, weekday: Mon), ymd(2000, 1, 10));
889 assert_eq!(parse!(year: 2000, week_from_sun: 52, weekday: Sat), ymd(2000, 12, 30));
890 assert_eq!(parse!(year: 2000, week_from_sun: 53, weekday: Sun), ymd(2000, 12, 31));
891 assert_eq!(parse!(year: 2000, week_from_sun: 53, weekday: Mon), Err(OUT_OF_RANGE));
892 assert_eq!(parse!(year: 2000, week_from_sun: 0xffffffff, weekday: Mon), Err(OUT_OF_RANGE));
893 assert_eq!(parse!(year: 2006, week_from_sun: 0, weekday: Sat), Err(OUT_OF_RANGE));
894 assert_eq!(parse!(year: 2006, week_from_sun: 1, weekday: Sun), ymd(2006, 1, 1));
895
896 assert_eq!(
898 parse!(year: 2000, week_from_mon: 1, week_from_sun: 1, weekday: Sat),
899 ymd(2000, 1, 8)
900 );
901 assert_eq!(
902 parse!(year: 2000, week_from_mon: 1, week_from_sun: 2, weekday: Sun),
903 ymd(2000, 1, 9)
904 );
905 assert_eq!(
906 parse!(year: 2000, week_from_mon: 1, week_from_sun: 1, weekday: Sun),
907 Err(IMPOSSIBLE)
908 );
909 assert_eq!(
910 parse!(year: 2000, week_from_mon: 2, week_from_sun: 2, weekday: Sun),
911 Err(IMPOSSIBLE)
912 );
913
914 assert_eq!(parse!(isoyear: 2004, isoweek: 53), Err(NOT_ENOUGH));
916 assert_eq!(parse!(isoyear: 2004, isoweek: 53, weekday: Fri), ymd(2004, 12, 31));
917 assert_eq!(parse!(isoyear: 2004, isoweek: 53, weekday: Sat), ymd(2005, 1, 1));
918 assert_eq!(parse!(isoyear: 2004, isoweek: 0xffffffff, weekday: Sat), Err(OUT_OF_RANGE));
919 assert_eq!(parse!(isoyear: 2005, isoweek: 0, weekday: Thu), Err(OUT_OF_RANGE));
920 assert_eq!(parse!(isoyear: 2005, isoweek: 5, weekday: Thu), ymd(2005, 2, 3));
921 assert_eq!(parse!(isoyear: 2005, weekday: Thu), Err(NOT_ENOUGH));
922
923 assert_eq!(parse!(ordinal: 123), Err(NOT_ENOUGH));
925 assert_eq!(parse!(year: 2000, ordinal: 0), Err(OUT_OF_RANGE));
926 assert_eq!(parse!(year: 2000, ordinal: 1), ymd(2000, 1, 1));
927 assert_eq!(parse!(year: 2000, ordinal: 60), ymd(2000, 2, 29));
928 assert_eq!(parse!(year: 2000, ordinal: 61), ymd(2000, 3, 1));
929 assert_eq!(parse!(year: 2000, ordinal: 366), ymd(2000, 12, 31));
930 assert_eq!(parse!(year: 2000, ordinal: 367), Err(OUT_OF_RANGE));
931 assert_eq!(parse!(year: 2000, ordinal: 0xffffffff), Err(OUT_OF_RANGE));
932 assert_eq!(parse!(year: 2100, ordinal: 0), Err(OUT_OF_RANGE));
933 assert_eq!(parse!(year: 2100, ordinal: 1), ymd(2100, 1, 1));
934 assert_eq!(parse!(year: 2100, ordinal: 59), ymd(2100, 2, 28));
935 assert_eq!(parse!(year: 2100, ordinal: 60), ymd(2100, 3, 1));
936 assert_eq!(parse!(year: 2100, ordinal: 365), ymd(2100, 12, 31));
937 assert_eq!(parse!(year: 2100, ordinal: 366), Err(OUT_OF_RANGE));
938 assert_eq!(parse!(year: 2100, ordinal: 0xffffffff), Err(OUT_OF_RANGE));
939
940 assert_eq!(
942 parse!(year: 2014, month: 12, day: 31, ordinal: 365, isoyear: 2015, isoweek: 1,
943 week_from_sun: 52, week_from_mon: 52, weekday: Wed),
944 ymd(2014, 12, 31)
945 );
946 assert_eq!(
947 parse!(year: 2014, month: 12, ordinal: 365, isoyear: 2015, isoweek: 1,
948 week_from_sun: 52, week_from_mon: 52),
949 ymd(2014, 12, 31)
950 );
951 assert_eq!(
952 parse!(year: 2014, month: 12, day: 31, ordinal: 365, isoyear: 2014, isoweek: 53,
953 week_from_sun: 52, week_from_mon: 52, weekday: Wed),
954 Err(IMPOSSIBLE)
955 ); assert_eq!(
957 parse!(year: 2012, isoyear: 2015, isoweek: 1,
958 week_from_sun: 52, week_from_mon: 52),
959 Err(NOT_ENOUGH)
960 ); assert_eq!(parse!(year_div_100: 20, isoyear_mod_100: 15, ordinal: 366), Err(NOT_ENOUGH));
962 }
964
965 #[test]
966 fn test_parsed_to_naive_time() {
967 macro_rules! parse {
968 ($($k:ident: $v:expr),*) => (
969 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_naive_time()
970 )
971 }
972
973 let hms = |h, m, s| Ok(NaiveTime::from_hms_opt(h, m, s).unwrap());
974 let hmsn = |h, m, s, n| Ok(NaiveTime::from_hms_nano_opt(h, m, s, n).unwrap());
975
976 assert_eq!(parse!(), Err(NOT_ENOUGH));
978 assert_eq!(parse!(hour_div_12: 0), Err(NOT_ENOUGH));
979 assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1), Err(NOT_ENOUGH));
980 assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23), hms(1, 23, 0));
981 assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 45), hms(1, 23, 45));
982 assert_eq!(
983 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 45,
984 nanosecond: 678_901_234),
985 hmsn(1, 23, 45, 678_901_234)
986 );
987 assert_eq!(parse!(hour_div_12: 1, hour_mod_12: 11, minute: 45, second: 6), hms(23, 45, 6));
988 assert_eq!(parse!(hour_mod_12: 1, minute: 23), Err(NOT_ENOUGH));
989 assert_eq!(
990 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, nanosecond: 456_789_012),
991 Err(NOT_ENOUGH)
992 );
993
994 assert_eq!(parse!(hour_div_12: 2, hour_mod_12: 0, minute: 0), Err(OUT_OF_RANGE));
996 assert_eq!(parse!(hour_div_12: 1, hour_mod_12: 12, minute: 0), Err(OUT_OF_RANGE));
997 assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 60), Err(OUT_OF_RANGE));
998 assert_eq!(
999 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 61),
1000 Err(OUT_OF_RANGE)
1001 );
1002 assert_eq!(
1003 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 34,
1004 nanosecond: 1_000_000_000),
1005 Err(OUT_OF_RANGE)
1006 );
1007
1008 assert_eq!(
1010 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 60),
1011 hmsn(1, 23, 59, 1_000_000_000)
1012 );
1013 assert_eq!(
1014 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 60,
1015 nanosecond: 999_999_999),
1016 hmsn(1, 23, 59, 1_999_999_999)
1017 );
1018 }
1019
1020 #[test]
1021 fn test_parsed_to_naive_datetime_with_offset() {
1022 macro_rules! parse {
1023 (offset = $offset:expr; $($k:ident: $v:expr),*) => (
1024 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_naive_datetime_with_offset($offset)
1025 );
1026 ($($k:ident: $v:expr),*) => (parse!(offset = 0; $($k: $v),*))
1027 }
1028
1029 let ymdhms = |y, m, d, h, n, s| {
1030 Ok(NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_opt(h, n, s).unwrap())
1031 };
1032 let ymdhmsn = |y, m, d, h, n, s, nano| {
1033 Ok(NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_nano_opt(h, n, s, nano).unwrap())
1034 };
1035
1036 assert_eq!(parse!(), Err(NOT_ENOUGH));
1038 assert_eq!(
1039 parse!(year: 2015, month: 1, day: 30,
1040 hour_div_12: 1, hour_mod_12: 2, minute: 38),
1041 ymdhms(2015, 1, 30, 14, 38, 0)
1042 );
1043 assert_eq!(
1044 parse!(year: 1997, month: 1, day: 30,
1045 hour_div_12: 1, hour_mod_12: 2, minute: 38, second: 5),
1046 ymdhms(1997, 1, 30, 14, 38, 5)
1047 );
1048 assert_eq!(
1049 parse!(year: 2012, ordinal: 34, hour_div_12: 0, hour_mod_12: 5,
1050 minute: 6, second: 7, nanosecond: 890_123_456),
1051 ymdhmsn(2012, 2, 3, 5, 6, 7, 890_123_456)
1052 );
1053 assert_eq!(parse!(timestamp: 0), ymdhms(1970, 1, 1, 0, 0, 0));
1054 assert_eq!(parse!(timestamp: 1, nanosecond: 0), ymdhms(1970, 1, 1, 0, 0, 1));
1055 assert_eq!(parse!(timestamp: 1, nanosecond: 1), ymdhmsn(1970, 1, 1, 0, 0, 1, 1));
1056 assert_eq!(parse!(timestamp: 1_420_000_000), ymdhms(2014, 12, 31, 4, 26, 40));
1057 assert_eq!(parse!(timestamp: -0x1_0000_0000), ymdhms(1833, 11, 24, 17, 31, 44));
1058
1059 assert_eq!(
1061 parse!(year: 2014, year_div_100: 20, year_mod_100: 14, month: 12, day: 31,
1062 ordinal: 365, isoyear: 2015, isoyear_div_100: 20, isoyear_mod_100: 15,
1063 isoweek: 1, week_from_sun: 52, week_from_mon: 52, weekday: Wed,
1064 hour_div_12: 0, hour_mod_12: 4, minute: 26, second: 40,
1065 nanosecond: 12_345_678, timestamp: 1_420_000_000),
1066 ymdhmsn(2014, 12, 31, 4, 26, 40, 12_345_678)
1067 );
1068 assert_eq!(
1069 parse!(year: 2014, year_div_100: 20, year_mod_100: 14, month: 12, day: 31,
1070 ordinal: 365, isoyear: 2015, isoyear_div_100: 20, isoyear_mod_100: 15,
1071 isoweek: 1, week_from_sun: 52, week_from_mon: 52, weekday: Wed,
1072 hour_div_12: 0, hour_mod_12: 4, minute: 26, second: 40,
1073 nanosecond: 12_345_678, timestamp: 1_419_999_999),
1074 Err(IMPOSSIBLE)
1075 );
1076 assert_eq!(
1077 parse!(offset = 32400;
1078 year: 2014, year_div_100: 20, year_mod_100: 14, month: 12, day: 31,
1079 ordinal: 365, isoyear: 2015, isoyear_div_100: 20, isoyear_mod_100: 15,
1080 isoweek: 1, week_from_sun: 52, week_from_mon: 52, weekday: Wed,
1081 hour_div_12: 0, hour_mod_12: 4, minute: 26, second: 40,
1082 nanosecond: 12_345_678, timestamp: 1_419_967_600),
1083 ymdhmsn(2014, 12, 31, 4, 26, 40, 12_345_678)
1084 );
1085
1086 let max_days_from_year_1970 =
1088 NaiveDate::MAX.signed_duration_since(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap());
1089 let year_0_from_year_1970 = NaiveDate::from_ymd_opt(0, 1, 1)
1090 .unwrap()
1091 .signed_duration_since(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap());
1092 let min_days_from_year_1970 =
1093 NaiveDate::MIN.signed_duration_since(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap());
1094 assert_eq!(
1095 parse!(timestamp: min_days_from_year_1970.num_seconds()),
1096 ymdhms(NaiveDate::MIN.year(), 1, 1, 0, 0, 0)
1097 );
1098 assert_eq!(
1099 parse!(timestamp: year_0_from_year_1970.num_seconds()),
1100 ymdhms(0, 1, 1, 0, 0, 0)
1101 );
1102 assert_eq!(
1103 parse!(timestamp: max_days_from_year_1970.num_seconds() + 86399),
1104 ymdhms(NaiveDate::MAX.year(), 12, 31, 23, 59, 59)
1105 );
1106
1107 assert_eq!(parse!(second: 59, timestamp: 1_341_100_798), Err(IMPOSSIBLE));
1109 assert_eq!(parse!(second: 59, timestamp: 1_341_100_799), ymdhms(2012, 6, 30, 23, 59, 59));
1110 assert_eq!(parse!(second: 59, timestamp: 1_341_100_800), Err(IMPOSSIBLE));
1111 assert_eq!(
1112 parse!(second: 60, timestamp: 1_341_100_799),
1113 ymdhmsn(2012, 6, 30, 23, 59, 59, 1_000_000_000)
1114 );
1115 assert_eq!(
1116 parse!(second: 60, timestamp: 1_341_100_800),
1117 ymdhmsn(2012, 6, 30, 23, 59, 59, 1_000_000_000)
1118 );
1119 assert_eq!(parse!(second: 0, timestamp: 1_341_100_800), ymdhms(2012, 7, 1, 0, 0, 0));
1120 assert_eq!(parse!(second: 1, timestamp: 1_341_100_800), Err(IMPOSSIBLE));
1121 assert_eq!(parse!(second: 60, timestamp: 1_341_100_801), Err(IMPOSSIBLE));
1122
1123 assert_eq!(
1126 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1127 minute: 59, second: 59, timestamp: 1_341_100_798),
1128 Err(IMPOSSIBLE)
1129 );
1130 assert_eq!(
1131 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1132 minute: 59, second: 59, timestamp: 1_341_100_799),
1133 ymdhms(2012, 6, 30, 23, 59, 59)
1134 );
1135 assert_eq!(
1136 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1137 minute: 59, second: 59, timestamp: 1_341_100_800),
1138 Err(IMPOSSIBLE)
1139 );
1140 assert_eq!(
1141 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1142 minute: 59, second: 60, timestamp: 1_341_100_799),
1143 ymdhmsn(2012, 6, 30, 23, 59, 59, 1_000_000_000)
1144 );
1145 assert_eq!(
1146 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1147 minute: 59, second: 60, timestamp: 1_341_100_800),
1148 ymdhmsn(2012, 6, 30, 23, 59, 59, 1_000_000_000)
1149 );
1150 assert_eq!(
1151 parse!(year: 2012, ordinal: 183, hour_div_12: 0, hour_mod_12: 0,
1152 minute: 0, second: 0, timestamp: 1_341_100_800),
1153 ymdhms(2012, 7, 1, 0, 0, 0)
1154 );
1155 assert_eq!(
1156 parse!(year: 2012, ordinal: 183, hour_div_12: 0, hour_mod_12: 0,
1157 minute: 0, second: 1, timestamp: 1_341_100_800),
1158 Err(IMPOSSIBLE)
1159 );
1160 assert_eq!(
1161 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1162 minute: 59, second: 60, timestamp: 1_341_100_801),
1163 Err(IMPOSSIBLE)
1164 );
1165
1166 assert_eq!(
1168 parse!(year: 2015, month: 1, day: 20, weekday: Tue,
1169 hour_div_12: 2, hour_mod_12: 1, minute: 35, second: 20),
1170 Err(OUT_OF_RANGE)
1171 ); }
1173
1174 #[test]
1175 fn test_parsed_to_datetime() {
1176 macro_rules! parse {
1177 ($($k:ident: $v:expr),*) => (
1178 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_datetime()
1179 )
1180 }
1181
1182 let ymdhmsn = |y, m, d, h, n, s, nano, off| {
1183 Ok(FixedOffset::east_opt(off)
1184 .unwrap()
1185 .from_local_datetime(
1186 &NaiveDate::from_ymd_opt(y, m, d)
1187 .unwrap()
1188 .and_hms_nano_opt(h, n, s, nano)
1189 .unwrap(),
1190 )
1191 .unwrap())
1192 };
1193
1194 assert_eq!(parse!(offset: 0), Err(NOT_ENOUGH));
1195 assert_eq!(
1196 parse!(year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1197 minute: 26, second: 40, nanosecond: 12_345_678),
1198 Err(NOT_ENOUGH)
1199 );
1200 assert_eq!(
1201 parse!(year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1202 minute: 26, second: 40, nanosecond: 12_345_678, offset: 0),
1203 ymdhmsn(2014, 12, 31, 4, 26, 40, 12_345_678, 0)
1204 );
1205 assert_eq!(
1206 parse!(year: 2014, ordinal: 365, hour_div_12: 1, hour_mod_12: 1,
1207 minute: 26, second: 40, nanosecond: 12_345_678, offset: 32400),
1208 ymdhmsn(2014, 12, 31, 13, 26, 40, 12_345_678, 32400)
1209 );
1210 assert_eq!(
1211 parse!(year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 1,
1212 minute: 42, second: 4, nanosecond: 12_345_678, offset: -9876),
1213 ymdhmsn(2014, 12, 31, 1, 42, 4, 12_345_678, -9876)
1214 );
1215 assert_eq!(
1216 parse!(year: 2015, ordinal: 1, hour_div_12: 0, hour_mod_12: 4,
1217 minute: 26, second: 40, nanosecond: 12_345_678, offset: 86_400),
1218 Err(OUT_OF_RANGE)
1219 ); }
1221
1222 #[test]
1223 fn test_parsed_to_datetime_with_timezone() {
1224 macro_rules! parse {
1225 ($tz:expr; $($k:ident: $v:expr),*) => (
1226 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_datetime_with_timezone(&$tz)
1227 )
1228 }
1229
1230 assert_eq!(
1232 parse!(Utc;
1233 year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1234 minute: 26, second: 40, nanosecond: 12_345_678, offset: 0),
1235 Ok(Utc
1236 .from_local_datetime(
1237 &NaiveDate::from_ymd_opt(2014, 12, 31)
1238 .unwrap()
1239 .and_hms_nano_opt(4, 26, 40, 12_345_678)
1240 .unwrap()
1241 )
1242 .unwrap())
1243 );
1244 assert_eq!(
1245 parse!(Utc;
1246 year: 2014, ordinal: 365, hour_div_12: 1, hour_mod_12: 1,
1247 minute: 26, second: 40, nanosecond: 12_345_678, offset: 32400),
1248 Err(IMPOSSIBLE)
1249 );
1250 assert_eq!(
1251 parse!(FixedOffset::east_opt(32400).unwrap();
1252 year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1253 minute: 26, second: 40, nanosecond: 12_345_678, offset: 0),
1254 Err(IMPOSSIBLE)
1255 );
1256 assert_eq!(
1257 parse!(FixedOffset::east_opt(32400).unwrap();
1258 year: 2014, ordinal: 365, hour_div_12: 1, hour_mod_12: 1,
1259 minute: 26, second: 40, nanosecond: 12_345_678, offset: 32400),
1260 Ok(FixedOffset::east_opt(32400)
1261 .unwrap()
1262 .from_local_datetime(
1263 &NaiveDate::from_ymd_opt(2014, 12, 31)
1264 .unwrap()
1265 .and_hms_nano_opt(13, 26, 40, 12_345_678)
1266 .unwrap()
1267 )
1268 .unwrap())
1269 );
1270
1271 assert_eq!(
1273 parse!(Utc; timestamp: 1_420_000_000, offset: 0),
1274 Ok(Utc.with_ymd_and_hms(2014, 12, 31, 4, 26, 40).unwrap())
1275 );
1276 assert_eq!(parse!(Utc; timestamp: 1_420_000_000, offset: 32400), Err(IMPOSSIBLE));
1277 assert_eq!(
1278 parse!(FixedOffset::east_opt(32400).unwrap(); timestamp: 1_420_000_000, offset: 0),
1279 Err(IMPOSSIBLE)
1280 );
1281 assert_eq!(
1282 parse!(FixedOffset::east_opt(32400).unwrap(); timestamp: 1_420_000_000, offset: 32400),
1283 Ok(FixedOffset::east_opt(32400)
1284 .unwrap()
1285 .with_ymd_and_hms(2014, 12, 31, 13, 26, 40)
1286 .unwrap())
1287 );
1288
1289 }
1291
1292 #[test]
1293 fn issue_551() {
1294 use crate::Weekday;
1295 let mut parsed = Parsed::new();
1296
1297 parsed.year = Some(2002);
1298 parsed.week_from_mon = Some(22);
1299 parsed.weekday = Some(Weekday::Mon);
1300 assert_eq!(NaiveDate::from_ymd_opt(2002, 6, 3).unwrap(), parsed.to_naive_date().unwrap());
1301
1302 parsed.year = Some(2001);
1303 assert_eq!(NaiveDate::from_ymd_opt(2001, 5, 28).unwrap(), parsed.to_naive_date().unwrap());
1304 }
1305}