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