1use super::{ParseResult, IMPOSSIBLE, NOT_ENOUGH, OUT_OF_RANGE};
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)]
129pub struct Parsed {
130 #[doc(hidden)]
131 pub year: Option<i32>,
132 #[doc(hidden)]
133 pub year_div_100: Option<i32>,
134 #[doc(hidden)]
135 pub year_mod_100: Option<i32>,
136 #[doc(hidden)]
137 pub isoyear: Option<i32>,
138 #[doc(hidden)]
139 pub isoyear_div_100: Option<i32>,
140 #[doc(hidden)]
141 pub isoyear_mod_100: Option<i32>,
142 #[doc(hidden)]
143 pub month: Option<u32>,
144 #[doc(hidden)]
145 pub week_from_sun: Option<u32>,
146 #[doc(hidden)]
147 pub week_from_mon: Option<u32>,
148 #[doc(hidden)]
149 pub isoweek: Option<u32>,
150 #[doc(hidden)]
151 pub weekday: Option<Weekday>,
152 #[doc(hidden)]
153 pub ordinal: Option<u32>,
154 #[doc(hidden)]
155 pub day: Option<u32>,
156 #[doc(hidden)]
157 pub hour_div_12: Option<u32>,
158 #[doc(hidden)]
159 pub hour_mod_12: Option<u32>,
160 #[doc(hidden)]
161 pub minute: Option<u32>,
162 #[doc(hidden)]
163 pub second: Option<u32>,
164 #[doc(hidden)]
165 pub nanosecond: Option<u32>,
166 #[doc(hidden)]
167 pub timestamp: Option<i64>,
168 #[doc(hidden)]
169 pub offset: Option<i32>,
170 #[doc(hidden)]
171 _dummy: (),
172}
173
174#[inline]
177fn set_if_consistent<T: PartialEq>(old: &mut Option<T>, new: T) -> ParseResult<()> {
178 if let Some(ref old) = *old {
179 if *old == new {
180 Ok(())
181 } else {
182 Err(IMPOSSIBLE)
183 }
184 } else {
185 *old = Some(new);
186 Ok(())
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]
318 pub fn set_month(&mut self, value: i64) -> ParseResult<()> {
319 if !(1..=12).contains(&value) {
320 return Err(OUT_OF_RANGE);
321 }
322 set_if_consistent(&mut self.month, value as u32)
323 }
324
325 #[inline]
335 pub fn set_week_from_sun(&mut self, value: i64) -> ParseResult<()> {
336 if !(0..=53).contains(&value) {
337 return Err(OUT_OF_RANGE);
338 }
339 set_if_consistent(&mut self.week_from_sun, value as u32)
340 }
341
342 #[inline]
353 pub fn set_week_from_mon(&mut self, value: i64) -> ParseResult<()> {
354 if !(0..=53).contains(&value) {
355 return Err(OUT_OF_RANGE);
356 }
357 set_if_consistent(&mut self.week_from_mon, value as u32)
358 }
359
360 #[inline]
370 pub fn set_isoweek(&mut self, value: i64) -> ParseResult<()> {
371 if !(1..=53).contains(&value) {
372 return Err(OUT_OF_RANGE);
373 }
374 set_if_consistent(&mut self.isoweek, value as u32)
375 }
376
377 #[inline]
383 pub fn set_weekday(&mut self, value: Weekday) -> ParseResult<()> {
384 set_if_consistent(&mut self.weekday, value)
385 }
386
387 #[inline]
395 pub fn set_ordinal(&mut self, value: i64) -> ParseResult<()> {
396 if !(1..=366).contains(&value) {
397 return Err(OUT_OF_RANGE);
398 }
399 set_if_consistent(&mut self.ordinal, value as u32)
400 }
401
402 #[inline]
410 pub fn set_day(&mut self, value: i64) -> ParseResult<()> {
411 if !(1..=31).contains(&value) {
412 return Err(OUT_OF_RANGE);
413 }
414 set_if_consistent(&mut self.day, value as u32)
415 }
416
417 #[inline]
425 pub fn set_ampm(&mut self, value: bool) -> ParseResult<()> {
426 set_if_consistent(&mut self.hour_div_12, value as u32)
427 }
428
429 #[inline]
441 pub fn set_hour12(&mut self, mut value: i64) -> ParseResult<()> {
442 if !(1..=12).contains(&value) {
443 return Err(OUT_OF_RANGE);
444 }
445 if value == 12 {
446 value = 0
447 }
448 set_if_consistent(&mut self.hour_mod_12, value as u32)
449 }
450
451 #[inline]
461 pub fn set_hour(&mut self, value: i64) -> ParseResult<()> {
462 let (hour_div_12, hour_mod_12) = match value {
463 hour @ 0..=11 => (0, hour as u32),
464 hour @ 12..=23 => (1, hour as u32 - 12),
465 _ => return Err(OUT_OF_RANGE),
466 };
467 set_if_consistent(&mut self.hour_div_12, hour_div_12)?;
468 set_if_consistent(&mut self.hour_mod_12, hour_mod_12)
469 }
470
471 #[inline]
479 pub fn set_minute(&mut self, value: i64) -> ParseResult<()> {
480 if !(0..=59).contains(&value) {
481 return Err(OUT_OF_RANGE);
482 }
483 set_if_consistent(&mut self.minute, value as u32)
484 }
485
486 #[inline]
496 pub fn set_second(&mut self, value: i64) -> ParseResult<()> {
497 if !(0..=60).contains(&value) {
498 return Err(OUT_OF_RANGE);
499 }
500 set_if_consistent(&mut self.second, value as u32)
501 }
502
503 #[inline]
513 pub fn set_nanosecond(&mut self, value: i64) -> ParseResult<()> {
514 if !(0..=999_999_999).contains(&value) {
515 return Err(OUT_OF_RANGE);
516 }
517 set_if_consistent(&mut self.nanosecond, value as u32)
518 }
519
520 #[inline]
529 pub fn set_timestamp(&mut self, value: i64) -> ParseResult<()> {
530 set_if_consistent(&mut self.timestamp, value)
531 }
532
533 #[inline]
543 pub fn set_offset(&mut self, value: i64) -> ParseResult<()> {
544 set_if_consistent(&mut self.offset, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
545 }
546
547 pub fn to_naive_date(&self) -> ParseResult<NaiveDate> {
571 fn resolve_year(
572 y: Option<i32>,
573 q: Option<i32>,
574 r: Option<i32>,
575 ) -> ParseResult<Option<i32>> {
576 match (y, q, r) {
577 (y, None, None) => Ok(y),
580
581 (Some(y), q, r @ Some(0..=99)) | (Some(y), q, r @ None) => {
586 if y < 0 {
587 return Err(IMPOSSIBLE);
588 }
589 let q_ = y / 100;
590 let r_ = y % 100;
591 if q.unwrap_or(q_) == q_ && r.unwrap_or(r_) == r_ {
592 Ok(Some(y))
593 } else {
594 Err(IMPOSSIBLE)
595 }
596 }
597
598 (None, Some(q), Some(r @ 0..=99)) => {
601 if q < 0 {
602 return Err(IMPOSSIBLE);
603 }
604 let y = q.checked_mul(100).and_then(|v| v.checked_add(r));
605 Ok(Some(y.ok_or(OUT_OF_RANGE)?))
606 }
607
608 (None, None, Some(r @ 0..=99)) => Ok(Some(r + if r < 70 { 2000 } else { 1900 })),
611
612 (None, Some(_), None) => Err(NOT_ENOUGH),
614 (_, _, Some(_)) => Err(OUT_OF_RANGE),
615 }
616 }
617
618 let given_year = resolve_year(self.year, self.year_div_100, self.year_mod_100)?;
619 let given_isoyear = resolve_year(self.isoyear, self.isoyear_div_100, self.isoyear_mod_100)?;
620
621 let verify_ymd = |date: NaiveDate| {
623 let year = date.year();
624 let (year_div_100, year_mod_100) = if year >= 0 {
625 (Some(year / 100), Some(year % 100))
626 } else {
627 (None, None) };
629 let month = date.month();
630 let day = date.day();
631 self.year.unwrap_or(year) == year
632 && self.year_div_100.or(year_div_100) == year_div_100
633 && self.year_mod_100.or(year_mod_100) == year_mod_100
634 && self.month.unwrap_or(month) == month
635 && self.day.unwrap_or(day) == day
636 };
637
638 let verify_isoweekdate = |date: NaiveDate| {
640 let week = date.iso_week();
641 let isoyear = week.year();
642 let isoweek = week.week();
643 let weekday = date.weekday();
644 let (isoyear_div_100, isoyear_mod_100) = if isoyear >= 0 {
645 (Some(isoyear / 100), Some(isoyear % 100))
646 } else {
647 (None, None) };
649 self.isoyear.unwrap_or(isoyear) == isoyear
650 && self.isoyear_div_100.or(isoyear_div_100) == isoyear_div_100
651 && self.isoyear_mod_100.or(isoyear_mod_100) == isoyear_mod_100
652 && self.isoweek.unwrap_or(isoweek) == isoweek
653 && self.weekday.unwrap_or(weekday) == weekday
654 };
655
656 let verify_ordinal = |date: NaiveDate| {
658 let ordinal = date.ordinal();
659 let week_from_sun = date.weeks_from(Weekday::Sun);
660 let week_from_mon = date.weeks_from(Weekday::Mon);
661 self.ordinal.unwrap_or(ordinal) == ordinal
662 && self.week_from_sun.map_or(week_from_sun, |v| v as i32) == week_from_sun
663 && self.week_from_mon.map_or(week_from_mon, |v| v as i32) == week_from_mon
664 };
665
666 let (verified, parsed_date) = match (given_year, given_isoyear, self) {
670 (Some(year), _, &Parsed { month: Some(month), day: Some(day), .. }) => {
671 let date = NaiveDate::from_ymd_opt(year, month, day).ok_or(OUT_OF_RANGE)?;
673 (verify_isoweekdate(date) && verify_ordinal(date), date)
674 }
675
676 (Some(year), _, &Parsed { ordinal: Some(ordinal), .. }) => {
677 let date = NaiveDate::from_yo_opt(year, ordinal).ok_or(OUT_OF_RANGE)?;
679 (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
680 }
681
682 (Some(year), _, &Parsed { week_from_sun: Some(week), weekday: Some(weekday), .. }) => {
683 let date = resolve_week_date(year, week, weekday, Weekday::Sun)?;
685 (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
686 }
687
688 (Some(year), _, &Parsed { week_from_mon: Some(week), weekday: Some(weekday), .. }) => {
689 let date = resolve_week_date(year, week, weekday, Weekday::Mon)?;
691 (verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
692 }
693
694 (_, Some(isoyear), &Parsed { isoweek: Some(isoweek), weekday: Some(weekday), .. }) => {
695 let date = NaiveDate::from_isoywd_opt(isoyear, isoweek, weekday);
697 let date = date.ok_or(OUT_OF_RANGE)?;
698 (verify_ymd(date) && verify_ordinal(date), date)
699 }
700
701 (_, _, _) => return Err(NOT_ENOUGH),
702 };
703
704 if verified {
705 Ok(parsed_date)
706 } else {
707 Err(IMPOSSIBLE)
708 }
709 }
710
711 pub fn to_naive_time(&self) -> ParseResult<NaiveTime> {
729 let hour_div_12 = match self.hour_div_12 {
730 Some(v @ 0..=1) => v,
731 Some(_) => return Err(OUT_OF_RANGE),
732 None => return Err(NOT_ENOUGH),
733 };
734 let hour_mod_12 = match self.hour_mod_12 {
735 Some(v @ 0..=11) => v,
736 Some(_) => return Err(OUT_OF_RANGE),
737 None => return Err(NOT_ENOUGH),
738 };
739 let hour = hour_div_12 * 12 + hour_mod_12;
740
741 let minute = match self.minute {
742 Some(v @ 0..=59) => v,
743 Some(_) => return Err(OUT_OF_RANGE),
744 None => return Err(NOT_ENOUGH),
745 };
746
747 let (second, mut nano) = match self.second.unwrap_or(0) {
749 v @ 0..=59 => (v, 0),
750 60 => (59, 1_000_000_000),
751 _ => return Err(OUT_OF_RANGE),
752 };
753 nano += match self.nanosecond {
754 Some(v @ 0..=999_999_999) if self.second.is_some() => v,
755 Some(0..=999_999_999) => return Err(NOT_ENOUGH), Some(_) => return Err(OUT_OF_RANGE),
757 None => 0,
758 };
759
760 NaiveTime::from_hms_nano_opt(hour, minute, second, nano).ok_or(OUT_OF_RANGE)
761 }
762
763 pub fn to_naive_datetime_with_offset(&self, offset: i32) -> ParseResult<NaiveDateTime> {
783 let date = self.to_naive_date();
784 let time = self.to_naive_time();
785 if let (Ok(date), Ok(time)) = (date, time) {
786 let datetime = date.and_time(time);
787
788 let timestamp = datetime.and_utc().timestamp() - i64::from(offset);
791 if let Some(given_timestamp) = self.timestamp {
792 if given_timestamp != timestamp
794 && !(datetime.nanosecond() >= 1_000_000_000 && given_timestamp == timestamp + 1)
795 {
796 return Err(IMPOSSIBLE);
797 }
798 }
799
800 Ok(datetime)
801 } else if let Some(timestamp) = self.timestamp {
802 use super::ParseError as PE;
803 use super::ParseErrorKind::{Impossible, OutOfRange};
804
805 match (date, time) {
808 (Err(PE(OutOfRange)), _) | (_, Err(PE(OutOfRange))) => return Err(OUT_OF_RANGE),
809 (Err(PE(Impossible)), _) | (_, Err(PE(Impossible))) => return Err(IMPOSSIBLE),
810 (_, _) => {} }
812
813 let ts = timestamp.checked_add(i64::from(offset)).ok_or(OUT_OF_RANGE)?;
815 let mut datetime = DateTime::from_timestamp(ts, 0).ok_or(OUT_OF_RANGE)?.naive_utc();
816
817 let mut parsed = self.clone();
820 if parsed.second == Some(60) {
821 match datetime.second() {
823 59 => {}
825 0 => {
827 datetime -= TimeDelta::try_seconds(1).unwrap();
828 }
829 _ => return Err(IMPOSSIBLE),
831 }
832 } else {
834 parsed.set_second(i64::from(datetime.second()))?;
835 }
836 parsed.set_year(i64::from(datetime.year()))?;
837 parsed.set_ordinal(i64::from(datetime.ordinal()))?; parsed.set_hour(i64::from(datetime.hour()))?;
839 parsed.set_minute(i64::from(datetime.minute()))?;
840
841 let date = parsed.to_naive_date()?;
843 let time = parsed.to_naive_time()?;
844 Ok(date.and_time(time))
845 } else {
846 date?;
848 time?;
849 unreachable!()
850 }
851 }
852
853 pub fn to_fixed_offset(&self) -> ParseResult<FixedOffset> {
861 FixedOffset::east_opt(self.offset.ok_or(NOT_ENOUGH)?).ok_or(OUT_OF_RANGE)
862 }
863
864 pub fn to_datetime(&self) -> ParseResult<DateTime<FixedOffset>> {
883 let offset = match (self.offset, self.timestamp) {
885 (Some(off), _) => off,
886 (None, Some(_)) => 0, (None, None) => return Err(NOT_ENOUGH),
888 };
889 let datetime = self.to_naive_datetime_with_offset(offset)?;
890 let offset = FixedOffset::east_opt(offset).ok_or(OUT_OF_RANGE)?;
891
892 match offset.from_local_datetime(&datetime) {
893 MappedLocalTime::None => Err(IMPOSSIBLE),
894 MappedLocalTime::Single(t) => Ok(t),
895 MappedLocalTime::Ambiguous(..) => Err(NOT_ENOUGH),
896 }
897 }
898
899 pub fn to_datetime_with_timezone<Tz: TimeZone>(&self, tz: &Tz) -> ParseResult<DateTime<Tz>> {
925 let mut guessed_offset = 0;
927 if let Some(timestamp) = self.timestamp {
928 let nanosecond = self.nanosecond.unwrap_or(0);
931 let dt =
932 DateTime::from_timestamp(timestamp, nanosecond).ok_or(OUT_OF_RANGE)?.naive_utc();
933 guessed_offset = tz.offset_from_utc_datetime(&dt).fix().local_minus_utc();
934 }
935
936 let check_offset = |dt: &DateTime<Tz>| {
938 if let Some(offset) = self.offset {
939 dt.offset().fix().local_minus_utc() == offset
940 } else {
941 true
942 }
943 };
944
945 let datetime = self.to_naive_datetime_with_offset(guessed_offset)?;
948 match tz.from_local_datetime(&datetime) {
949 MappedLocalTime::None => Err(IMPOSSIBLE),
950 MappedLocalTime::Single(t) => {
951 if check_offset(&t) {
952 Ok(t)
953 } else {
954 Err(IMPOSSIBLE)
955 }
956 }
957 MappedLocalTime::Ambiguous(min, max) => {
958 match (check_offset(&min), check_offset(&max)) {
960 (false, false) => Err(IMPOSSIBLE),
961 (false, true) => Ok(max),
962 (true, false) => Ok(min),
963 (true, true) => Err(NOT_ENOUGH),
964 }
965 }
966 }
967 }
968
969 #[inline]
973 pub fn year(&self) -> Option<i32> {
974 self.year
975 }
976
977 #[inline]
981 pub fn year_div_100(&self) -> Option<i32> {
982 self.year_div_100
983 }
984
985 #[inline]
989 pub fn year_mod_100(&self) -> Option<i32> {
990 self.year_mod_100
991 }
992
993 #[inline]
999 pub fn isoyear(&self) -> Option<i32> {
1000 self.isoyear
1001 }
1002
1003 #[inline]
1009 pub fn isoyear_div_100(&self) -> Option<i32> {
1010 self.isoyear_div_100
1011 }
1012
1013 #[inline]
1019 pub fn isoyear_mod_100(&self) -> Option<i32> {
1020 self.isoyear_mod_100
1021 }
1022
1023 #[inline]
1027 pub fn month(&self) -> Option<u32> {
1028 self.month
1029 }
1030
1031 #[inline]
1035 pub fn week_from_sun(&self) -> Option<u32> {
1036 self.week_from_sun
1037 }
1038
1039 #[inline]
1043 pub fn week_from_mon(&self) -> Option<u32> {
1044 self.week_from_mon
1045 }
1046
1047 #[inline]
1053 pub fn isoweek(&self) -> Option<u32> {
1054 self.isoweek
1055 }
1056
1057 #[inline]
1061 pub fn weekday(&self) -> Option<Weekday> {
1062 self.weekday
1063 }
1064
1065 #[inline]
1069 pub fn ordinal(&self) -> Option<u32> {
1070 self.ordinal
1071 }
1072
1073 #[inline]
1077 pub fn day(&self) -> Option<u32> {
1078 self.day
1079 }
1080
1081 #[inline]
1087 pub fn hour_div_12(&self) -> Option<u32> {
1088 self.hour_div_12
1089 }
1090
1091 pub fn hour_mod_12(&self) -> Option<u32> {
1095 self.hour_mod_12
1096 }
1097
1098 #[inline]
1102 pub fn minute(&self) -> Option<u32> {
1103 self.minute
1104 }
1105
1106 #[inline]
1110 pub fn second(&self) -> Option<u32> {
1111 self.second
1112 }
1113
1114 #[inline]
1118 pub fn nanosecond(&self) -> Option<u32> {
1119 self.nanosecond
1120 }
1121
1122 #[inline]
1126 pub fn timestamp(&self) -> Option<i64> {
1127 self.timestamp
1128 }
1129
1130 #[inline]
1134 pub fn offset(&self) -> Option<i32> {
1135 self.offset
1136 }
1137}
1138
1139fn resolve_week_date(
1144 year: i32,
1145 week: u32,
1146 weekday: Weekday,
1147 week_start_day: Weekday,
1148) -> ParseResult<NaiveDate> {
1149 if week > 53 {
1150 return Err(OUT_OF_RANGE);
1151 }
1152
1153 let first_day_of_year = NaiveDate::from_yo_opt(year, 1).ok_or(OUT_OF_RANGE)?;
1154 let first_week_start = 1 + week_start_day.days_since(first_day_of_year.weekday()) as i32;
1156 let weekday = weekday.days_since(week_start_day) as i32;
1158 let ordinal = first_week_start + (week as i32 - 1) * 7 + weekday;
1159 if ordinal <= 0 {
1160 return Err(IMPOSSIBLE);
1161 }
1162 first_day_of_year.with_ordinal(ordinal as u32).ok_or(IMPOSSIBLE)
1163}
1164
1165#[cfg(test)]
1166mod tests {
1167 use super::super::{IMPOSSIBLE, NOT_ENOUGH, OUT_OF_RANGE};
1168 use super::Parsed;
1169 use crate::naive::{NaiveDate, NaiveTime};
1170 use crate::offset::{FixedOffset, TimeZone, Utc};
1171 use crate::Datelike;
1172 use crate::Weekday::*;
1173
1174 #[test]
1175 fn test_parsed_set_fields() {
1176 let mut p = Parsed::new();
1178 assert_eq!(p.set_year(1987), Ok(()));
1179 assert_eq!(p.set_year(1986), Err(IMPOSSIBLE));
1180 assert_eq!(p.set_year(1988), Err(IMPOSSIBLE));
1181 assert_eq!(p.set_year(1987), Ok(()));
1182 assert_eq!(p.set_year_div_100(20), Ok(())); assert_eq!(p.set_year_div_100(21), Err(IMPOSSIBLE));
1184 assert_eq!(p.set_year_div_100(19), Err(IMPOSSIBLE));
1185 assert_eq!(p.set_year_mod_100(37), Ok(())); assert_eq!(p.set_year_mod_100(38), Err(IMPOSSIBLE));
1187 assert_eq!(p.set_year_mod_100(36), Err(IMPOSSIBLE));
1188
1189 let mut p = Parsed::new();
1190 assert_eq!(p.set_year(0), Ok(()));
1191 assert_eq!(p.set_year_div_100(0), Ok(()));
1192 assert_eq!(p.set_year_mod_100(0), Ok(()));
1193
1194 let mut p = Parsed::new();
1195 assert_eq!(p.set_year_div_100(-1), Err(OUT_OF_RANGE));
1196 assert_eq!(p.set_year_mod_100(-1), Err(OUT_OF_RANGE));
1197 assert_eq!(p.set_year(-1), Ok(()));
1198 assert_eq!(p.set_year(-2), Err(IMPOSSIBLE));
1199 assert_eq!(p.set_year(0), Err(IMPOSSIBLE));
1200
1201 let mut p = Parsed::new();
1202 assert_eq!(p.set_year_div_100(0x1_0000_0008), Err(OUT_OF_RANGE));
1203 assert_eq!(p.set_year_div_100(8), Ok(()));
1204 assert_eq!(p.set_year_div_100(0x1_0000_0008), Err(OUT_OF_RANGE));
1205
1206 let mut p = Parsed::new();
1208 assert_eq!(p.set_month(7), Ok(()));
1209 assert_eq!(p.set_month(1), Err(IMPOSSIBLE));
1210 assert_eq!(p.set_month(6), Err(IMPOSSIBLE));
1211 assert_eq!(p.set_month(8), Err(IMPOSSIBLE));
1212 assert_eq!(p.set_month(12), Err(IMPOSSIBLE));
1213
1214 let mut p = Parsed::new();
1215 assert_eq!(p.set_month(8), Ok(()));
1216 assert_eq!(p.set_month(0x1_0000_0008), Err(OUT_OF_RANGE));
1217
1218 let mut p = Parsed::new();
1220 assert_eq!(p.set_hour(12), Ok(()));
1221 assert_eq!(p.set_hour(11), Err(IMPOSSIBLE));
1222 assert_eq!(p.set_hour(13), Err(IMPOSSIBLE));
1223 assert_eq!(p.set_hour(12), Ok(()));
1224 assert_eq!(p.set_ampm(false), Err(IMPOSSIBLE));
1225 assert_eq!(p.set_ampm(true), Ok(()));
1226 assert_eq!(p.set_hour12(12), Ok(()));
1227 assert_eq!(p.set_hour12(0), Err(OUT_OF_RANGE)); assert_eq!(p.set_hour12(1), Err(IMPOSSIBLE));
1229 assert_eq!(p.set_hour12(11), Err(IMPOSSIBLE));
1230
1231 let mut p = Parsed::new();
1232 assert_eq!(p.set_ampm(true), Ok(()));
1233 assert_eq!(p.set_hour12(7), Ok(()));
1234 assert_eq!(p.set_hour(7), Err(IMPOSSIBLE));
1235 assert_eq!(p.set_hour(18), Err(IMPOSSIBLE));
1236 assert_eq!(p.set_hour(19), Ok(()));
1237
1238 let mut p = Parsed::new();
1240 assert_eq!(p.set_timestamp(1_234_567_890), Ok(()));
1241 assert_eq!(p.set_timestamp(1_234_567_889), Err(IMPOSSIBLE));
1242 assert_eq!(p.set_timestamp(1_234_567_891), Err(IMPOSSIBLE));
1243 }
1244
1245 #[test]
1246 fn test_parsed_set_range() {
1247 assert_eq!(Parsed::new().set_year(i32::MIN as i64 - 1), Err(OUT_OF_RANGE));
1248 assert!(Parsed::new().set_year(i32::MIN as i64).is_ok());
1249 assert!(Parsed::new().set_year(i32::MAX as i64).is_ok());
1250 assert_eq!(Parsed::new().set_year(i32::MAX as i64 + 1), Err(OUT_OF_RANGE));
1251
1252 assert_eq!(Parsed::new().set_year_div_100(-1), Err(OUT_OF_RANGE));
1253 assert!(Parsed::new().set_year_div_100(0).is_ok());
1254 assert!(Parsed::new().set_year_div_100(i32::MAX as i64).is_ok());
1255 assert_eq!(Parsed::new().set_year_div_100(i32::MAX as i64 + 1), Err(OUT_OF_RANGE));
1256
1257 assert_eq!(Parsed::new().set_year_mod_100(-1), Err(OUT_OF_RANGE));
1258 assert!(Parsed::new().set_year_mod_100(0).is_ok());
1259 assert!(Parsed::new().set_year_mod_100(99).is_ok());
1260 assert_eq!(Parsed::new().set_year_mod_100(100), Err(OUT_OF_RANGE));
1261
1262 assert_eq!(Parsed::new().set_isoyear(i32::MIN as i64 - 1), Err(OUT_OF_RANGE));
1263 assert!(Parsed::new().set_isoyear(i32::MIN as i64).is_ok());
1264 assert!(Parsed::new().set_isoyear(i32::MAX as i64).is_ok());
1265 assert_eq!(Parsed::new().set_isoyear(i32::MAX as i64 + 1), Err(OUT_OF_RANGE));
1266
1267 assert_eq!(Parsed::new().set_isoyear_div_100(-1), Err(OUT_OF_RANGE));
1268 assert!(Parsed::new().set_isoyear_div_100(0).is_ok());
1269 assert!(Parsed::new().set_isoyear_div_100(99).is_ok());
1270 assert_eq!(Parsed::new().set_isoyear_div_100(i32::MAX as i64 + 1), Err(OUT_OF_RANGE));
1271
1272 assert_eq!(Parsed::new().set_isoyear_mod_100(-1), Err(OUT_OF_RANGE));
1273 assert!(Parsed::new().set_isoyear_mod_100(0).is_ok());
1274 assert!(Parsed::new().set_isoyear_mod_100(99).is_ok());
1275 assert_eq!(Parsed::new().set_isoyear_mod_100(100), Err(OUT_OF_RANGE));
1276
1277 assert_eq!(Parsed::new().set_month(0), Err(OUT_OF_RANGE));
1278 assert!(Parsed::new().set_month(1).is_ok());
1279 assert!(Parsed::new().set_month(12).is_ok());
1280 assert_eq!(Parsed::new().set_month(13), Err(OUT_OF_RANGE));
1281
1282 assert_eq!(Parsed::new().set_week_from_sun(-1), Err(OUT_OF_RANGE));
1283 assert!(Parsed::new().set_week_from_sun(0).is_ok());
1284 assert!(Parsed::new().set_week_from_sun(53).is_ok());
1285 assert_eq!(Parsed::new().set_week_from_sun(54), Err(OUT_OF_RANGE));
1286
1287 assert_eq!(Parsed::new().set_week_from_mon(-1), Err(OUT_OF_RANGE));
1288 assert!(Parsed::new().set_week_from_mon(0).is_ok());
1289 assert!(Parsed::new().set_week_from_mon(53).is_ok());
1290 assert_eq!(Parsed::new().set_week_from_mon(54), Err(OUT_OF_RANGE));
1291
1292 assert_eq!(Parsed::new().set_isoweek(0), Err(OUT_OF_RANGE));
1293 assert!(Parsed::new().set_isoweek(1).is_ok());
1294 assert!(Parsed::new().set_isoweek(53).is_ok());
1295 assert_eq!(Parsed::new().set_isoweek(54), Err(OUT_OF_RANGE));
1296
1297 assert_eq!(Parsed::new().set_ordinal(0), Err(OUT_OF_RANGE));
1298 assert!(Parsed::new().set_ordinal(1).is_ok());
1299 assert!(Parsed::new().set_ordinal(366).is_ok());
1300 assert_eq!(Parsed::new().set_ordinal(367), Err(OUT_OF_RANGE));
1301
1302 assert_eq!(Parsed::new().set_day(0), Err(OUT_OF_RANGE));
1303 assert!(Parsed::new().set_day(1).is_ok());
1304 assert!(Parsed::new().set_day(31).is_ok());
1305 assert_eq!(Parsed::new().set_day(32), Err(OUT_OF_RANGE));
1306
1307 assert_eq!(Parsed::new().set_hour12(0), Err(OUT_OF_RANGE));
1308 assert!(Parsed::new().set_hour12(1).is_ok());
1309 assert!(Parsed::new().set_hour12(12).is_ok());
1310 assert_eq!(Parsed::new().set_hour12(13), Err(OUT_OF_RANGE));
1311
1312 assert_eq!(Parsed::new().set_hour(-1), Err(OUT_OF_RANGE));
1313 assert!(Parsed::new().set_hour(0).is_ok());
1314 assert!(Parsed::new().set_hour(23).is_ok());
1315 assert_eq!(Parsed::new().set_hour(24), Err(OUT_OF_RANGE));
1316
1317 assert_eq!(Parsed::new().set_minute(-1), Err(OUT_OF_RANGE));
1318 assert!(Parsed::new().set_minute(0).is_ok());
1319 assert!(Parsed::new().set_minute(59).is_ok());
1320 assert_eq!(Parsed::new().set_minute(60), Err(OUT_OF_RANGE));
1321
1322 assert_eq!(Parsed::new().set_second(-1), Err(OUT_OF_RANGE));
1323 assert!(Parsed::new().set_second(0).is_ok());
1324 assert!(Parsed::new().set_second(60).is_ok());
1325 assert_eq!(Parsed::new().set_second(61), Err(OUT_OF_RANGE));
1326
1327 assert_eq!(Parsed::new().set_nanosecond(-1), Err(OUT_OF_RANGE));
1328 assert!(Parsed::new().set_nanosecond(0).is_ok());
1329 assert!(Parsed::new().set_nanosecond(999_999_999).is_ok());
1330 assert_eq!(Parsed::new().set_nanosecond(1_000_000_000), Err(OUT_OF_RANGE));
1331
1332 assert!(Parsed::new().set_timestamp(i64::MIN).is_ok());
1333 assert!(Parsed::new().set_timestamp(i64::MAX).is_ok());
1334
1335 assert_eq!(Parsed::new().set_offset(i32::MIN as i64 - 1), Err(OUT_OF_RANGE));
1336 assert!(Parsed::new().set_offset(i32::MIN as i64).is_ok());
1337 assert!(Parsed::new().set_offset(i32::MAX as i64).is_ok());
1338 assert_eq!(Parsed::new().set_offset(i32::MAX as i64 + 1), Err(OUT_OF_RANGE));
1339 }
1340
1341 #[test]
1342 fn test_parsed_to_naive_date() {
1343 macro_rules! parse {
1344 ($($k:ident: $v:expr),*) => (
1345 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_naive_date()
1346 )
1347 }
1348
1349 let ymd = |y, m, d| Ok(NaiveDate::from_ymd_opt(y, m, d).unwrap());
1350
1351 assert_eq!(parse!(), Err(NOT_ENOUGH));
1353 assert_eq!(parse!(year: 1984), Err(NOT_ENOUGH));
1354 assert_eq!(parse!(year: 1984, month: 1), Err(NOT_ENOUGH));
1355 assert_eq!(parse!(year: 1984, month: 1, day: 2), ymd(1984, 1, 2));
1356 assert_eq!(parse!(year: 1984, day: 2), Err(NOT_ENOUGH));
1357 assert_eq!(parse!(year_div_100: 19), Err(NOT_ENOUGH));
1358 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84), Err(NOT_ENOUGH));
1359 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, month: 1), Err(NOT_ENOUGH));
1360 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, month: 1, day: 2), ymd(1984, 1, 2));
1361 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, day: 2), Err(NOT_ENOUGH));
1362 assert_eq!(parse!(year_div_100: 19, month: 1, day: 2), Err(NOT_ENOUGH));
1363 assert_eq!(parse!(year_mod_100: 70, month: 1, day: 2), ymd(1970, 1, 2));
1364 assert_eq!(parse!(year_mod_100: 69, month: 1, day: 2), ymd(2069, 1, 2));
1365
1366 assert_eq!(parse!(year_div_100: 19, year_mod_100: 84, month: 2, day: 29), ymd(1984, 2, 29));
1368 assert_eq!(
1369 parse!(year_div_100: 19, year_mod_100: 83, month: 2, day: 29),
1370 Err(OUT_OF_RANGE)
1371 );
1372 assert_eq!(
1373 parse!(year_div_100: 19, year_mod_100: 83, month: 13, day: 1),
1374 Err(OUT_OF_RANGE)
1375 );
1376 assert_eq!(
1377 parse!(year_div_100: 19, year_mod_100: 83, month: 12, day: 31),
1378 ymd(1983, 12, 31)
1379 );
1380 assert_eq!(
1381 parse!(year_div_100: 19, year_mod_100: 83, month: 12, day: 32),
1382 Err(OUT_OF_RANGE)
1383 );
1384 assert_eq!(
1385 parse!(year_div_100: 19, year_mod_100: 83, month: 12, day: 0),
1386 Err(OUT_OF_RANGE)
1387 );
1388 assert_eq!(
1389 parse!(year_div_100: 19, year_mod_100: 100, month: 1, day: 1),
1390 Err(OUT_OF_RANGE)
1391 );
1392 assert_eq!(parse!(year_div_100: 19, year_mod_100: -1, month: 1, day: 1), Err(OUT_OF_RANGE));
1393 assert_eq!(parse!(year_div_100: 0, year_mod_100: 0, month: 1, day: 1), ymd(0, 1, 1));
1394 assert_eq!(parse!(year_div_100: -1, year_mod_100: 42, month: 1, day: 1), Err(IMPOSSIBLE));
1395 let max_year = NaiveDate::MAX.year();
1396 assert_eq!(
1397 parse!(year_div_100: max_year / 100,
1398 year_mod_100: max_year % 100, month: 1, day: 1),
1399 ymd(max_year, 1, 1)
1400 );
1401 assert_eq!(
1402 parse!(year_div_100: (max_year + 1) / 100,
1403 year_mod_100: (max_year + 1) % 100, month: 1, day: 1),
1404 Err(OUT_OF_RANGE)
1405 );
1406
1407 assert_eq!(parse!(year: 1984, year_div_100: 19, month: 1, day: 1), ymd(1984, 1, 1));
1409 assert_eq!(parse!(year: 1984, year_div_100: 20, month: 1, day: 1), Err(IMPOSSIBLE));
1410 assert_eq!(parse!(year: 1984, year_mod_100: 84, month: 1, day: 1), ymd(1984, 1, 1));
1411 assert_eq!(parse!(year: 1984, year_mod_100: 83, month: 1, day: 1), Err(IMPOSSIBLE));
1412 assert_eq!(
1413 parse!(year: 1984, year_div_100: 19, year_mod_100: 84, month: 1, day: 1),
1414 ymd(1984, 1, 1)
1415 );
1416 assert_eq!(
1417 parse!(year: 1984, year_div_100: 18, year_mod_100: 94, month: 1, day: 1),
1418 Err(IMPOSSIBLE)
1419 );
1420 assert_eq!(
1421 parse!(year: 1984, year_div_100: 18, year_mod_100: 184, month: 1, day: 1),
1422 Err(OUT_OF_RANGE)
1423 );
1424 assert_eq!(
1425 parse!(year: -1, year_div_100: 0, year_mod_100: -1, month: 1, day: 1),
1426 Err(OUT_OF_RANGE)
1427 );
1428 assert_eq!(
1429 parse!(year: -1, year_div_100: -1, year_mod_100: 99, month: 1, day: 1),
1430 Err(IMPOSSIBLE)
1431 );
1432 assert_eq!(parse!(year: -1, year_div_100: 0, month: 1, day: 1), Err(IMPOSSIBLE));
1433 assert_eq!(parse!(year: -1, year_mod_100: 99, month: 1, day: 1), Err(IMPOSSIBLE));
1434
1435 assert_eq!(parse!(year: 2000, week_from_mon: 0), Err(NOT_ENOUGH));
1437 assert_eq!(parse!(year: 2000, week_from_sun: 0), Err(NOT_ENOUGH));
1438 assert_eq!(parse!(year: 2000, weekday: Sun), Err(NOT_ENOUGH));
1439 assert_eq!(parse!(year: 2000, week_from_mon: 0, weekday: Fri), Err(IMPOSSIBLE));
1440 assert_eq!(parse!(year: 2000, week_from_sun: 0, weekday: Fri), Err(IMPOSSIBLE));
1441 assert_eq!(parse!(year: 2000, week_from_mon: 0, weekday: Sat), ymd(2000, 1, 1));
1442 assert_eq!(parse!(year: 2000, week_from_sun: 0, weekday: Sat), ymd(2000, 1, 1));
1443 assert_eq!(parse!(year: 2000, week_from_mon: 0, weekday: Sun), ymd(2000, 1, 2));
1444 assert_eq!(parse!(year: 2000, week_from_sun: 1, weekday: Sun), ymd(2000, 1, 2));
1445 assert_eq!(parse!(year: 2000, week_from_mon: 1, weekday: Mon), ymd(2000, 1, 3));
1446 assert_eq!(parse!(year: 2000, week_from_sun: 1, weekday: Mon), ymd(2000, 1, 3));
1447 assert_eq!(parse!(year: 2000, week_from_mon: 1, weekday: Sat), ymd(2000, 1, 8));
1448 assert_eq!(parse!(year: 2000, week_from_sun: 1, weekday: Sat), ymd(2000, 1, 8));
1449 assert_eq!(parse!(year: 2000, week_from_mon: 1, weekday: Sun), ymd(2000, 1, 9));
1450 assert_eq!(parse!(year: 2000, week_from_sun: 2, weekday: Sun), ymd(2000, 1, 9));
1451 assert_eq!(parse!(year: 2000, week_from_mon: 2, weekday: Mon), ymd(2000, 1, 10));
1452 assert_eq!(parse!(year: 2000, week_from_sun: 52, weekday: Sat), ymd(2000, 12, 30));
1453 assert_eq!(parse!(year: 2000, week_from_sun: 53, weekday: Sun), ymd(2000, 12, 31));
1454 assert_eq!(parse!(year: 2000, week_from_sun: 53, weekday: Mon), Err(IMPOSSIBLE));
1455 assert_eq!(parse!(year: 2000, week_from_sun: 0xffffffff, weekday: Mon), Err(OUT_OF_RANGE));
1456 assert_eq!(parse!(year: 2006, week_from_sun: 0, weekday: Sat), Err(IMPOSSIBLE));
1457 assert_eq!(parse!(year: 2006, week_from_sun: 1, weekday: Sun), ymd(2006, 1, 1));
1458
1459 assert_eq!(
1461 parse!(year: 2000, week_from_mon: 1, week_from_sun: 1, weekday: Sat),
1462 ymd(2000, 1, 8)
1463 );
1464 assert_eq!(
1465 parse!(year: 2000, week_from_mon: 1, week_from_sun: 2, weekday: Sun),
1466 ymd(2000, 1, 9)
1467 );
1468 assert_eq!(
1469 parse!(year: 2000, week_from_mon: 1, week_from_sun: 1, weekday: Sun),
1470 Err(IMPOSSIBLE)
1471 );
1472 assert_eq!(
1473 parse!(year: 2000, week_from_mon: 2, week_from_sun: 2, weekday: Sun),
1474 Err(IMPOSSIBLE)
1475 );
1476
1477 assert_eq!(parse!(isoyear: 2004, isoweek: 53), Err(NOT_ENOUGH));
1479 assert_eq!(parse!(isoyear: 2004, isoweek: 53, weekday: Fri), ymd(2004, 12, 31));
1480 assert_eq!(parse!(isoyear: 2004, isoweek: 53, weekday: Sat), ymd(2005, 1, 1));
1481 assert_eq!(parse!(isoyear: 2004, isoweek: 0xffffffff, weekday: Sat), Err(OUT_OF_RANGE));
1482 assert_eq!(parse!(isoyear: 2005, isoweek: 0, weekday: Thu), Err(OUT_OF_RANGE));
1483 assert_eq!(parse!(isoyear: 2005, isoweek: 5, weekday: Thu), ymd(2005, 2, 3));
1484 assert_eq!(parse!(isoyear: 2005, weekday: Thu), Err(NOT_ENOUGH));
1485
1486 assert_eq!(parse!(ordinal: 123), Err(NOT_ENOUGH));
1488 assert_eq!(parse!(year: 2000, ordinal: 0), Err(OUT_OF_RANGE));
1489 assert_eq!(parse!(year: 2000, ordinal: 1), ymd(2000, 1, 1));
1490 assert_eq!(parse!(year: 2000, ordinal: 60), ymd(2000, 2, 29));
1491 assert_eq!(parse!(year: 2000, ordinal: 61), ymd(2000, 3, 1));
1492 assert_eq!(parse!(year: 2000, ordinal: 366), ymd(2000, 12, 31));
1493 assert_eq!(parse!(year: 2000, ordinal: 367), Err(OUT_OF_RANGE));
1494 assert_eq!(parse!(year: 2000, ordinal: 0xffffffff), Err(OUT_OF_RANGE));
1495 assert_eq!(parse!(year: 2100, ordinal: 0), Err(OUT_OF_RANGE));
1496 assert_eq!(parse!(year: 2100, ordinal: 1), ymd(2100, 1, 1));
1497 assert_eq!(parse!(year: 2100, ordinal: 59), ymd(2100, 2, 28));
1498 assert_eq!(parse!(year: 2100, ordinal: 60), ymd(2100, 3, 1));
1499 assert_eq!(parse!(year: 2100, ordinal: 365), ymd(2100, 12, 31));
1500 assert_eq!(parse!(year: 2100, ordinal: 366), Err(OUT_OF_RANGE));
1501 assert_eq!(parse!(year: 2100, ordinal: 0xffffffff), Err(OUT_OF_RANGE));
1502
1503 assert_eq!(
1505 parse!(year: 2014, month: 12, day: 31, ordinal: 365, isoyear: 2015, isoweek: 1,
1506 week_from_sun: 52, week_from_mon: 52, weekday: Wed),
1507 ymd(2014, 12, 31)
1508 );
1509 assert_eq!(
1510 parse!(year: 2014, month: 12, ordinal: 365, isoyear: 2015, isoweek: 1,
1511 week_from_sun: 52, week_from_mon: 52),
1512 ymd(2014, 12, 31)
1513 );
1514 assert_eq!(
1515 parse!(year: 2014, month: 12, day: 31, ordinal: 365, isoyear: 2014, isoweek: 53,
1516 week_from_sun: 52, week_from_mon: 52, weekday: Wed),
1517 Err(IMPOSSIBLE)
1518 ); assert_eq!(
1520 parse!(year: 2012, isoyear: 2015, isoweek: 1,
1521 week_from_sun: 52, week_from_mon: 52),
1522 Err(NOT_ENOUGH)
1523 ); assert_eq!(parse!(year_div_100: 20, isoyear_mod_100: 15, ordinal: 366), Err(NOT_ENOUGH));
1525 }
1527
1528 #[test]
1529 fn test_parsed_to_naive_time() {
1530 macro_rules! parse {
1531 ($($k:ident: $v:expr),*) => (
1532 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_naive_time()
1533 )
1534 }
1535
1536 let hms = |h, m, s| Ok(NaiveTime::from_hms_opt(h, m, s).unwrap());
1537 let hmsn = |h, m, s, n| Ok(NaiveTime::from_hms_nano_opt(h, m, s, n).unwrap());
1538
1539 assert_eq!(parse!(), Err(NOT_ENOUGH));
1541 assert_eq!(parse!(hour_div_12: 0), Err(NOT_ENOUGH));
1542 assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1), Err(NOT_ENOUGH));
1543 assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23), hms(1, 23, 0));
1544 assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 45), hms(1, 23, 45));
1545 assert_eq!(
1546 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 45,
1547 nanosecond: 678_901_234),
1548 hmsn(1, 23, 45, 678_901_234)
1549 );
1550 assert_eq!(parse!(hour_div_12: 1, hour_mod_12: 11, minute: 45, second: 6), hms(23, 45, 6));
1551 assert_eq!(parse!(hour_mod_12: 1, minute: 23), Err(NOT_ENOUGH));
1552 assert_eq!(
1553 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, nanosecond: 456_789_012),
1554 Err(NOT_ENOUGH)
1555 );
1556
1557 assert_eq!(parse!(hour_div_12: 2, hour_mod_12: 0, minute: 0), Err(OUT_OF_RANGE));
1559 assert_eq!(parse!(hour_div_12: 1, hour_mod_12: 12, minute: 0), Err(OUT_OF_RANGE));
1560 assert_eq!(parse!(hour_div_12: 0, hour_mod_12: 1, minute: 60), Err(OUT_OF_RANGE));
1561 assert_eq!(
1562 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 61),
1563 Err(OUT_OF_RANGE)
1564 );
1565 assert_eq!(
1566 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 34,
1567 nanosecond: 1_000_000_000),
1568 Err(OUT_OF_RANGE)
1569 );
1570
1571 assert_eq!(
1573 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 60),
1574 hmsn(1, 23, 59, 1_000_000_000)
1575 );
1576 assert_eq!(
1577 parse!(hour_div_12: 0, hour_mod_12: 1, minute: 23, second: 60,
1578 nanosecond: 999_999_999),
1579 hmsn(1, 23, 59, 1_999_999_999)
1580 );
1581 }
1582
1583 #[test]
1584 fn test_parsed_to_naive_datetime_with_offset() {
1585 macro_rules! parse {
1586 (offset = $offset:expr; $($k:ident: $v:expr),*) => (
1587 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_naive_datetime_with_offset($offset)
1588 );
1589 ($($k:ident: $v:expr),*) => (parse!(offset = 0; $($k: $v),*))
1590 }
1591
1592 let ymdhms = |y, m, d, h, n, s| {
1593 Ok(NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_opt(h, n, s).unwrap())
1594 };
1595 let ymdhmsn = |y, m, d, h, n, s, nano| {
1596 Ok(NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_nano_opt(h, n, s, nano).unwrap())
1597 };
1598
1599 assert_eq!(parse!(), Err(NOT_ENOUGH));
1601 assert_eq!(
1602 parse!(year: 2015, month: 1, day: 30,
1603 hour_div_12: 1, hour_mod_12: 2, minute: 38),
1604 ymdhms(2015, 1, 30, 14, 38, 0)
1605 );
1606 assert_eq!(
1607 parse!(year: 1997, month: 1, day: 30,
1608 hour_div_12: 1, hour_mod_12: 2, minute: 38, second: 5),
1609 ymdhms(1997, 1, 30, 14, 38, 5)
1610 );
1611 assert_eq!(
1612 parse!(year: 2012, ordinal: 34, hour_div_12: 0, hour_mod_12: 5,
1613 minute: 6, second: 7, nanosecond: 890_123_456),
1614 ymdhmsn(2012, 2, 3, 5, 6, 7, 890_123_456)
1615 );
1616 assert_eq!(parse!(timestamp: 0), ymdhms(1970, 1, 1, 0, 0, 0));
1617 assert_eq!(parse!(timestamp: 1, nanosecond: 0), ymdhms(1970, 1, 1, 0, 0, 1));
1618 assert_eq!(parse!(timestamp: 1, nanosecond: 1), ymdhmsn(1970, 1, 1, 0, 0, 1, 1));
1619 assert_eq!(parse!(timestamp: 1_420_000_000), ymdhms(2014, 12, 31, 4, 26, 40));
1620 assert_eq!(parse!(timestamp: -0x1_0000_0000), ymdhms(1833, 11, 24, 17, 31, 44));
1621
1622 assert_eq!(
1624 parse!(year: 2014, year_div_100: 20, year_mod_100: 14, month: 12, day: 31,
1625 ordinal: 365, isoyear: 2015, isoyear_div_100: 20, isoyear_mod_100: 15,
1626 isoweek: 1, week_from_sun: 52, week_from_mon: 52, weekday: Wed,
1627 hour_div_12: 0, hour_mod_12: 4, minute: 26, second: 40,
1628 nanosecond: 12_345_678, timestamp: 1_420_000_000),
1629 ymdhmsn(2014, 12, 31, 4, 26, 40, 12_345_678)
1630 );
1631 assert_eq!(
1632 parse!(year: 2014, year_div_100: 20, year_mod_100: 14, month: 12, day: 31,
1633 ordinal: 365, isoyear: 2015, isoyear_div_100: 20, isoyear_mod_100: 15,
1634 isoweek: 1, week_from_sun: 52, week_from_mon: 52, weekday: Wed,
1635 hour_div_12: 0, hour_mod_12: 4, minute: 26, second: 40,
1636 nanosecond: 12_345_678, timestamp: 1_419_999_999),
1637 Err(IMPOSSIBLE)
1638 );
1639 assert_eq!(
1640 parse!(offset = 32400;
1641 year: 2014, year_div_100: 20, year_mod_100: 14, month: 12, day: 31,
1642 ordinal: 365, isoyear: 2015, isoyear_div_100: 20, isoyear_mod_100: 15,
1643 isoweek: 1, week_from_sun: 52, week_from_mon: 52, weekday: Wed,
1644 hour_div_12: 0, hour_mod_12: 4, minute: 26, second: 40,
1645 nanosecond: 12_345_678, timestamp: 1_419_967_600),
1646 ymdhmsn(2014, 12, 31, 4, 26, 40, 12_345_678)
1647 );
1648
1649 let max_days_from_year_1970 =
1651 NaiveDate::MAX.signed_duration_since(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap());
1652 let year_0_from_year_1970 = NaiveDate::from_ymd_opt(0, 1, 1)
1653 .unwrap()
1654 .signed_duration_since(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap());
1655 let min_days_from_year_1970 =
1656 NaiveDate::MIN.signed_duration_since(NaiveDate::from_ymd_opt(1970, 1, 1).unwrap());
1657 assert_eq!(
1658 parse!(timestamp: min_days_from_year_1970.num_seconds()),
1659 ymdhms(NaiveDate::MIN.year(), 1, 1, 0, 0, 0)
1660 );
1661 assert_eq!(
1662 parse!(timestamp: year_0_from_year_1970.num_seconds()),
1663 ymdhms(0, 1, 1, 0, 0, 0)
1664 );
1665 assert_eq!(
1666 parse!(timestamp: max_days_from_year_1970.num_seconds() + 86399),
1667 ymdhms(NaiveDate::MAX.year(), 12, 31, 23, 59, 59)
1668 );
1669
1670 assert_eq!(parse!(second: 59, timestamp: 1_341_100_798), Err(IMPOSSIBLE));
1672 assert_eq!(parse!(second: 59, timestamp: 1_341_100_799), ymdhms(2012, 6, 30, 23, 59, 59));
1673 assert_eq!(parse!(second: 59, timestamp: 1_341_100_800), Err(IMPOSSIBLE));
1674 assert_eq!(
1675 parse!(second: 60, timestamp: 1_341_100_799),
1676 ymdhmsn(2012, 6, 30, 23, 59, 59, 1_000_000_000)
1677 );
1678 assert_eq!(
1679 parse!(second: 60, timestamp: 1_341_100_800),
1680 ymdhmsn(2012, 6, 30, 23, 59, 59, 1_000_000_000)
1681 );
1682 assert_eq!(parse!(second: 0, timestamp: 1_341_100_800), ymdhms(2012, 7, 1, 0, 0, 0));
1683 assert_eq!(parse!(second: 1, timestamp: 1_341_100_800), Err(IMPOSSIBLE));
1684 assert_eq!(parse!(second: 60, timestamp: 1_341_100_801), Err(IMPOSSIBLE));
1685
1686 assert_eq!(
1689 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1690 minute: 59, second: 59, timestamp: 1_341_100_798),
1691 Err(IMPOSSIBLE)
1692 );
1693 assert_eq!(
1694 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1695 minute: 59, second: 59, timestamp: 1_341_100_799),
1696 ymdhms(2012, 6, 30, 23, 59, 59)
1697 );
1698 assert_eq!(
1699 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1700 minute: 59, second: 59, timestamp: 1_341_100_800),
1701 Err(IMPOSSIBLE)
1702 );
1703 assert_eq!(
1704 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1705 minute: 59, second: 60, timestamp: 1_341_100_799),
1706 ymdhmsn(2012, 6, 30, 23, 59, 59, 1_000_000_000)
1707 );
1708 assert_eq!(
1709 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1710 minute: 59, second: 60, timestamp: 1_341_100_800),
1711 ymdhmsn(2012, 6, 30, 23, 59, 59, 1_000_000_000)
1712 );
1713 assert_eq!(
1714 parse!(year: 2012, ordinal: 183, hour_div_12: 0, hour_mod_12: 0,
1715 minute: 0, second: 0, timestamp: 1_341_100_800),
1716 ymdhms(2012, 7, 1, 0, 0, 0)
1717 );
1718 assert_eq!(
1719 parse!(year: 2012, ordinal: 183, hour_div_12: 0, hour_mod_12: 0,
1720 minute: 0, second: 1, timestamp: 1_341_100_800),
1721 Err(IMPOSSIBLE)
1722 );
1723 assert_eq!(
1724 parse!(year: 2012, ordinal: 182, hour_div_12: 1, hour_mod_12: 11,
1725 minute: 59, second: 60, timestamp: 1_341_100_801),
1726 Err(IMPOSSIBLE)
1727 );
1728
1729 assert_eq!(
1731 parse!(year: 2015, month: 1, day: 20, weekday: Tue,
1732 hour_div_12: 2, hour_mod_12: 1, minute: 35, second: 20),
1733 Err(OUT_OF_RANGE)
1734 ); }
1736
1737 #[test]
1738 fn test_parsed_to_datetime() {
1739 macro_rules! parse {
1740 ($($k:ident: $v:expr),*) => (
1741 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_datetime()
1742 )
1743 }
1744
1745 let ymdhmsn = |y, m, d, h, n, s, nano, off| {
1746 Ok(FixedOffset::east_opt(off)
1747 .unwrap()
1748 .from_local_datetime(
1749 &NaiveDate::from_ymd_opt(y, m, d)
1750 .unwrap()
1751 .and_hms_nano_opt(h, n, s, nano)
1752 .unwrap(),
1753 )
1754 .unwrap())
1755 };
1756
1757 assert_eq!(parse!(offset: 0), Err(NOT_ENOUGH));
1758 assert_eq!(
1759 parse!(year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1760 minute: 26, second: 40, nanosecond: 12_345_678),
1761 Err(NOT_ENOUGH)
1762 );
1763 assert_eq!(
1764 parse!(year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1765 minute: 26, second: 40, nanosecond: 12_345_678, offset: 0),
1766 ymdhmsn(2014, 12, 31, 4, 26, 40, 12_345_678, 0)
1767 );
1768 assert_eq!(
1769 parse!(year: 2014, ordinal: 365, hour_div_12: 1, hour_mod_12: 1,
1770 minute: 26, second: 40, nanosecond: 12_345_678, offset: 32400),
1771 ymdhmsn(2014, 12, 31, 13, 26, 40, 12_345_678, 32400)
1772 );
1773 assert_eq!(
1774 parse!(year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 1,
1775 minute: 42, second: 4, nanosecond: 12_345_678, offset: -9876),
1776 ymdhmsn(2014, 12, 31, 1, 42, 4, 12_345_678, -9876)
1777 );
1778 assert_eq!(
1779 parse!(year: 2015, ordinal: 1, hour_div_12: 0, hour_mod_12: 4,
1780 minute: 26, second: 40, nanosecond: 12_345_678, offset: 86_400),
1781 Err(OUT_OF_RANGE)
1782 ); }
1784
1785 #[test]
1786 fn test_parsed_to_datetime_with_timezone() {
1787 macro_rules! parse {
1788 ($tz:expr; $($k:ident: $v:expr),*) => (
1789 Parsed { $($k: Some($v),)* ..Parsed::new() }.to_datetime_with_timezone(&$tz)
1790 )
1791 }
1792
1793 assert_eq!(
1795 parse!(Utc;
1796 year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1797 minute: 26, second: 40, nanosecond: 12_345_678, offset: 0),
1798 Ok(Utc
1799 .from_local_datetime(
1800 &NaiveDate::from_ymd_opt(2014, 12, 31)
1801 .unwrap()
1802 .and_hms_nano_opt(4, 26, 40, 12_345_678)
1803 .unwrap()
1804 )
1805 .unwrap())
1806 );
1807 assert_eq!(
1808 parse!(Utc;
1809 year: 2014, ordinal: 365, hour_div_12: 1, hour_mod_12: 1,
1810 minute: 26, second: 40, nanosecond: 12_345_678, offset: 32400),
1811 Err(IMPOSSIBLE)
1812 );
1813 assert_eq!(
1814 parse!(FixedOffset::east_opt(32400).unwrap();
1815 year: 2014, ordinal: 365, hour_div_12: 0, hour_mod_12: 4,
1816 minute: 26, second: 40, nanosecond: 12_345_678, offset: 0),
1817 Err(IMPOSSIBLE)
1818 );
1819 assert_eq!(
1820 parse!(FixedOffset::east_opt(32400).unwrap();
1821 year: 2014, ordinal: 365, hour_div_12: 1, hour_mod_12: 1,
1822 minute: 26, second: 40, nanosecond: 12_345_678, offset: 32400),
1823 Ok(FixedOffset::east_opt(32400)
1824 .unwrap()
1825 .from_local_datetime(
1826 &NaiveDate::from_ymd_opt(2014, 12, 31)
1827 .unwrap()
1828 .and_hms_nano_opt(13, 26, 40, 12_345_678)
1829 .unwrap()
1830 )
1831 .unwrap())
1832 );
1833
1834 assert_eq!(
1836 parse!(Utc; timestamp: 1_420_000_000, offset: 0),
1837 Ok(Utc.with_ymd_and_hms(2014, 12, 31, 4, 26, 40).unwrap())
1838 );
1839 assert_eq!(parse!(Utc; timestamp: 1_420_000_000, offset: 32400), Err(IMPOSSIBLE));
1840 assert_eq!(
1841 parse!(FixedOffset::east_opt(32400).unwrap(); timestamp: 1_420_000_000, offset: 0),
1842 Err(IMPOSSIBLE)
1843 );
1844 assert_eq!(
1845 parse!(FixedOffset::east_opt(32400).unwrap(); timestamp: 1_420_000_000, offset: 32400),
1846 Ok(FixedOffset::east_opt(32400)
1847 .unwrap()
1848 .with_ymd_and_hms(2014, 12, 31, 13, 26, 40)
1849 .unwrap())
1850 );
1851
1852 }
1854
1855 #[test]
1856 fn issue_551() {
1857 use crate::Weekday;
1858 let mut parsed = Parsed::new();
1859
1860 parsed.year = Some(2002);
1861 parsed.week_from_mon = Some(22);
1862 parsed.weekday = Some(Weekday::Mon);
1863 assert_eq!(NaiveDate::from_ymd_opt(2002, 6, 3).unwrap(), parsed.to_naive_date().unwrap());
1864
1865 parsed.year = Some(2001);
1866 assert_eq!(NaiveDate::from_ymd_opt(2001, 5, 28).unwrap(), parsed.to_naive_date().unwrap());
1867 }
1868}