1use super::{IMPOSSIBLE, NOT_ENOUGH, OUT_OF_RANGE, ParseResult};
8use crate::naive::{NaiveDate, NaiveDateTime, NaiveTime};
9use crate::offset::{FixedOffset, MappedLocalTime, Offset, TimeZone};
10use crate::{DateTime, Datelike, TimeDelta, Timelike, Weekday};
11
12#[allow(clippy::manual_non_exhaustive)]
128#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
129#[cfg_attr(feature = "defmt", derive(defmt::Format))]
130pub struct Parsed {
131 #[doc(hidden)]
132 pub year: Option<i32>,
133 #[doc(hidden)]
134 pub year_div_100: Option<i32>,
135 #[doc(hidden)]
136 pub year_mod_100: Option<i32>,
137 #[doc(hidden)]
138 pub isoyear: Option<i32>,
139 #[doc(hidden)]
140 pub isoyear_div_100: Option<i32>,
141 #[doc(hidden)]
142 pub isoyear_mod_100: Option<i32>,
143 #[doc(hidden)]
144 pub quarter: Option<u32>,
145 #[doc(hidden)]
146 pub month: Option<u32>,
147 #[doc(hidden)]
148 pub week_from_sun: Option<u32>,
149 #[doc(hidden)]
150 pub week_from_mon: Option<u32>,
151 #[doc(hidden)]
152 pub isoweek: Option<u32>,
153 #[doc(hidden)]
154 pub weekday: Option<Weekday>,
155 #[doc(hidden)]
156 pub ordinal: Option<u32>,
157 #[doc(hidden)]
158 pub day: Option<u32>,
159 #[doc(hidden)]
160 pub hour_div_12: Option<u32>,
161 #[doc(hidden)]
162 pub hour_mod_12: Option<u32>,
163 #[doc(hidden)]
164 pub minute: Option<u32>,
165 #[doc(hidden)]
166 pub second: Option<u32>,
167 #[doc(hidden)]
168 pub nanosecond: Option<u32>,
169 #[doc(hidden)]
170 pub timestamp: Option<i64>,
171 #[doc(hidden)]
172 pub offset: Option<i32>,
173 #[doc(hidden)]
174 _dummy: (),
175}
176
177#[inline]
180fn set_if_consistent<T: PartialEq>(old: &mut Option<T>, new: T) -> ParseResult<()> {
181 match old {
182 Some(old) if *old != new => Err(IMPOSSIBLE),
183 _ => {
184 *old = Some(new);
185 Ok(())
186 }
187 }
188}
189
190impl Parsed {
191 #[must_use]
193 pub fn new() -> Parsed {
194 Parsed::default()
195 }
196
197 #[inline]
208 pub fn set_year(&mut self, value: i64) -> ParseResult<()> {
209 set_if_consistent(&mut self.year, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
210 }
211
212 #[inline]
220 pub fn set_year_div_100(&mut self, value: i64) -> ParseResult<()> {
221 if !(0..=i32::MAX as i64).contains(&value) {
222 return Err(OUT_OF_RANGE);
223 }
224 set_if_consistent(&mut self.year_div_100, value as i32)
225 }
226
227 #[inline]
242 pub fn set_year_mod_100(&mut self, value: i64) -> ParseResult<()> {
243 if !(0..100).contains(&value) {
244 return Err(OUT_OF_RANGE);
245 }
246 set_if_consistent(&mut self.year_mod_100, value as i32)
247 }
248
249 #[inline]
263 pub fn set_isoyear(&mut self, value: i64) -> ParseResult<()> {
264 set_if_consistent(&mut self.isoyear, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
265 }
266
267 #[inline]
278 pub fn set_isoyear_div_100(&mut self, value: i64) -> ParseResult<()> {
279 if !(0..=i32::MAX as i64).contains(&value) {
280 return Err(OUT_OF_RANGE);
281 }
282 set_if_consistent(&mut self.isoyear_div_100, value as i32)
283 }
284
285 #[inline]
303 pub fn set_isoyear_mod_100(&mut self, value: i64) -> ParseResult<()> {
304 if !(0..100).contains(&value) {
305 return Err(OUT_OF_RANGE);
306 }
307 set_if_consistent(&mut self.isoyear_mod_100, value as i32)
308 }
309
310 #[inline]
320 pub fn set_quarter(&mut self, value: i64) -> ParseResult<()> {
321 if !(1..=4).contains(&value) {
322 return Err(OUT_OF_RANGE);
323 }
324 set_if_consistent(&mut self.quarter, value as u32)
325 }
326
327 #[inline]
335 pub fn set_month(&mut self, value: i64) -> ParseResult<()> {
336 if !(1..=12).contains(&value) {
337 return Err(OUT_OF_RANGE);
338 }
339 set_if_consistent(&mut self.month, value as u32)
340 }
341
342 #[inline]
352 pub fn set_week_from_sun(&mut self, value: i64) -> ParseResult<()> {
353 if !(0..=53).contains(&value) {
354 return Err(OUT_OF_RANGE);
355 }
356 set_if_consistent(&mut self.week_from_sun, value as u32)
357 }
358
359 #[inline]
370 pub fn set_week_from_mon(&mut self, value: i64) -> ParseResult<()> {
371 if !(0..=53).contains(&value) {
372 return Err(OUT_OF_RANGE);
373 }
374 set_if_consistent(&mut self.week_from_mon, value as u32)
375 }
376
377 #[inline]
387 pub fn set_isoweek(&mut self, value: i64) -> ParseResult<()> {
388 if !(1..=53).contains(&value) {
389 return Err(OUT_OF_RANGE);
390 }
391 set_if_consistent(&mut self.isoweek, value as u32)
392 }
393
394 #[inline]
400 pub fn set_weekday(&mut self, value: Weekday) -> ParseResult<()> {
401 set_if_consistent(&mut self.weekday, value)
402 }
403
404 #[inline]
412 pub fn set_ordinal(&mut self, value: i64) -> ParseResult<()> {
413 if !(1..=366).contains(&value) {
414 return Err(OUT_OF_RANGE);
415 }
416 set_if_consistent(&mut self.ordinal, value as u32)
417 }
418
419 #[inline]
427 pub fn set_day(&mut self, value: i64) -> ParseResult<()> {
428 if !(1..=31).contains(&value) {
429 return Err(OUT_OF_RANGE);
430 }
431 set_if_consistent(&mut self.day, value as u32)
432 }
433
434 #[inline]
442 pub fn set_ampm(&mut self, value: bool) -> ParseResult<()> {
443 set_if_consistent(&mut self.hour_div_12, value as u32)
444 }
445
446 #[inline]
458 pub fn set_hour12(&mut self, mut value: i64) -> ParseResult<()> {
459 if !(1..=12).contains(&value) {
460 return Err(OUT_OF_RANGE);
461 }
462 if value == 12 {
463 value = 0
464 }
465 set_if_consistent(&mut self.hour_mod_12, value as u32)
466 }
467
468 #[inline]
478 pub fn set_hour(&mut self, value: i64) -> ParseResult<()> {
479 let (hour_div_12, hour_mod_12) = match value {
480 hour @ 0..=11 => (0, hour as u32),
481 hour @ 12..=23 => (1, hour as u32 - 12),
482 _ => return Err(OUT_OF_RANGE),
483 };
484 set_if_consistent(&mut self.hour_div_12, hour_div_12)?;
485 set_if_consistent(&mut self.hour_mod_12, hour_mod_12)
486 }
487
488 #[inline]
496 pub fn set_minute(&mut self, value: i64) -> ParseResult<()> {
497 if !(0..=59).contains(&value) {
498 return Err(OUT_OF_RANGE);
499 }
500 set_if_consistent(&mut self.minute, value as u32)
501 }
502
503 #[inline]
513 pub fn set_second(&mut self, value: i64) -> ParseResult<()> {
514 if !(0..=60).contains(&value) {
515 return Err(OUT_OF_RANGE);
516 }
517 set_if_consistent(&mut self.second, value as u32)
518 }
519
520 #[inline]
530 pub fn set_nanosecond(&mut self, value: i64) -> ParseResult<()> {
531 if !(0..=999_999_999).contains(&value) {
532 return Err(OUT_OF_RANGE);
533 }
534 set_if_consistent(&mut self.nanosecond, value as u32)
535 }
536
537 #[inline]
546 pub fn set_timestamp(&mut self, value: i64) -> ParseResult<()> {
547 set_if_consistent(&mut self.timestamp, value)
548 }
549
550 #[inline]
560 pub fn set_offset(&mut self, value: i64) -> ParseResult<()> {
561 set_if_consistent(&mut self.offset, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
562 }
563
564 pub fn to_naive_date(&self) -> ParseResult<NaiveDate> {
588 fn resolve_year(
589 y: Option<i32>,
590 q: Option<i32>,
591 r: Option<i32>,
592 ) -> ParseResult<Option<i32>> {
593 match (y, q, r) {
594 (y, None, None) => Ok(y),
597
598 (Some(y), q, r @ Some(0..=99)) | (Some(y), q, r @ None) => {
603 if y < 0 {
604 return Err(IMPOSSIBLE);
605 }
606 let q_ = y / 100;
607 let r_ = y % 100;
608 if q.unwrap_or(q_) == q_ && r.unwrap_or(r_) == r_ {
609 Ok(Some(y))
610 } else {
611 Err(IMPOSSIBLE)
612 }
613 }
614
615 (None, Some(q), Some(r @ 0..=99)) => {
618 if q < 0 {
619 return Err(IMPOSSIBLE);
620 }
621 let y = q.checked_mul(100).and_then(|v| v.checked_add(r));
622 Ok(Some(y.ok_or(OUT_OF_RANGE)?))
623 }
624
625 (None, None, Some(r @ 0..=99)) => Ok(Some(r + if r < 70 { 2000 } else { 1900 })),
628
629 (None, Some(_), None) => Err(NOT_ENOUGH),
631 (_, _, Some(_)) => Err(OUT_OF_RANGE),
632 }
633 }
634
635 let given_year = resolve_year(self.year, self.year_div_100, self.year_mod_100)?;
636 let given_isoyear = resolve_year(self.isoyear, self.isoyear_div_100, self.isoyear_mod_100)?;
637
638 let verify_ymd = |date: NaiveDate| {
640 let year = date.year();
641 let (year_div_100, year_mod_100) = if year >= 0 {
642 (Some(year / 100), Some(year % 100))
643 } else {
644 (None, None) };
646 let month = date.month();
647 let day = date.day();
648 self.year.unwrap_or(year) == year
649 && self.year_div_100.or(year_div_100) == year_div_100
650 && self.year_mod_100.or(year_mod_100) == year_mod_100
651 && self.month.unwrap_or(month) == month
652 && self.day.unwrap_or(day) == day
653 };
654
655 let verify_isoweekdate = |date: NaiveDate| {
657 let week = date.iso_week();
658 let isoyear = week.year();
659 let isoweek = week.week();
660 let weekday = date.weekday();
661 let (isoyear_div_100, isoyear_mod_100) = if isoyear >= 0 {
662 (Some(isoyear / 100), Some(isoyear % 100))
663 } else {
664 (None, None) };
666 self.isoyear.unwrap_or(isoyear) == isoyear
667 && self.isoyear_div_100.or(isoyear_div_100) == isoyear_div_100
668 && self.isoyear_mod_100.or(isoyear_mod_100) == isoyear_mod_100
669 && self.isoweek.unwrap_or(isoweek) == isoweek
670 && self.weekday.unwrap_or(weekday) == weekday
671 };
672
673 let verify_ordinal = |date: NaiveDate| {
675 let ordinal = date.ordinal();
676 let week_from_sun = date.weeks_from(Weekday::Sun);
677 let week_from_mon = date.weeks_from(Weekday::Mon);
678 self.ordinal.unwrap_or(ordinal) == ordinal
679 && self.week_from_sun.map_or(week_from_sun, |v| v as i32) == week_from_sun
680 && self.week_from_mon.map_or(week_from_mon, |v| v as i32) == week_from_mon
681 };
682
683 let (verified, parsed_date) = match (given_year, given_isoyear, self) {
687 (Some(year), _, &Parsed { month: Some(month), day: Some(day), .. }) => {
688 let date = NaiveDate::from_ymd_opt(year, month, day).ok_or(OUT_OF_RANGE)?;
690 (verify_isoweekdate(date) && verify_ordinal(date), date)
691 }
692
693 (Some(year), _, &Parsed { ordinal: Some(ordinal), .. }) => {
694 let date = NaiveDate::from_yo_opt(year, ordinal).ok_or(OUT_OF_RANGE)?;
696 (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
697 }
698
699 (Some(year), _, &Parsed { week_from_sun: Some(week), weekday: Some(weekday), .. }) => {
700 let date = resolve_week_date(year, week, weekday, Weekday::Sun)?;
702 (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
703 }
704
705 (Some(year), _, &Parsed { week_from_mon: Some(week), weekday: Some(weekday), .. }) => {
706 let date = resolve_week_date(year, week, weekday, Weekday::Mon)?;
708 (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
709 }
710
711 (_, Some(isoyear), &Parsed { isoweek: Some(isoweek), weekday: Some(weekday), .. }) => {
712 let date = NaiveDate::from_isoywd_opt(isoyear, isoweek, weekday);
714 let date = date.ok_or(OUT_OF_RANGE)?;
715 (verify_ymd(date) && verify_ordinal(date), date)
716 }
717
718 (_, _, _) => return Err(NOT_ENOUGH),
719 };
720
721 if !verified {
722 return Err(IMPOSSIBLE);
723 } else if let Some(parsed) = self.quarter {
724 if parsed != parsed_date.quarter() {
725 return Err(IMPOSSIBLE);
726 }
727 }
728
729 Ok(parsed_date)
730 }
731
732 pub fn to_naive_time(&self) -> ParseResult<NaiveTime> {
750 let hour_div_12 = match self.hour_div_12 {
751 Some(v @ 0..=1) => v,
752 Some(_) => return Err(OUT_OF_RANGE),
753 None => return Err(NOT_ENOUGH),
754 };
755 let hour_mod_12 = match self.hour_mod_12 {
756 Some(v @ 0..=11) => v,
757 Some(_) => return Err(OUT_OF_RANGE),
758 None => return Err(NOT_ENOUGH),
759 };
760 let hour = hour_div_12 * 12 + hour_mod_12;
761
762 let minute = match self.minute {
763 Some(v @ 0..=59) => v,
764 Some(_) => return Err(OUT_OF_RANGE),
765 None => return Err(NOT_ENOUGH),
766 };
767
768 let (second, mut nano) = match self.second.unwrap_or(0) {
770 v @ 0..=59 => (v, 0),
771 60 => (59, 1_000_000_000),
772 _ => return Err(OUT_OF_RANGE),
773 };
774 nano += match self.nanosecond {
775 Some(v @ 0..=999_999_999) if self.second.is_some() => v,
776 Some(0..=999_999_999) => return Err(NOT_ENOUGH), Some(_) => return Err(OUT_OF_RANGE),
778 None => 0,
779 };
780
781 NaiveTime::from_hms_nano_opt(hour, minute, second, nano).ok_or(OUT_OF_RANGE)
782 }
783
784 pub fn to_naive_datetime_with_offset(&self, offset: i32) -> ParseResult<NaiveDateTime> {
804 let date = self.to_naive_date();
805 let time = self.to_naive_time();
806 if let (Ok(date), Ok(time)) = (date, time) {
807 let datetime = date.and_time(time);
808
809 let timestamp = datetime.and_utc().timestamp() - i64::from(offset);
812 if let Some(given_timestamp) = self.timestamp {
813 if given_timestamp != timestamp
815 && !(datetime.nanosecond() >= 1_000_000_000 && given_timestamp == timestamp + 1)
816 {
817 return Err(IMPOSSIBLE);
818 }
819 }
820
821 Ok(datetime)
822 } else if let Some(timestamp) = self.timestamp {
823 use super::ParseError as PE;
824 use super::ParseErrorKind::{Impossible, OutOfRange};
825
826 match (date, time) {
829 (Err(PE(OutOfRange)), _) | (_, Err(PE(OutOfRange))) => return Err(OUT_OF_RANGE),
830 (Err(PE(Impossible)), _) | (_, Err(PE(Impossible))) => return Err(IMPOSSIBLE),
831 (_, _) => {} }
833
834 let ts = timestamp.checked_add(i64::from(offset)).ok_or(OUT_OF_RANGE)?;
836 let mut datetime = DateTime::from_timestamp_secs(ts).ok_or(OUT_OF_RANGE)?.naive_utc();
837
838 let mut parsed = self.clone();
841 if parsed.second == Some(60) {
842 match datetime.second() {
844 59 => {}
846 0 => {
848 datetime -= TimeDelta::try_seconds(1).unwrap();
849 }
850 _ => return Err(IMPOSSIBLE),
852 }
853 } else {
855 parsed.set_second(i64::from(datetime.second()))?;
856 }
857 parsed.set_year(i64::from(datetime.year()))?;
858 parsed.set_ordinal(i64::from(datetime.ordinal()))?; parsed.set_hour(i64::from(datetime.hour()))?;
860 parsed.set_minute(i64::from(datetime.minute()))?;
861
862 let date = parsed.to_naive_date()?;
864 let time = parsed.to_naive_time()?;
865 Ok(date.and_time(time))
866 } else {
867 date?;
869 time?;
870 unreachable!()
871 }
872 }
873
874 pub fn to_fixed_offset(&self) -> ParseResult<FixedOffset> {
882 FixedOffset::east_opt(self.offset.ok_or(NOT_ENOUGH)?).ok_or(OUT_OF_RANGE)
883 }
884
885 pub fn to_datetime(&self) -> ParseResult<DateTime<FixedOffset>> {
904 let offset = match (self.offset, self.timestamp) {
906 (Some(off), _) => off,
907 (None, Some(_)) => 0, (None, None) => return Err(NOT_ENOUGH),
909 };
910 let datetime = self.to_naive_datetime_with_offset(offset)?;
911 let offset = FixedOffset::east_opt(offset).ok_or(OUT_OF_RANGE)?;
912
913 match offset.from_local_datetime(&datetime) {
914 MappedLocalTime::None => Err(IMPOSSIBLE),
915 MappedLocalTime::Single(t) => Ok(t),
916 MappedLocalTime::Ambiguous(..) => Err(NOT_ENOUGH),
917 }
918 }
919
920 pub fn to_datetime_with_timezone<Tz: TimeZone>(&self, tz: &Tz) -> ParseResult<DateTime<Tz>> {
946 let mut guessed_offset = 0;
948 if let Some(timestamp) = self.timestamp {
949 let nanosecond = self.nanosecond.unwrap_or(0);
952 let dt =
953 DateTime::from_timestamp(timestamp, nanosecond).ok_or(OUT_OF_RANGE)?.naive_utc();
954 guessed_offset = tz.offset_from_utc_datetime(&dt).fix().local_minus_utc();
955 }
956
957 let check_offset = |dt: &DateTime<Tz>| {
959 if let Some(offset) = self.offset {
960 dt.offset().fix().local_minus_utc() == offset
961 } else {
962 true
963 }
964 };
965
966 let datetime = self.to_naive_datetime_with_offset(guessed_offset)?;
969 match tz.from_local_datetime(&datetime) {
970 MappedLocalTime::None => Err(IMPOSSIBLE),
971 MappedLocalTime::Single(t) => {
972 if check_offset(&t) {
973 Ok(t)
974 } else {
975 Err(IMPOSSIBLE)
976 }
977 }
978 MappedLocalTime::Ambiguous(min, max) => {
979 match (check_offset(&min), check_offset(&max)) {
981 (false, false) => Err(IMPOSSIBLE),
982 (false, true) => Ok(max),
983 (true, false) => Ok(min),
984 (true, true) => Err(NOT_ENOUGH),
985 }
986 }
987 }
988 }
989
990 #[inline]
994 pub fn year(&self) -> Option<i32> {
995 self.year
996 }
997
998 #[inline]
1002 pub fn year_div_100(&self) -> Option<i32> {
1003 self.year_div_100
1004 }
1005
1006 #[inline]
1010 pub fn year_mod_100(&self) -> Option<i32> {
1011 self.year_mod_100
1012 }
1013
1014 #[inline]
1020 pub fn isoyear(&self) -> Option<i32> {
1021 self.isoyear
1022 }
1023
1024 #[inline]
1030 pub fn isoyear_div_100(&self) -> Option<i32> {
1031 self.isoyear_div_100
1032 }
1033
1034 #[inline]
1040 pub fn isoyear_mod_100(&self) -> Option<i32> {
1041 self.isoyear_mod_100
1042 }
1043
1044 #[inline]
1048 pub fn quarter(&self) -> Option<u32> {
1049 self.quarter
1050 }
1051
1052 #[inline]
1056 pub fn month(&self) -> Option<u32> {
1057 self.month
1058 }
1059
1060 #[inline]
1064 pub fn week_from_sun(&self) -> Option<u32> {
1065 self.week_from_sun
1066 }
1067
1068 #[inline]
1072 pub fn week_from_mon(&self) -> Option<u32> {
1073 self.week_from_mon
1074 }
1075
1076 #[inline]
1082 pub fn isoweek(&self) -> Option<u32> {
1083 self.isoweek
1084 }
1085
1086 #[inline]
1090 pub fn weekday(&self) -> Option<Weekday> {
1091 self.weekday
1092 }
1093
1094 #[inline]
1098 pub fn ordinal(&self) -> Option<u32> {
1099 self.ordinal
1100 }
1101
1102 #[inline]
1106 pub fn day(&self) -> Option<u32> {
1107 self.day
1108 }
1109
1110 #[inline]
1116 pub fn hour_div_12(&self) -> Option<u32> {
1117 self.hour_div_12
1118 }
1119
1120 pub fn hour_mod_12(&self) -> Option<u32> {
1124 self.hour_mod_12
1125 }
1126
1127 #[inline]
1131 pub fn minute(&self) -> Option<u32> {
1132 self.minute
1133 }
1134
1135 #[inline]
1139 pub fn second(&self) -> Option<u32> {
1140 self.second
1141 }
1142
1143 #[inline]
1147 pub fn nanosecond(&self) -> Option<u32> {
1148 self.nanosecond
1149 }
1150
1151 #[inline]
1155 pub fn timestamp(&self) -> Option<i64> {
1156 self.timestamp
1157 }
1158
1159 #[inline]
1163 pub fn offset(&self) -> Option<i32> {
1164 self.offset
1165 }
1166}
1167
1168fn resolve_week_date(
1173 year: i32,
1174 week: u32,
1175 weekday: Weekday,
1176 week_start_day: Weekday,
1177) -> ParseResult<NaiveDate> {
1178 if week > 53 {
1179 return Err(OUT_OF_RANGE);
1180 }
1181
1182 let first_day_of_year = NaiveDate::from_yo_opt(year, 1).ok_or(OUT_OF_RANGE)?;
1183 let first_week_start = 1 + week_start_day.days_since(first_day_of_year.weekday()) as i32;
1185 let weekday = weekday.days_since(week_start_day) as i32;
1187 let ordinal = first_week_start + (week as i32 - 1) * 7 + weekday;
1188 if ordinal <= 0 {
1189 return Err(IMPOSSIBLE);
1190 }
1191 first_day_of_year.with_ordinal(ordinal as u32).ok_or(IMPOSSIBLE)
1192}
1193
1194#[cfg(test)]
1195mod tests {
1196 use super::super::{IMPOSSIBLE, NOT_ENOUGH, OUT_OF_RANGE};
1197 use super::Parsed;
1198 use crate::Datelike;
1199 use crate::Weekday::*;
1200 use crate::naive::{NaiveDate, NaiveTime};
1201 use crate::offset::{FixedOffset, TimeZone, Utc};
1202
1203 #[test]
1204 fn test_parsed_set_fields() {
1205 let mut p = Parsed::new();
1207 assert_eq!(p.set_year(1987), Ok(()));
1208 assert_eq!(p.set_year(1986), Err(IMPOSSIBLE));
1209 assert_eq!(p.set_year(1988), Err(IMPOSSIBLE));
1210 assert_eq!(p.set_year(1987), Ok(()));
1211 assert_eq!(p.set_year_div_100(20), Ok(())); assert_eq!(p.set_year_div_100(21), Err(IMPOSSIBLE));
1213 assert_eq!(p.set_year_div_100(19), Err(IMPOSSIBLE));
1214 assert_eq!(p.set_year_mod_100(37), Ok(())); assert_eq!(p.set_year_mod_100(38), Err(IMPOSSIBLE));
1216 assert_eq!(p.set_year_mod_100(36), Err(IMPOSSIBLE));
1217
1218 let mut p = Parsed::new();
1219 assert_eq!(p.set_year(0), Ok(()));
1220 assert_eq!(p.set_year_div_100(0), Ok(()));
1221 assert_eq!(p.set_year_mod_100(0), Ok(()));
1222
1223 let mut p = Parsed::new();
1224 assert_eq!(p.set_year_div_100(-1), Err(OUT_OF_RANGE));
1225 assert_eq!(p.set_year_mod_100(-1), Err(OUT_OF_RANGE));
1226 assert_eq!(p.set_year(-1), Ok(()));
1227 assert_eq!(p.set_year(-2), Err(IMPOSSIBLE));
1228 assert_eq!(p.set_year(0), Err(IMPOSSIBLE));
1229
1230 let mut p = Parsed::new();
1231 assert_eq!(p.set_year_div_100(0x1_0000_0008), Err(OUT_OF_RANGE));
1232 assert_eq!(p.set_year_div_100(8), Ok(()));
1233 assert_eq!(p.set_year_div_100(0x1_0000_0008), Err(OUT_OF_RANGE));
1234
1235 let mut p = Parsed::new();
1237 assert_eq!(p.set_month(7), Ok(()));
1238 assert_eq!(p.set_month(1), Err(IMPOSSIBLE));
1239 assert_eq!(p.set_month(6), Err(IMPOSSIBLE));
1240 assert_eq!(p.set_month(8), Err(IMPOSSIBLE));
1241 assert_eq!(p.set_month(12), Err(IMPOSSIBLE));
1242
1243 let mut p = Parsed::new();
1244 assert_eq!(p.set_month(8), Ok(()));
1245 assert_eq!(p.set_month(0x1_0000_0008), Err(OUT_OF_RANGE));
1246
1247 let mut p = Parsed::new();
1249 assert_eq!(p.set_hour(12), Ok(()));
1250 assert_eq!(p.set_hour(11), Err(IMPOSSIBLE));
1251 assert_eq!(p.set_hour(13), Err(IMPOSSIBLE));
1252 assert_eq!(p.set_hour(12), Ok(()));
1253 assert_eq!(p.set_ampm(false), Err(IMPOSSIBLE));
1254 assert_eq!(p.set_ampm(true), Ok(()));
1255 assert_eq!(p.set_hour12(12), Ok(()));
1256 assert_eq!(p.set_hour12(0), Err(OUT_OF_RANGE)); assert_eq!(p.set_hour12(1), Err(IMPOSSIBLE));
1258 assert_eq!(p.set_hour12(11), Err(IMPOSSIBLE));
1259
1260 let mut p = Parsed::new();
1261 assert_eq!(p.set_ampm(true), Ok(()));
1262 assert_eq!(p.set_hour12(7), Ok(()));
1263 assert_eq!(p.set_hour(7), Err(IMPOSSIBLE));
1264 assert_eq!(p.set_hour(18), Err(IMPOSSIBLE));
1265 assert_eq!(p.set_hour(19), Ok(()));
1266
1267 let mut p = Parsed::new();
1269 assert_eq!(p.set_timestamp(1_234_567_890), Ok(()));
1270 assert_eq!(p.set_timestamp(1_234_567_889), Err(IMPOSSIBLE));
1271 assert_eq!(p.set_timestamp(1_234_567_891), Err(IMPOSSIBLE));
1272 }
1273
1274 #[test]
1275 fn test_parsed_set_range() {
1276 assert_eq!(Parsed::new().set_year(i32::MIN as i64 - 1), Err(OUT_OF_RANGE));
1277 assert!(Parsed::new().set_year(i32::MIN as i64).is_ok());
1278 assert!(Parsed::new().set_year(i32::MAX as i64).is_ok());
1279 assert_eq!(Parsed::new().set_year(i32::MAX as i64 + 1), Err(OUT_OF_RANGE));
1280
1281 assert_eq!(Parsed::new().set_year_div_100(-1), Err(OUT_OF_RANGE));
1282 assert!(Parsed::new().set_year_div_100(0).is_ok());
1283 assert!(Parsed::new().set_year_div_100(i32::MAX as i64).is_ok());
1284 assert_eq!(Parsed::new().set_year_div_100(i32::MAX as i64 + 1), Err(OUT_OF_RANGE));
1285
1286 assert_eq!(Parsed::new().set_year_mod_100(-1), Err(OUT_OF_RANGE));
1287 assert!(Parsed::new().set_year_mod_100(0).is_ok());
1288 assert!(Parsed::new().set_year_mod_100(99).is_ok());
1289 assert_eq!(Parsed::new().set_year_mod_100(100), Err(OUT_OF_RANGE));
1290
1291 assert_eq!(Parsed::new().set_isoyear(i32::MIN as i64 - 1), Err(OUT_OF_RANGE));
1292 assert!(Parsed::new().set_isoyear(i32::MIN as i64).is_ok());
1293 assert!(Parsed::new().set_isoyear(i32::MAX as i64).is_ok());
1294 assert_eq!(Parsed::new().set_isoyear(i32::MAX as i64 + 1), Err(OUT_OF_RANGE));
1295
1296 assert_eq!(Parsed::new().set_isoyear_div_100(-1), Err(OUT_OF_RANGE));
1297 assert!(Parsed::new().set_isoyear_div_100(0).is_ok());
1298 assert!(Parsed::new().set_isoyear_div_100(99).is_ok());
1299 assert_eq!(Parsed::new().set_isoyear_div_100(i32::MAX as i64 + 1), Err(OUT_OF_RANGE));
1300
1301 assert_eq!(Parsed::new().set_isoyear_mod_100(-1), Err(OUT_OF_RANGE));
1302 assert!(Parsed::new().set_isoyear_mod_100(0).is_ok());
1303 assert!(Parsed::new().set_isoyear_mod_100(99).is_ok());
1304 assert_eq!(Parsed::new().set_isoyear_mod_100(100), Err(OUT_OF_RANGE));
1305
1306 assert_eq!(Parsed::new().set_quarter(0), Err(OUT_OF_RANGE));
1307 assert!(Parsed::new().set_quarter(1).is_ok());
1308 assert!(Parsed::new().set_quarter(4).is_ok());
1309 assert_eq!(Parsed::new().set_quarter(5), Err(OUT_OF_RANGE));
1310
1311 assert_eq!(Parsed::new().set_month(0), Err(OUT_OF_RANGE));
1312 assert!(Parsed::new().set_month(1).is_ok());
1313 assert!(Parsed::new().set_month(12).is_ok());
1314 assert_eq!(Parsed::new().set_month(13), Err(OUT_OF_RANGE));
1315
1316 assert_eq!(Parsed::new().set_week_from_sun(-1), Err(OUT_OF_RANGE));
1317 assert!(Parsed::new().set_week_from_sun(0).is_ok());
1318 assert!(Parsed::new().set_week_from_sun(53).is_ok());
1319 assert_eq!(Parsed::new().set_week_from_sun(54), Err(OUT_OF_RANGE));
1320
1321 assert_eq!(Parsed::new().set_week_from_mon(-1), Err(OUT_OF_RANGE));
1322 assert!(Parsed::new().set_week_from_mon(0).is_ok());
1323 assert!(Parsed::new().set_week_from_mon(53).is_ok());
1324 assert_eq!(Parsed::new().set_week_from_mon(54), Err(OUT_OF_RANGE));
1325
1326 assert_eq!(Parsed::new().set_isoweek(0), Err(OUT_OF_RANGE));
1327 assert!(Parsed::new().set_isoweek(1).is_ok());
1328 assert!(Parsed::new().set_isoweek(53).is_ok());
1329 assert_eq!(Parsed::new().set_isoweek(54), Err(OUT_OF_RANGE));
1330
1331 assert_eq!(Parsed::new().set_ordinal(0), Err(OUT_OF_RANGE));
1332 assert!(Parsed::new().set_ordinal(1).is_ok());
1333 assert!(Parsed::new().set_ordinal(366).is_ok());
1334 assert_eq!(Parsed::new().set_ordinal(367), Err(OUT_OF_RANGE));
1335
1336 assert_eq!(Parsed::new().set_day(0), Err(OUT_OF_RANGE));
1337 assert!(Parsed::new().set_day(1).is_ok());
1338 assert!(Parsed::new().set_day(31).is_ok());
1339 assert_eq!(Parsed::new().set_day(32), Err(OUT_OF_RANGE));
1340
1341 assert_eq!(Parsed::new().set_hour12(0), Err(OUT_OF_RANGE));
1342 assert!(Parsed::new().set_hour12(1).is_ok());
1343 assert!(Parsed::new().set_hour12(12).is_ok());
1344 assert_eq!(Parsed::new().set_hour12(13), Err(OUT_OF_RANGE));
1345
1346 assert_eq!(Parsed::new().set_hour(-1), Err(OUT_OF_RANGE));
1347 assert!(Parsed::new().set_hour(0).is_ok());
1348 assert!(Parsed::new().set_hour(23).is_ok());
1349 assert_eq!(Parsed::new().set_hour(24), Err(OUT_OF_RANGE));
1350
1351 assert_eq!(Parsed::new().set_minute(-1), Err(OUT_OF_RANGE));
1352 assert!(Parsed::new().set_minute(0).is_ok());
1353 assert!(Parsed::new().set_minute(59).is_ok());
1354 assert_eq!(Parsed::new().set_minute(60), Err(OUT_OF_RANGE));
1355
1356 assert_eq!(Parsed::new().set_second(-1), Err(OUT_OF_RANGE));
1357 assert!(Parsed::new().set_second(0).is_ok());
1358 assert!(Parsed::new().set_second(60).is_ok());
1359 assert_eq!(Parsed::new().set_second(61), Err(OUT_OF_RANGE));
1360
1361 assert_eq!(Parsed::new().set_nanosecond(-1), Err(OUT_OF_RANGE));
1362 assert!(Parsed::new().set_nanosecond(0).is_ok());
1363 assert!(Parsed::new().set_nanosecond(999_999_999).is_ok());
1364 assert_eq!(Parsed::new().set_nanosecond(1_000_000_000), Err(OUT_OF_RANGE));
1365
1366 assert!(Parsed::new().set_timestamp(i64::MIN).is_ok());
1367 assert!(Parsed::new().set_timestamp(i64::MAX).is_ok());
1368
1369 assert_eq!(Parsed::new().set_offset(i32::MIN as i64 - 1), Err(OUT_OF_RANGE));
1370 assert!(Parsed::new().set_offset(i32::MIN as i64).is_ok());
1371 assert!(Parsed::new().set_offset(i32::MAX as i64).is_ok());
1372 assert_eq!(Parsed::new().set_offset(i32::MAX as i64 + 1), Err(OUT_OF_RANGE));
1373 }
1374
1375 #[test]
1376 fn test_parsed_to_naive_date() {
1377 macro_rules! parse {
1378 ($($k:ident: $v:expr),*) => (
1379 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_naive_date()
1380 )
1381 }
1382
1383 let ymd = |y, m, d| Ok(NaiveDate::from_ymd_opt(y, m, d).unwrap());
1384
1385 assert_eq!(parse!(), Err(NOT_ENOUGH));
1387 assert_eq!(parse!(year: 1984), Err(NOT_ENOUGH));
1388 assert_eq!(parse!(year: 1984, month: 1), Err(NOT_ENOUGH));
1389 assert_eq!(parse!(year: 1984, month: 1, day: 2), ymd(1984, 1, 2));
1390 assert_eq!(parse!(year: 1984, day: 2), Err(NOT_ENOUGH));
1391 assert_eq!(parse!(year_div_100: 19), Err(NOT_ENOUGH));
1392 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84), Err(NOT_ENOUGH));
1393 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, month: 1), Err(NOT_ENOUGH));
1394 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, month: 1, day: 2), ymd(1984, 1, 2));
1395 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, day: 2), Err(NOT_ENOUGH));
1396 assert_eq!(parse!(year_div_100: 19, month: 1, day: 2), Err(NOT_ENOUGH));
1397 assert_eq!(parse!(year_mod_100: 70, month: 1, day: 2), ymd(1970, 1, 2));
1398 assert_eq!(parse!(year_mod_100: 69, month: 1, day: 2), ymd(2069, 1, 2));
1399
1400 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, month: 2, day: 29), ymd(1984, 2, 29));
1402 assert_eq!(
1403 parse!(year_div_100: 19, year_mod_100: 83, month: 2, day: 29),
1404 Err(OUT_OF_RANGE)
1405 );
1406 assert_eq!(
1407 parse!(year_div_100: 19, year_mod_100: 83, month: 13, day: 1),
1408 Err(OUT_OF_RANGE)
1409 );
1410 assert_eq!(
1411 parse!(year_div_100: 19, year_mod_100: 83, month: 12, day: 31),
1412 ymd(1983, 12, 31)
1413 );
1414 assert_eq!(
1415 parse!(year_div_100: 19, year_mod_100: 83, month: 12, day: 32),
1416 Err(OUT_OF_RANGE)
1417 );
1418 assert_eq!(
1419 parse!(year_div_100: 19, year_mod_100: 83, month: 12, day: 0),
1420 Err(OUT_OF_RANGE)
1421 );
1422 assert_eq!(
1423 parse!(year_div_100: 19, year_mod_100: 100, month: 1, day: 1),
1424 Err(OUT_OF_RANGE)
1425 );
1426 assert_eq!(parse!(year_div_100: 19, year_mod_100: -1, month: 1, day: 1), Err(OUT_OF_RANGE));
1427 assert_eq!(parse!(year_div_100: 0, year_mod_100: 0, month: 1, day: 1), ymd(0, 1, 1));
1428 assert_eq!(parse!(year_div_100: -1, year_mod_100: 42, month: 1, day: 1), Err(IMPOSSIBLE));
1429 let max_year = NaiveDate::MAX.year();
1430 assert_eq!(
1431 parse!(year_div_100: max_year / 100,
1432 year_mod_100: max_year % 100, month: 1, day: 1),
1433 ymd(max_year, 1, 1)
1434 );
1435 assert_eq!(
1436 parse!(year_div_100: (max_year + 1) / 100,
1437 year_mod_100: (max_year + 1) % 100, month: 1, day: 1),
1438 Err(OUT_OF_RANGE)
1439 );
1440
1441 assert_eq!(parse!(year: 1984, year_div_100: 19, month: 1, day: 1), ymd(1984, 1, 1));
1443 assert_eq!(parse!(year: 1984, year_div_100: 20, month: 1, day: 1), Err(IMPOSSIBLE));
1444 assert_eq!(parse!(year: 1984, year_mod_100: 84, month: 1, day: 1), ymd(1984, 1, 1));
1445 assert_eq!(parse!(year: 1984, year_mod_100: 83, month: 1, day: 1), Err(IMPOSSIBLE));
1446 assert_eq!(
1447 parse!(year: 1984, year_div_100: 19, year_mod_100: 84, month: 1, day: 1),
1448 ymd(1984, 1, 1)
1449 );
1450 assert_eq!(
1451 parse!(year: 1984, year_div_100: 18, year_mod_100: 94, month: 1, day: 1),
1452 Err(IMPOSSIBLE)
1453 );
1454 assert_eq!(
1455 parse!(year: 1984, year_div_100: 18, year_mod_100: 184, month: 1, day: 1),
1456 Err(OUT_OF_RANGE)
1457 );
1458 assert_eq!(
1459 parse!(year: -1, year_div_100: 0, year_mod_100: -1, month: 1, day: 1),
1460 Err(OUT_OF_RANGE)
1461 );
1462 assert_eq!(
1463 parse!(year: -1, year_div_100: -1, year_mod_100: 99, month: 1, day: 1),
1464 Err(IMPOSSIBLE)
1465 );
1466 assert_eq!(parse!(year: -1, year_div_100: 0, month: 1, day: 1), Err(IMPOSSIBLE));
1467 assert_eq!(parse!(year: -1, year_mod_100: 99, month: 1, day: 1), Err(IMPOSSIBLE));
1468
1469 assert_eq!(parse!(year: 2000, quarter: 1), Err(NOT_ENOUGH));
1471 assert_eq!(parse!(year: 2000, quarter: 1, month: 1, day: 1), ymd(2000, 1, 1));
1472 assert_eq!(parse!(year: 2000, quarter: 2, month: 4, day: 1), ymd(2000, 4, 1));
1473 assert_eq!(parse!(year: 2000, quarter: 3, month: 7, day: 1), ymd(2000, 7, 1));
1474 assert_eq!(parse!(year: 2000, quarter: 4, month: 10, day: 1), ymd(2000, 10, 1));
1475
1476 assert_eq!(parse!(year: 2000, quarter: 2, month: 3, day: 31), Err(IMPOSSIBLE));
1478 assert_eq!(parse!(year: 2000, quarter: 4, month: 3, day: 31), Err(IMPOSSIBLE));
1479
1480 assert_eq!(parse!(year: 2000, week_from_mon: 0), Err(NOT_ENOUGH));
1482 assert_eq!(parse!(year: 2000, week_from_sun: 0), Err(NOT_ENOUGH));
1483 assert_eq!(parse!(year: 2000, weekday: Sun), Err(NOT_ENOUGH));
1484 assert_eq!(parse!(year: 2000, week_from_mon: 0, weekday: Fri), Err(IMPOSSIBLE));
1485 assert_eq!(parse!(year: 2000, week_from_sun: 0, weekday: Fri), Err(IMPOSSIBLE));
1486 assert_eq!(parse!(year: 2000, week_from_mon: 0, weekday: Sat), ymd(2000, 1, 1));
1487 assert_eq!(parse!(year: 2000, week_from_sun: 0, weekday: Sat), ymd(2000, 1, 1));
1488 assert_eq!(parse!(year: 2000, week_from_mon: 0, weekday: Sun), ymd(2000, 1, 2));
1489 assert_eq!(parse!(year: 2000, week_from_sun: 1, weekday: Sun), ymd(2000, 1, 2));
1490 assert_eq!(parse!(year: 2000, week_from_mon: 1, weekday: Mon), ymd(2000, 1, 3));
1491 assert_eq!(parse!(year: 2000, week_from_sun: 1, weekday: Mon), ymd(2000, 1, 3));
1492 assert_eq!(parse!(year: 2000, week_from_mon: 1, weekday: Sat), ymd(2000, 1, 8));
1493 assert_eq!(parse!(year: 2000, week_from_sun: 1, weekday: Sat), ymd(2000, 1, 8));
1494 assert_eq!(parse!(year: 2000, week_from_mon: 1, weekday: Sun), ymd(2000, 1, 9));
1495 assert_eq!(parse!(year: 2000, week_from_sun: 2, weekday: Sun), ymd(2000, 1, 9));
1496 assert_eq!(parse!(year: 2000, week_from_mon: 2, weekday: Mon), ymd(2000, 1, 10));
1497 assert_eq!(parse!(year: 2000, week_from_sun: 52, weekday: Sat), ymd(2000, 12, 30));
1498 assert_eq!(parse!(year: 2000, week_from_sun: 53, weekday: Sun), ymd(2000, 12, 31));
1499 assert_eq!(parse!(year: 2000, week_from_sun: 53, weekday: Mon), Err(IMPOSSIBLE));
1500 assert_eq!(parse!(year: 2000, week_from_sun: 0xffffffff, weekday: Mon), Err(OUT_OF_RANGE));
1501 assert_eq!(parse!(year: 2006, week_from_sun: 0, weekday: Sat), Err(IMPOSSIBLE));
1502 assert_eq!(parse!(year: 2006, week_from_sun: 1, weekday: Sun), ymd(2006, 1, 1));
1503
1504 assert_eq!(
1506 parse!(year: 2000, week_from_mon: 1, week_from_sun: 1, weekday: Sat),
1507 ymd(2000, 1, 8)
1508 );
1509 assert_eq!(
1510 parse!(year: 2000, week_from_mon: 1, week_from_sun: 2, weekday: Sun),
1511 ymd(2000, 1, 9)
1512 );
1513 assert_eq!(
1514 parse!(year: 2000, week_from_mon: 1, week_from_sun: 1, weekday: Sun),
1515 Err(IMPOSSIBLE)
1516 );
1517 assert_eq!(
1518 parse!(year: 2000, week_from_mon: 2, week_from_sun: 2, weekday: Sun),
1519 Err(IMPOSSIBLE)
1520 );
1521
1522 assert_eq!(parse!(isoyear: 2004, isoweek: 53), Err(NOT_ENOUGH));
1524 assert_eq!(parse!(isoyear: 2004, isoweek: 53, weekday: Fri), ymd(2004, 12, 31));
1525 assert_eq!(parse!(isoyear: 2004, isoweek: 53, weekday: Sat), ymd(2005, 1, 1));
1526 assert_eq!(parse!(isoyear: 2004, isoweek: 0xffffffff, weekday: Sat), Err(OUT_OF_RANGE));
1527 assert_eq!(parse!(isoyear: 2005, isoweek: 0, weekday: Thu), Err(OUT_OF_RANGE));
1528 assert_eq!(parse!(isoyear: 2005, isoweek: 5, weekday: Thu), ymd(2005, 2, 3));
1529 assert_eq!(parse!(isoyear: 2005, weekday: Thu), Err(NOT_ENOUGH));
1530
1531 assert_eq!(parse!(ordinal: 123), Err(NOT_ENOUGH));
1533 assert_eq!(parse!(year: 2000, ordinal: 0), Err(OUT_OF_RANGE));
1534 assert_eq!(parse!(year: 2000, ordinal: 1), ymd(2000, 1, 1));
1535 assert_eq!(parse!(year: 2000, ordinal: 60), ymd(2000, 2, 29));
1536 assert_eq!(parse!(year: 2000, ordinal: 61), ymd(2000, 3, 1));
1537 assert_eq!(parse!(year: 2000, ordinal: 366), ymd(2000, 12, 31));
1538 assert_eq!(parse!(year: 2000, ordinal: 367), Err(OUT_OF_RANGE));
1539 assert_eq!(parse!(year: 2000, ordinal: 0xffffffff), Err(OUT_OF_RANGE));
1540 assert_eq!(parse!(year: 2100, ordinal: 0), Err(OUT_OF_RANGE));
1541 assert_eq!(parse!(year: 2100, ordinal: 1), ymd(2100, 1, 1));
1542 assert_eq!(parse!(year: 2100, ordinal: 59), ymd(2100, 2, 28));
1543 assert_eq!(parse!(year: 2100, ordinal: 60), ymd(2100, 3, 1));
1544 assert_eq!(parse!(year: 2100, ordinal: 365), ymd(2100, 12, 31));
1545 assert_eq!(parse!(year: 2100, ordinal: 366), Err(OUT_OF_RANGE));
1546 assert_eq!(parse!(year: 2100, ordinal: 0xffffffff), Err(OUT_OF_RANGE));
1547
1548 assert_eq!(
1550 parse!(year: 2014, month: 12, day: 31, ordinal: 365, isoyear: 2015, isoweek: 1,
1551 week_from_sun: 52, week_from_mon: 52, weekday: Wed),
1552 ymd(2014, 12, 31)
1553 );
1554 assert_eq!(
1555 parse!(year: 2014, month: 12, ordinal: 365, isoyear: 2015, isoweek: 1,
1556 week_from_sun: 52, week_from_mon: 52),
1557 ymd(2014, 12, 31)
1558 );
1559 assert_eq!(
1560 parse!(year: 2014, month: 12, day: 31, ordinal: 365, isoyear: 2014, isoweek: 53,
1561 week_from_sun: 52, week_from_mon: 52, weekday: Wed),
1562 Err(IMPOSSIBLE)
1563 ); assert_eq!(
1565 parse!(year: 2012, isoyear: 2015, isoweek: 1,
1566 week_from_sun: 52, week_from_mon: 52),
1567 Err(NOT_ENOUGH)
1568 ); assert_eq!(parse!(year_div_100: 20, isoyear_mod_100: 15, ordinal: 366), Err(NOT_ENOUGH));
1570 }
1572
1573 #[test]
1574 fn test_parsed_to_naive_time() {
1575 macro_rules! parse {
1576 ($($k:ident: $v:expr),*) => (
1577 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_naive_time()
1578 )
1579 }
1580
1581 let hms = |h, m, s| Ok(NaiveTime::from_hms_opt(h, m, s).unwrap());
1582 let hmsn = |h, m, s, n| Ok(NaiveTime::from_hms_nano_opt(h, m, s, n).unwrap());
1583
1584 assert_eq!(parse!(), Err(NOT_ENOUGH));
1586 assert_eq!(parse!(hour_div_12: 0), Err(NOT_ENOUGH));
1587 assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1), Err(NOT_ENOUGH));
1588 assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23), hms(1, 23, 0));
1589 assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 45), hms(1, 23, 45));
1590 assert_eq!(
1591 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 45,
1592 nanosecond: 678_901_234),
1593 hmsn(1, 23, 45, 678_901_234)
1594 );
1595 assert_eq!(parse!(hour_div_12: 1, hour_mod_12: 11, minute: 45, second: 6), hms(23, 45, 6));
1596 assert_eq!(parse!(hour_mod_12: 1, minute: 23), Err(NOT_ENOUGH));
1597 assert_eq!(
1598 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, nanosecond: 456_789_012),
1599 Err(NOT_ENOUGH)
1600 );
1601
1602 assert_eq!(parse!(hour_div_12: 2, hour_mod_12: 0, minute: 0), Err(OUT_OF_RANGE));
1604 assert_eq!(parse!(hour_div_12: 1, hour_mod_12: 12, minute: 0), Err(OUT_OF_RANGE));
1605 assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 60), Err(OUT_OF_RANGE));
1606 assert_eq!(
1607 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 61),
1608 Err(OUT_OF_RANGE)
1609 );
1610 assert_eq!(
1611 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 34,
1612 nanosecond: 1_000_000_000),
1613 Err(OUT_OF_RANGE)
1614 );
1615
1616 assert_eq!(
1618 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 60),
1619 hmsn(1, 23, 59, 1_000_000_000)
1620 );
1621 assert_eq!(
1622 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 60,
1623 nanosecond: 999_999_999),
1624 hmsn(1, 23, 59, 1_999_999_999)
1625 );
1626 }
1627
1628 #[test]
1629 fn test_parsed_to_naive_datetime_with_offset() {
1630 macro_rules! parse {
1631 (offset = $offset:expr; $($k:ident: $v:expr),*) => (
1632 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_naive_datetime_with_offset($offset)
1633 );
1634 ($($k:ident: $v:expr),*) => (parse!(offset = 0; $($k: $v),*))
1635 }
1636
1637 let ymdhms = |y, m, d, h, n, s| {
1638 Ok(NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_opt(h, n, s).unwrap())
1639 };
1640 let ymdhmsn = |y, m, d, h, n, s, nano| {
1641 Ok(NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_nano_opt(h, n, s, nano).unwrap())
1642 };
1643
1644 assert_eq!(parse!(), Err(NOT_ENOUGH));
1646 assert_eq!(
1647 parse!(year: 2015, month: 1, day: 30,
1648 hour_div_12: 1, hour_mod_12: 2, minute: 38),
1649 ymdhms(2015, 1, 30, 14, 38, 0)
1650 );
1651 assert_eq!(
1652 parse!(year: 1997, month: 1, day: 30,
1653 hour_div_12: 1, hour_mod_12: 2, minute: 38, second: 5),
1654 ymdhms(1997, 1, 30, 14, 38, 5)
1655 );
1656 assert_eq!(
1657 parse!(year: 2012, ordinal: 34, hour_div_12: 0, hour_mod_12: 5,
1658 minute: 6, second: 7, nanosecond: 890_123_456),
1659 ymdhmsn(2012, 2, 3, 5, 6, 7, 890_123_456)
1660 );
1661 assert_eq!(parse!(timestamp: 0), ymdhms(1970, 1, 1, 0, 0, 0));
1662 assert_eq!(parse!(timestamp: 1, nanosecond: 0), ymdhms(1970, 1, 1, 0, 0, 1));
1663 assert_eq!(parse!(timestamp: 1, nanosecond: 1), ymdhmsn(1970, 1, 1, 0, 0, 1, 1));
1664 assert_eq!(parse!(timestamp: 1_420_000_000), ymdhms(2014, 12, 31, 4, 26, 40));
1665 assert_eq!(parse!(timestamp: -0x1_0000_0000), ymdhms(1833, 11, 24, 17, 31, 44));
1666
1667 assert_eq!(
1669 parse!(year: 2014, year_div_100: 20, year_mod_100: 14, month: 12, day: 31,
1670 ordinal: 365, isoyear: 2015, isoyear_div_100: 20, isoyear_mod_100: 15,
1671 isoweek: 1, week_from_sun: 52, week_from_mon: 52, weekday: Wed,
1672 hour_div_12: 0, hour_mod_12: 4, minute: 26, second: 40,
1673 nanosecond: 12_345_678, timestamp: 1_420_000_000),
1674 ymdhmsn(2014, 12, 31, 4, 26, 40, 12_345_678)
1675 );
1676 assert_eq!(
1677 parse!(year: 2014, year_div_100: 20, year_mod_100: 14, month: 12, day: 31,
1678 ordinal: 365, isoyear: 2015, isoyear_div_100: 20, isoyear_mod_100: 15,
1679 isoweek: 1, week_from_sun: 52, week_from_mon: 52, weekday: Wed,
1680 hour_div_12: 0, hour_mod_12: 4, minute: 26, second: 40,
1681 nanosecond: 12_345_678, timestamp: 1_419_999_999),
1682 Err(IMPOSSIBLE)
1683 );
1684 assert_eq!(
1685 parse!(offset = 32400;
1686 year: 2014, year_div_100: 20, year_mod_100: 14, month: 12, day: 31,
1687 ordinal: 365, isoyear: 2015, isoyear_div_100: 20, isoyear_mod_100: 15,
1688 isoweek: 1, week_from_sun: 52, week_from_mon: 52, weekday: Wed,
1689 hour_div_12: 0, hour_mod_12: 4, minute: 26, second: 40,
1690 nanosecond: 12_345_678, timestamp: 1_419_967_600),
1691 ymdhmsn(2014, 12, 31, 4, 26, 40, 12_345_678)
1692 );
1693
1694 let max_days_from_year_1970 =
1696 NaiveDate::MAX.signed_duration_since(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap());
1697 let year_0_from_year_1970 = NaiveDate::from_ymd_opt(0, 1, 1)
1698 .unwrap()
1699 .signed_duration_since(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap());
1700 let min_days_from_year_1970 =
1701 NaiveDate::MIN.signed_duration_since(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap());
1702 assert_eq!(
1703 parse!(timestamp: min_days_from_year_1970.num_seconds()),
1704 ymdhms(NaiveDate::MIN.year(), 1, 1, 0, 0, 0)
1705 );
1706 assert_eq!(
1707 parse!(timestamp: year_0_from_year_1970.num_seconds()),
1708 ymdhms(0, 1, 1, 0, 0, 0)
1709 );
1710 assert_eq!(
1711 parse!(timestamp: max_days_from_year_1970.num_seconds() + 86399),
1712 ymdhms(NaiveDate::MAX.year(), 12, 31, 23, 59, 59)
1713 );
1714
1715 assert_eq!(parse!(second: 59, timestamp: 1_341_100_798), Err(IMPOSSIBLE));
1717 assert_eq!(parse!(second: 59, timestamp: 1_341_100_799), ymdhms(2012, 6, 30, 23, 59, 59));
1718 assert_eq!(parse!(second: 59, timestamp: 1_341_100_800), Err(IMPOSSIBLE));
1719 assert_eq!(
1720 parse!(second: 60, timestamp: 1_341_100_799),
1721 ymdhmsn(2012, 6, 30, 23, 59, 59, 1_000_000_000)
1722 );
1723 assert_eq!(
1724 parse!(second: 60, timestamp: 1_341_100_800),
1725 ymdhmsn(2012, 6, 30, 23, 59, 59, 1_000_000_000)
1726 );
1727 assert_eq!(parse!(second: 0, timestamp: 1_341_100_800), ymdhms(2012, 7, 1, 0, 0, 0));
1728 assert_eq!(parse!(second: 1, timestamp: 1_341_100_800), Err(IMPOSSIBLE));
1729 assert_eq!(parse!(second: 60, timestamp: 1_341_100_801), Err(IMPOSSIBLE));
1730
1731 assert_eq!(
1734 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1735 minute: 59, second: 59, timestamp: 1_341_100_798),
1736 Err(IMPOSSIBLE)
1737 );
1738 assert_eq!(
1739 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1740 minute: 59, second: 59, timestamp: 1_341_100_799),
1741 ymdhms(2012, 6, 30, 23, 59, 59)
1742 );
1743 assert_eq!(
1744 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1745 minute: 59, second: 59, timestamp: 1_341_100_800),
1746 Err(IMPOSSIBLE)
1747 );
1748 assert_eq!(
1749 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1750 minute: 59, second: 60, timestamp: 1_341_100_799),
1751 ymdhmsn(2012, 6, 30, 23, 59, 59, 1_000_000_000)
1752 );
1753 assert_eq!(
1754 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1755 minute: 59, second: 60, timestamp: 1_341_100_800),
1756 ymdhmsn(2012, 6, 30, 23, 59, 59, 1_000_000_000)
1757 );
1758 assert_eq!(
1759 parse!(year: 2012, ordinal: 183, hour_div_12: 0, hour_mod_12: 0,
1760 minute: 0, second: 0, timestamp: 1_341_100_800),
1761 ymdhms(2012, 7, 1, 0, 0, 0)
1762 );
1763 assert_eq!(
1764 parse!(year: 2012, ordinal: 183, hour_div_12: 0, hour_mod_12: 0,
1765 minute: 0, second: 1, timestamp: 1_341_100_800),
1766 Err(IMPOSSIBLE)
1767 );
1768 assert_eq!(
1769 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1770 minute: 59, second: 60, timestamp: 1_341_100_801),
1771 Err(IMPOSSIBLE)
1772 );
1773
1774 assert_eq!(
1776 parse!(year: 2015, month: 1, day: 20, weekday: Tue,
1777 hour_div_12: 2, hour_mod_12: 1, minute: 35, second: 20),
1778 Err(OUT_OF_RANGE)
1779 ); }
1781
1782 #[test]
1783 fn test_parsed_to_datetime() {
1784 macro_rules! parse {
1785 ($($k:ident: $v:expr),*) => (
1786 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_datetime()
1787 )
1788 }
1789
1790 let ymdhmsn = |y, m, d, h, n, s, nano, off| {
1791 Ok(FixedOffset::east_opt(off)
1792 .unwrap()
1793 .from_local_datetime(
1794 &NaiveDate::from_ymd_opt(y, m, d)
1795 .unwrap()
1796 .and_hms_nano_opt(h, n, s, nano)
1797 .unwrap(),
1798 )
1799 .unwrap())
1800 };
1801
1802 assert_eq!(parse!(offset: 0), Err(NOT_ENOUGH));
1803 assert_eq!(
1804 parse!(year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1805 minute: 26, second: 40, nanosecond: 12_345_678),
1806 Err(NOT_ENOUGH)
1807 );
1808 assert_eq!(
1809 parse!(year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1810 minute: 26, second: 40, nanosecond: 12_345_678, offset: 0),
1811 ymdhmsn(2014, 12, 31, 4, 26, 40, 12_345_678, 0)
1812 );
1813 assert_eq!(
1814 parse!(year: 2014, ordinal: 365, hour_div_12: 1, hour_mod_12: 1,
1815 minute: 26, second: 40, nanosecond: 12_345_678, offset: 32400),
1816 ymdhmsn(2014, 12, 31, 13, 26, 40, 12_345_678, 32400)
1817 );
1818 assert_eq!(
1819 parse!(year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 1,
1820 minute: 42, second: 4, nanosecond: 12_345_678, offset: -9876),
1821 ymdhmsn(2014, 12, 31, 1, 42, 4, 12_345_678, -9876)
1822 );
1823 assert_eq!(
1824 parse!(year: 2015, ordinal: 1, hour_div_12: 0, hour_mod_12: 4,
1825 minute: 26, second: 40, nanosecond: 12_345_678, offset: 86_400),
1826 Err(OUT_OF_RANGE)
1827 ); }
1829
1830 #[test]
1831 fn test_parsed_to_datetime_with_timezone() {
1832 macro_rules! parse {
1833 ($tz:expr; $($k:ident: $v:expr),*) => (
1834 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_datetime_with_timezone(&$tz)
1835 )
1836 }
1837
1838 assert_eq!(
1840 parse!(Utc;
1841 year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1842 minute: 26, second: 40, nanosecond: 12_345_678, offset: 0),
1843 Ok(Utc
1844 .from_local_datetime(
1845 &NaiveDate::from_ymd_opt(2014, 12, 31)
1846 .unwrap()
1847 .and_hms_nano_opt(4, 26, 40, 12_345_678)
1848 .unwrap()
1849 )
1850 .unwrap())
1851 );
1852 assert_eq!(
1853 parse!(Utc;
1854 year: 2014, ordinal: 365, hour_div_12: 1, hour_mod_12: 1,
1855 minute: 26, second: 40, nanosecond: 12_345_678, offset: 32400),
1856 Err(IMPOSSIBLE)
1857 );
1858 assert_eq!(
1859 parse!(FixedOffset::east_opt(32400).unwrap();
1860 year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1861 minute: 26, second: 40, nanosecond: 12_345_678, offset: 0),
1862 Err(IMPOSSIBLE)
1863 );
1864 assert_eq!(
1865 parse!(FixedOffset::east_opt(32400).unwrap();
1866 year: 2014, ordinal: 365, hour_div_12: 1, hour_mod_12: 1,
1867 minute: 26, second: 40, nanosecond: 12_345_678, offset: 32400),
1868 Ok(FixedOffset::east_opt(32400)
1869 .unwrap()
1870 .from_local_datetime(
1871 &NaiveDate::from_ymd_opt(2014, 12, 31)
1872 .unwrap()
1873 .and_hms_nano_opt(13, 26, 40, 12_345_678)
1874 .unwrap()
1875 )
1876 .unwrap())
1877 );
1878
1879 assert_eq!(
1881 parse!(Utc; timestamp: 1_420_000_000, offset: 0),
1882 Ok(Utc.with_ymd_and_hms(2014, 12, 31, 4, 26, 40).unwrap())
1883 );
1884 assert_eq!(parse!(Utc; timestamp: 1_420_000_000, offset: 32400), Err(IMPOSSIBLE));
1885 assert_eq!(
1886 parse!(FixedOffset::east_opt(32400).unwrap(); timestamp: 1_420_000_000, offset: 0),
1887 Err(IMPOSSIBLE)
1888 );
1889 assert_eq!(
1890 parse!(FixedOffset::east_opt(32400).unwrap(); timestamp: 1_420_000_000, offset: 32400),
1891 Ok(FixedOffset::east_opt(32400)
1892 .unwrap()
1893 .with_ymd_and_hms(2014, 12, 31, 13, 26, 40)
1894 .unwrap())
1895 );
1896
1897 }
1899
1900 #[test]
1901 fn issue_551() {
1902 use crate::Weekday;
1903 let mut parsed = Parsed::new();
1904
1905 parsed.year = Some(2002);
1906 parsed.week_from_mon = Some(22);
1907 parsed.weekday = Some(Weekday::Mon);
1908 assert_eq!(NaiveDate::from_ymd_opt(2002, 6, 3).unwrap(), parsed.to_naive_date().unwrap());
1909
1910 parsed.year = Some(2001);
1911 assert_eq!(NaiveDate::from_ymd_opt(2001, 5, 28).unwrap(), parsed.to_naive_date().unwrap());
1912 }
1913}