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