sqldatetime/
oracle.rs

1use crate::common::{
2    days_of_month, is_valid_timestamp, MONTHS_PER_YEAR, USECONDS_PER_DAY, USECONDS_PER_SECOND,
3};
4use crate::error::{Error, Result};
5use crate::format::{DateTimeFormat, LazyFormat, NaiveDateTime};
6use crate::local::Local;
7use crate::{
8    Date as SqlDate, DateTime, Formatter, IntervalDT, IntervalYM, Round, Time, Timestamp, Trunc,
9};
10use std::cmp::Ordering;
11use std::convert::TryFrom;
12use std::fmt::Display;
13
14/// Oracle oriented `Date` type.
15#[cfg_attr(docsrs, doc(cfg(feature = "oracle")))]
16#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
17#[repr(transparent)]
18pub struct Date(Timestamp);
19
20impl Date {
21    /// The smallest date that can be represented by `Date`, i.e. `0001-01-01 00:00:00`.
22    pub const MIN: Self = Date(Timestamp::MIN);
23
24    /// The largest date that can be represented by `Date`, i.e. `9999-12-31 23:59:59`.
25    pub const MAX: Self = Date(Timestamp::new(SqlDate::MAX, unsafe {
26        Time::from_hms_unchecked(23, 59, 59, 0)
27    }));
28
29    /// Creates a new Oracle `Date` from a date and a time.
30    #[inline]
31    pub const fn new(date: SqlDate, time: Time) -> Self {
32        let time = if time.usecs() % USECONDS_PER_SECOND != 0 {
33            unsafe {
34                Time::from_usecs_unchecked(time.usecs() / USECONDS_PER_SECOND * USECONDS_PER_SECOND)
35            }
36        } else {
37            time
38        };
39        Date(Timestamp::new(date, time))
40    }
41
42    /// Gets the microsecond value from Unix Epoch of `Date`.
43    #[inline(always)]
44    pub const fn usecs(self) -> i64 {
45        self.0.usecs()
46    }
47
48    /// Extracts `(Date, Time)` from the Oracle `Date`.
49    #[inline]
50    pub const fn extract(self) -> (SqlDate, Time) {
51        self.0.extract()
52    }
53
54    #[inline]
55    fn date(self) -> SqlDate {
56        self.0.date()
57    }
58
59    #[inline]
60    fn time(self) -> Time {
61        self.0.time()
62    }
63
64    /// Creates a `Date` from the given microseconds from Unix Epoch without checking validity.
65    ///
66    /// # Safety
67    /// This function is unsafe because the microsecond value is not checked for validity!
68    /// Before using it, check that the value is correct.
69    #[inline(always)]
70    pub const unsafe fn from_usecs_unchecked(usecs: i64) -> Self {
71        Date(Timestamp::from_usecs_unchecked(usecs))
72    }
73
74    /// Creates a `Date` from the given microseconds from Unix Epoch
75    #[inline]
76    pub const fn try_from_usecs(usecs: i64) -> Result<Self> {
77        if Self::is_valid_date(usecs) {
78            Ok(unsafe { Date(Timestamp::from_usecs_unchecked(usecs)) })
79        } else {
80            Err(Error::DateOutOfRange)
81        }
82    }
83
84    #[inline]
85    const fn is_valid_date(usecs: i64) -> bool {
86        is_valid_timestamp(usecs) && usecs % USECONDS_PER_SECOND == 0
87    }
88
89    /// Formats `Date` by given format string.
90    #[inline]
91    pub fn format<S: AsRef<str>>(self, fmt: S) -> Result<impl Display> {
92        let fmt = Formatter::try_new(fmt)?;
93        Ok(LazyFormat::new(fmt, self))
94    }
95
96    /// Parses `Date` from given string and format.
97    #[inline]
98    pub fn parse<S1: AsRef<str>, S2: AsRef<str>>(input: S1, fmt: S2) -> Result<Self> {
99        let fmt = Formatter::try_new(fmt)?;
100        fmt.parse(input)
101    }
102
103    /// `Date` adds `IntervalDT`
104    #[inline]
105    pub fn add_interval_dt(self, interval: IntervalDT) -> Result<Date> {
106        Ok(Date::from(self.0.add_interval_dt(interval)?))
107    }
108
109    /// `Date` adds `IntervalYM`
110    #[inline]
111    pub fn add_interval_ym(self, interval: IntervalYM) -> Result<Date> {
112        Ok(Date::from(self.0.add_interval_ym(interval)?))
113    }
114
115    /// `Date` adds `Time`
116    #[inline]
117    pub const fn add_time(self, time: Time) -> Result<Timestamp> {
118        self.0.add_time(time)
119    }
120
121    /// `Date` adds days
122    #[inline]
123    pub fn add_days(self, days: f64) -> Result<Date> {
124        let timestamp = self.0.add_days(days)?;
125        Ok(Date(Timestamp::try_from_usecs(
126            ((timestamp.usecs() as f64) / USECONDS_PER_SECOND as f64).round() as i64
127                * USECONDS_PER_SECOND,
128        )?))
129    }
130
131    /// `Date` subtracts `Date`
132    #[inline]
133    pub fn sub_date(self, date: Date) -> f64 {
134        (self.usecs() - date.usecs()) as f64 / USECONDS_PER_DAY as f64
135    }
136
137    /// `Date` subtracts `Timestamp`
138    #[inline]
139    pub fn sub_timestamp(self, timestamp: Timestamp) -> IntervalDT {
140        self.0.sub_timestamp(timestamp)
141    }
142
143    /// `Date` subtracts `IntervalDT`
144    #[inline]
145    pub fn sub_interval_dt(self, interval: IntervalDT) -> Result<Date> {
146        self.add_interval_dt(-interval)
147    }
148
149    /// `Date` subtracts `Time`
150    #[inline]
151    pub const fn sub_time(self, time: Time) -> Result<Timestamp> {
152        self.0.sub_time(time)
153    }
154
155    /// `Date` subtracts `IntervalYM`
156    #[inline]
157    pub fn sub_interval_ym(self, interval: IntervalYM) -> Result<Date> {
158        self.add_interval_ym(-interval)
159    }
160
161    /// `Date` subtracts days
162    #[inline]
163    pub fn sub_days(self, days: f64) -> Result<Date> {
164        self.add_days(-days)
165    }
166
167    /// Get local system date
168    #[inline]
169    pub fn now() -> Result<Date> {
170        let now = Local::now();
171        Ok(Date::new(
172            SqlDate::try_from_ymd(now.year(), now.month(), now.day())?,
173            Time::try_from_hms(now.hour(), now.minute(), now.second(), 0)?,
174        ))
175    }
176
177    /// Gets the last day in month of `Date`.
178    #[inline]
179    pub fn last_day_of_month(self) -> Date {
180        self.0.last_day_of_month().into()
181    }
182
183    /// Gets months and microseconds of datetime between two `Date`.
184    #[inline]
185    pub fn months_between(self, date: Date) -> (i32, i64) {
186        let (date1, time1) = self.extract();
187        let (date2, time2) = date.extract();
188        let (year1, month1, day1) = date1.extract();
189        let (year2, month2, day2) = date2.extract();
190        let mon = (year1 - year2) * MONTHS_PER_YEAR as i32 + month1 as i32 - month2 as i32;
191        let (mon, day) =
192            if day1 == days_of_month(year1, month1) && day2 == days_of_month(year2, month2) {
193                (mon, 0)
194            } else if day1 < day2 {
195                (mon - 1, day1 + 31 - day2)
196            } else {
197                (mon, day1 - day2)
198            };
199        let usecs = match day {
200            0 => 0,
201            _ => day as i64 * USECONDS_PER_DAY + (time1.usecs() - time2.usecs()),
202        };
203        (mon, usecs)
204    }
205}
206
207impl Trunc for Date {
208    #[inline]
209    fn trunc_century(self) -> Result<Self> {
210        Ok(self.0.trunc_century()?.into())
211    }
212
213    #[inline]
214    fn trunc_year(self) -> Result<Self> {
215        Ok(self.0.trunc_year()?.into())
216    }
217
218    #[inline]
219    fn trunc_iso_year(self) -> Result<Self> {
220        Ok(self.0.trunc_iso_year()?.into())
221    }
222
223    #[inline]
224    fn trunc_quarter(self) -> Result<Self> {
225        Ok(self.0.trunc_quarter()?.into())
226    }
227
228    #[inline]
229    fn trunc_month(self) -> Result<Self> {
230        Ok(self.0.trunc_month()?.into())
231    }
232
233    #[inline]
234    fn trunc_week(self) -> Result<Self> {
235        Ok(self.0.trunc_week()?.into())
236    }
237
238    #[inline]
239    fn trunc_iso_week(self) -> Result<Self> {
240        Ok(self.0.trunc_iso_week()?.into())
241    }
242
243    #[inline]
244    fn trunc_month_start_week(self) -> Result<Self> {
245        Ok(self.0.trunc_month_start_week()?.into())
246    }
247
248    #[inline]
249    fn trunc_day(self) -> Result<Self> {
250        Ok(self.0.trunc_day()?.into())
251    }
252
253    #[inline]
254    fn trunc_sunday_start_week(self) -> Result<Self> {
255        Ok(self.0.trunc_sunday_start_week()?.into())
256    }
257
258    #[inline]
259    fn trunc_hour(self) -> Result<Self> {
260        Ok(self.0.trunc_hour()?.into())
261    }
262
263    #[inline]
264    fn trunc_minute(self) -> Result<Self> {
265        Ok(self.0.trunc_minute()?.into())
266    }
267}
268
269impl Round for Date {
270    #[inline]
271    fn round_century(self) -> Result<Self> {
272        Ok(self.0.round_century()?.into())
273    }
274
275    #[inline]
276    fn round_year(self) -> Result<Self> {
277        Ok(self.0.round_year()?.into())
278    }
279
280    #[inline]
281    fn round_iso_year(self) -> Result<Self> {
282        Ok(self.0.round_iso_year()?.into())
283    }
284
285    #[inline]
286    fn round_quarter(self) -> Result<Self> {
287        Ok(self.0.round_quarter()?.into())
288    }
289
290    #[inline]
291    fn round_month(self) -> Result<Self> {
292        Ok(self.0.round_month()?.into())
293    }
294
295    #[inline]
296    fn round_week(self) -> Result<Self> {
297        Ok(self.0.round_week()?.into())
298    }
299
300    #[inline]
301    fn round_iso_week(self) -> Result<Self> {
302        Ok(self.0.round_iso_week()?.into())
303    }
304
305    #[inline]
306    fn round_month_start_week(self) -> Result<Self> {
307        Ok(self.0.round_month_start_week()?.into())
308    }
309
310    #[inline]
311    fn round_day(self) -> Result<Self> {
312        Ok(self.0.round_day()?.into())
313    }
314
315    #[inline]
316    fn round_sunday_start_week(self) -> Result<Self> {
317        Ok(self.0.round_sunday_start_week()?.into())
318    }
319
320    #[inline]
321    fn round_hour(self) -> Result<Self> {
322        Ok(self.0.round_hour()?.into())
323    }
324
325    #[inline]
326    fn round_minute(self) -> Result<Self> {
327        Ok(self.0.round_minute()?.into())
328    }
329}
330
331impl Timestamp {
332    /// `Timestamp` subtracts `Date`
333    #[inline]
334    pub const fn oracle_sub_date(self, date: Date) -> IntervalDT {
335        self.sub_timestamp(date.0)
336    }
337
338    /// `Timestamp` add days
339    #[inline]
340    pub fn oracle_add_days(self, days: f64) -> Result<Date> {
341        Date::from(self).add_days(days)
342    }
343
344    /// `Timestamp` subtracts days
345    #[inline]
346    pub fn oracle_sub_days(self, days: f64) -> Result<Date> {
347        Date::from(self).add_days(-days)
348    }
349}
350
351impl DateTime for Date {
352    #[inline]
353    fn year(&self) -> Option<i32> {
354        Date::date(*self).year()
355    }
356
357    #[inline]
358    fn month(&self) -> Option<i32> {
359        Date::date(*self).month()
360    }
361
362    #[inline]
363    fn day(&self) -> Option<i32> {
364        Date::date(*self).day()
365    }
366
367    #[inline]
368    fn hour(&self) -> Option<i32> {
369        self.time().hour()
370    }
371
372    #[inline]
373    fn minute(&self) -> Option<i32> {
374        self.time().minute()
375    }
376
377    #[inline]
378    fn second(&self) -> Option<f64> {
379        self.time().second()
380    }
381
382    #[inline]
383    fn date(&self) -> Option<SqlDate> {
384        Some(Date::date(*self))
385    }
386}
387
388impl From<Timestamp> for Date {
389    #[inline]
390    fn from(timestamp: Timestamp) -> Self {
391        let usecs = timestamp.usecs();
392        let temp = usecs / USECONDS_PER_SECOND * USECONDS_PER_SECOND;
393        let result = if usecs < 0 && temp > usecs {
394            temp - USECONDS_PER_SECOND
395        } else {
396            temp
397        };
398
399        unsafe { Date(Timestamp::from_usecs_unchecked(result)) }
400    }
401}
402
403impl From<Date> for Timestamp {
404    #[inline]
405    fn from(input: Date) -> Self {
406        input.0
407    }
408}
409
410impl TryFrom<Time> for Date {
411    type Error = Error;
412
413    #[inline]
414    fn try_from(time: Time) -> Result<Self> {
415        let now = Local::now();
416        Ok(Date::new(
417            SqlDate::try_from_ymd(now.year(), now.month(), now.day())?,
418            time,
419        ))
420    }
421}
422
423impl From<Date> for Time {
424    #[inline(always)]
425    fn from(date: Date) -> Self {
426        date.time()
427    }
428}
429
430impl From<Date> for NaiveDateTime {
431    #[inline]
432    fn from(dt: Date) -> Self {
433        let (date, time) = dt.extract();
434        let (year, month, day) = date.extract();
435        let (hour, minute, sec, usec) = time.extract();
436
437        NaiveDateTime {
438            year,
439            month,
440            day,
441            hour,
442            minute,
443            sec,
444            usec,
445            ampm: None,
446            negative: false,
447        }
448    }
449}
450
451impl TryFrom<NaiveDateTime> for Date {
452    type Error = Error;
453
454    #[inline]
455    fn try_from(dt: NaiveDateTime) -> Result<Self> {
456        Ok(Date::from(Timestamp::try_from(dt)?))
457    }
458}
459
460impl DateTimeFormat for Date {
461    const HAS_DATE: bool = true;
462    const HAS_TIME: bool = true;
463    const HAS_FRACTION: bool = false;
464    const IS_INTERVAL_YM: bool = false;
465    const IS_INTERVAL_DT: bool = false;
466}
467
468impl PartialEq<Date> for Timestamp {
469    #[inline]
470    fn eq(&self, other: &Date) -> bool {
471        *self == other.0
472    }
473}
474
475impl PartialOrd<Date> for Timestamp {
476    #[inline]
477    fn partial_cmp(&self, other: &Date) -> Option<Ordering> {
478        self.partial_cmp(&other.0)
479    }
480}
481
482impl PartialEq<Timestamp> for Date {
483    #[inline]
484    fn eq(&self, other: &Timestamp) -> bool {
485        self.0 == *other
486    }
487}
488
489impl PartialOrd<Timestamp> for Date {
490    #[inline]
491    fn partial_cmp(&self, other: &Timestamp) -> Option<Ordering> {
492        self.0.partial_cmp(other)
493    }
494}
495
496impl PartialEq<Date> for SqlDate {
497    #[inline]
498    fn eq(&self, other: &Date) -> bool {
499        self.and_zero_time() == other.0
500    }
501}
502
503impl PartialOrd<Date> for SqlDate {
504    #[inline]
505    fn partial_cmp(&self, other: &Date) -> Option<Ordering> {
506        self.and_zero_time().partial_cmp(&other.0)
507    }
508}
509
510impl PartialEq<SqlDate> for Date {
511    #[inline]
512    fn eq(&self, other: &SqlDate) -> bool {
513        self.0 == other.and_zero_time()
514    }
515}
516
517impl PartialOrd<SqlDate> for Date {
518    #[inline]
519    fn partial_cmp(&self, other: &SqlDate) -> Option<Ordering> {
520        self.0.partial_cmp(&other.and_zero_time())
521    }
522}
523
524#[cfg(test)]
525mod tests {
526    use super::*;
527    use crate::common::USECONDS_PER_HOUR;
528
529    fn generate_date(year: i32, month: u32, day: u32, hour: u32, min: u32, sec: u32) -> Date {
530        Date::new(
531            SqlDate::try_from_ymd(year, month, day).unwrap(),
532            Time::try_from_hms(hour, min, sec, 0).unwrap(),
533        )
534    }
535
536    fn generate_ts(
537        year: i32,
538        month: u32,
539        day: u32,
540        hour: u32,
541        min: u32,
542        sec: u32,
543        usec: u32,
544    ) -> Timestamp {
545        Timestamp::new(
546            SqlDate::try_from_ymd(year, month, day).unwrap(),
547            Time::try_from_hms(hour, min, sec, usec).unwrap(),
548        )
549    }
550
551    fn generate_sql_date(year: i32, month: u32, day: u32) -> SqlDate {
552        SqlDate::try_from_ymd(year, month, day).unwrap()
553    }
554
555    fn generate_time(hour: u32, min: u32, sec: u32, usec: u32) -> Time {
556        Time::try_from_hms(hour, min, sec, usec).unwrap()
557    }
558
559    #[test]
560    fn test_date() {
561        {
562            let time = Time::try_from_hms(1, 23, 4, 5).unwrap();
563            let timestamp = Timestamp::try_from(time).unwrap();
564            let date = Date::try_from(time).unwrap();
565            let now = Local::now();
566            assert_eq!(
567                timestamp,
568                generate_ts(now.year(), now.month(), now.day(), 1, 23, 4, 5)
569            );
570            assert_eq!(
571                date,
572                generate_date(now.year(), now.month(), now.day(), 1, 23, 4)
573            );
574
575            let date = SqlDate::try_from_ymd(1970, 1, 1).unwrap();
576            let time = Time::try_from_hms(1, 2, 3, 4).unwrap();
577            let date = Date::new(date, time);
578            assert_eq!(date.usecs(), generate_ts(1970, 1, 1, 1, 2, 3, 0).usecs());
579
580            let date = SqlDate::try_from_ymd(1969, 1, 1).unwrap();
581            let time = Time::try_from_hms(1, 2, 3, 4).unwrap();
582            let date = Date::new(date, time);
583            assert_eq!(date.usecs(), generate_ts(1969, 1, 1, 1, 2, 3, 0).usecs());
584
585            let date = SqlDate::try_from_ymd(1970, 1, 1).unwrap();
586            let time = Time::try_from_hms(0, 0, 0, 0).unwrap();
587            let date = Date::new(date, time);
588            assert_eq!(date.usecs(), 0);
589
590            let (sql_date, time) = date.extract();
591            assert_eq!(sql_date.extract(), (1970, 1, 1));
592            assert_eq!(time.extract(), (0, 0, 0, 0));
593
594            let date = generate_date(1, 1, 1, 0, 0, 0);
595            let (sql_date, time) = date.extract();
596            assert_eq!(sql_date.extract(), (1, 1, 1));
597            assert_eq!(time.extract(), (0, 0, 0, 0));
598
599            let date = generate_date(1, 1, 1, 23, 59, 59);
600            let (sql_date, time) = date.extract();
601            assert_eq!(sql_date.extract(), (1, 1, 1));
602            assert_eq!(time.extract(), (23, 59, 59, 0));
603
604            let date = generate_date(1, 12, 31, 0, 0, 0);
605            let (sql_date, time) = date.extract();
606            assert_eq!(sql_date.extract(), (1, 12, 31));
607            assert_eq!(time.extract(), (0, 0, 0, 0));
608
609            let date = generate_date(1, 12, 31, 23, 59, 59);
610            let (sql_date, time) = date.extract();
611            assert_eq!(sql_date.extract(), (1, 12, 31));
612            assert_eq!(time.extract(), (23, 59, 59, 0));
613
614            let date = generate_date(1969, 12, 30, 0, 0, 0);
615            let (sql_date, time) = date.extract();
616            assert_eq!(sql_date.extract(), (1969, 12, 30));
617            assert_eq!(time.extract(), (0, 0, 0, 0));
618
619            let date = generate_date(1969, 12, 30, 23, 59, 59);
620            let (sql_date, time) = date.extract();
621            assert_eq!(sql_date.extract(), (1969, 12, 30));
622            assert_eq!(time.extract(), (23, 59, 59, 0));
623
624            let date = generate_date(1969, 12, 31, 0, 0, 0);
625            let (sql_date, time) = date.extract();
626            assert_eq!(sql_date.extract(), (1969, 12, 31));
627            assert_eq!(time.extract(), (0, 0, 0, 0));
628
629            let date = generate_date(1969, 12, 31, 23, 59, 59);
630            let (sql_date, time) = date.extract();
631            assert_eq!(sql_date.extract(), (1969, 12, 31));
632            assert_eq!(time.extract(), (23, 59, 59, 0));
633
634            let date = generate_date(1970, 1, 1, 0, 0, 0);
635            let (sql_date, time) = date.extract();
636            assert_eq!(sql_date.extract(), (1970, 1, 1));
637            assert_eq!(time.extract(), (0, 0, 0, 0));
638
639            let date = generate_date(1970, 1, 1, 23, 59, 59);
640            let (sql_date, time) = date.extract();
641            assert_eq!(sql_date.extract(), (1970, 1, 1));
642            assert_eq!(time.extract(), (23, 59, 59, 0));
643
644            let date = generate_date(1970, 3, 4, 23, 12, 30);
645            let (sql_date, time) = date.extract();
646            assert_eq!(sql_date.extract(), (1970, 3, 4));
647            assert_eq!(time.extract(), (23, 12, 30, 0));
648
649            let date = generate_date(9999, 12, 31, 0, 0, 0);
650            let (sql_date, time) = date.extract();
651            assert_eq!(sql_date.extract(), (9999, 12, 31));
652            assert_eq!(time.extract(), (0, 0, 0, 0));
653
654            let date = generate_date(9999, 12, 31, 23, 59, 59);
655            let (sql_date, time) = date.extract();
656            assert_eq!(sql_date.extract(), (9999, 12, 31));
657            assert_eq!(time.extract(), (23, 59, 59, 0));
658
659            let date = generate_date(1969, 10, 31, 1, 1, 1);
660            let (sql_date, time) = date.extract();
661            assert_eq!(sql_date.extract(), (1969, 10, 31));
662            assert_eq!(time.extract(), (1, 1, 1, 0));
663
664            // Out of order
665            {
666                // Parse
667                let date = generate_date(9999, 12, 31, 23, 59, 59);
668                let ts2 =
669                    Date::parse("PM 9999\\12-31 11/59:59", "AM yyyy\\mm-dd hh/mi:ss").unwrap();
670                assert_eq!(ts2, date);
671
672                let ts2 = Date::parse("PM 11-9999-59 12-59-31", "PM HH-YYYY-MI MM-SS-DD").unwrap();
673                assert_eq!(ts2, date);
674
675                let ts2 = Date::parse("23-9999-59 12 59 31", "HH24-YYYY-MI MM SS DD").unwrap();
676                assert_eq!(date, ts2);
677
678                let ts2 =
679                    Date::parse("T23--59 12 59 31.9999;", "THH24--MI MM SS DD.YYYY;").unwrap();
680                assert_eq!(date, ts2);
681
682                // Format
683                let fmt = date.format("TAM HH\\YYYY\\MI MM-SS/DD").unwrap();
684                assert_eq!(format!("{}", fmt), "TPM 11\\9999\\59 12-59/31");
685
686                let fmt = date.format("HH\\YYYY\\MI MM-SS/DD;").unwrap();
687                assert_eq!(format!("{}", fmt), "11\\9999\\59 12-59/31;");
688            }
689
690            // Duplicate parse
691            {
692                // Parse
693                assert!(
694                    Date::parse("AM PM 9999\\12-31 11/59:59", "AM PM yyyy\\mm-dd hh/mi:ss")
695                        .is_err()
696                );
697
698                assert!(
699                    Date::parse("pm PM 9999\\12-31 11/59:59", "AM PM yyyy\\mm-dd hh/mi:ss")
700                        .is_err()
701                );
702
703                assert!(Date::parse(
704                    "9999 9999\\12-31 11/59:59.999999",
705                    "yyyy yyyy\\mm-dd hh/mi:ss.ff"
706                )
707                .is_err());
708
709                assert!(Date::parse("9999\\12-31 11/59:59 59", "yyyy\\mm-dd hh/mi:ss mi").is_err());
710
711                assert!(Date::parse(
712                    "2021-04-23 03:04:05 5 thursday",
713                    "yyyy-mm-dd hh24:mi:ss d day"
714                )
715                .is_err());
716
717                // todo duplication special check, including parse and format
718            }
719
720            // Default
721            {
722                let now = Local::now();
723                let year = now.year();
724                let month = now.month();
725
726                let dt = generate_date(year, month, 1, 0, 0, 5);
727                let date = Date::parse("5", "ss").unwrap();
728                assert_eq!(dt, date);
729
730                let dt = generate_date(year, month, 1, 0, 0, 0);
731                let date = Date::parse("", "").unwrap();
732                assert_eq!(dt, date);
733
734                let dt = generate_date(year, 1, 1, 0, 0, 0);
735                let date = Date::parse("jan", "MONTH").unwrap();
736                assert_eq!(dt, date);
737
738                let dt = generate_date(year, 1, 1, 0, 0, 0);
739                let date = Date::parse("January", "mon").unwrap();
740                assert_eq!(dt, date);
741            }
742
743            // Absence of time
744            {
745                let dt = generate_date(2021, 12, 15, 0, 0, 0);
746                let date = Date::parse("2021-12-15", "yyyy-mm-dd hh24:mi:ss").unwrap();
747                assert_eq!(dt, date);
748
749                let dt = generate_date(2021, 12, 15, 0, 0, 0);
750                let date = Date::parse("2021-12-15", "yyyy-mm-dd hh24-mi-ss").unwrap();
751                assert_eq!(dt, date);
752
753                let dt = generate_date(2021, 12, 15, 11, 0, 0);
754                let date = Date::parse("2021-12-15 11", "yyyy-mm-dd hh24:mi:ss").unwrap();
755                assert_eq!(dt, date);
756
757                let dt = generate_date(2021, 12, 15, 11, 23, 0);
758                let date = Date::parse("2021-12-15 11:23", "yyyy-mm-dd hh24:mi:ss").unwrap();
759                assert_eq!(dt, date);
760
761                let dt = generate_date(2021, 12, 15, 0, 0, 0);
762                let date = Date::parse("2021-12-15", "yyyy-mm-dd hh:mi:ss").unwrap();
763                assert_eq!(dt, date);
764
765                let dt = generate_date(2021, 12, 15, 11, 0, 0);
766                let date = Date::parse("2021-12-15 11", "yyyy-mm-dd hh:mi:ss").unwrap();
767                assert_eq!(dt, date);
768
769                let dt = generate_date(2021, 12, 15, 11, 23, 0);
770                let date = Date::parse("2021-12-15 11:23", "yyyy-mm-dd hh:mi:ss").unwrap();
771                assert_eq!(dt, date);
772            }
773
774            // Can not absence of year\month\day
775            {
776                assert!(Date::parse("2022-4", "yyyy-mm-dd").is_err());
777            }
778
779            // Short format
780            {
781                let date = generate_date(1234, 8, 6, 7, 8, 9);
782                assert_eq!(format!("{}", date.format("YYYY").unwrap()), "1234");
783                assert_eq!(format!("{}", date.format("DD").unwrap()), "06");
784                assert_eq!(format!("{}", date.format("MON").unwrap()), "AUG");
785                assert_eq!(format!("{}", date.format("Mon").unwrap()), "Aug");
786                assert_eq!(format!("{}", date.format("mon").unwrap()), "aug");
787                assert_eq!(format!("{}", date.format("MONTH").unwrap()), "AUGUST");
788                assert_eq!(format!("{}", date.format("MONtH").unwrap()), "AUGUST");
789                assert_eq!(format!("{}", date.format("Month").unwrap()), "August");
790                assert_eq!(format!("{}", date.format("month").unwrap()), "august");
791                assert_eq!(format!("{}", date.format("WW").unwrap()), "32");
792                assert_eq!(format!("{}", date.format("W").unwrap()), "1");
793                assert_eq!(format!("{}", date.format("DAY").unwrap()), "SUNDAY");
794                assert_eq!(format!("{}", date.format("DAy").unwrap()), "SUNDAY");
795                assert_eq!(format!("{}", date.format("Day").unwrap()), "Sunday");
796                assert_eq!(format!("{}", date.format("DaY").unwrap()), "Sunday");
797                assert_eq!(format!("{}", date.format("day").unwrap()), "sunday");
798                assert_eq!(format!("{}", date.format("daY").unwrap()), "sunday");
799                assert_eq!(format!("{}", date.format("DY").unwrap()), "SUN");
800                assert_eq!(format!("{}", date.format("Dy").unwrap()), "Sun");
801                assert_eq!(format!("{}", date.format("dy").unwrap()), "sun");
802                assert_eq!(format!("{}", date.format("D").unwrap()), "1");
803                assert_eq!(format!("{}", date.format("DDD").unwrap()), "218");
804                assert_eq!(format!("{}", date.format("mi").unwrap()), "08");
805                assert_eq!(format!("{}", date.format("hh").unwrap()), "07");
806                assert_eq!(format!("{}", date.format("ss").unwrap()), "09");
807
808                let date = generate_date(1970, 1, 1, 7, 8, 9);
809                assert_eq!(format!("{}", date.format("day").unwrap()), "thursday");
810                assert_eq!(format!("{}", date.format("D").unwrap()), "5");
811                assert_eq!(format!("{}", date.format("DDD").unwrap()), "001");
812                assert_eq!(format!("{}", date.format("WW").unwrap()), "01");
813                assert_eq!(format!("{}", date.format("W").unwrap()), "1");
814
815                let date = generate_date(1970, 1, 2, 7, 8, 9);
816                assert_eq!(format!("{}", date.format("day").unwrap()), "friday");
817
818                let date = generate_date(1969, 12, 31, 7, 8, 9);
819                assert_eq!(format!("{}", date.format("day").unwrap()), "wednesday");
820                assert_eq!(format!("{}", date.format("D").unwrap()), "4");
821                assert_eq!(format!("{}", date.format("DDD").unwrap()), "365");
822                assert_eq!(format!("{}", date.format("WW").unwrap()), "53");
823                assert_eq!(format!("{}", date.format("W").unwrap()), "5");
824
825                let date = generate_date(1969, 10, 1, 7, 8, 9);
826                assert_eq!(format!("{}", date.format("day").unwrap()), "wednesday");
827
828                let date = generate_date(9999, 11, 14, 7, 8, 9);
829                assert_eq!(format!("{}", date.format("day").unwrap()), "sunday");
830            }
831
832            // Normal
833            {
834                let date = generate_date(2000, 1, 1, 0, 0, 0);
835                let fmt = format!("{}", date.format("yyyy-MONTH-dd hh:mi:ss").unwrap());
836                assert_eq!(fmt, "2000-JANUARY-01 12:00:00");
837
838                let fmt = format!("{}", date.format("yyyy-Mon-dd hh:mi:ss").unwrap());
839                assert_eq!(fmt, "2000-Jan-01 12:00:00");
840
841                let fmt = format!("{}", date.format("Day yyyy-Mon-dd hh:mi:ss").unwrap());
842                assert_eq!(fmt, "Saturday 2000-Jan-01 12:00:00");
843
844                let fmt = format!("{}", date.format("yyyyMMdd hh24miss").unwrap());
845                assert_eq!(fmt, "20000101 000000");
846
847                let date = generate_date(2001, 1, 2, 3, 4, 5);
848                assert_eq!(
849                    format!("{}", date.format("YYYYMMDDHHMISS").unwrap()),
850                    "20010102030405"
851                );
852
853                assert_eq!(
854                    date,
855                    Date::parse("20010102030405", "YYYYMMDDHHMISS").unwrap()
856                );
857
858                assert_eq!(
859                    date,
860                    Date::parse("2001012 030405", "YYYYMMDD HHMISS").unwrap()
861                );
862            }
863
864            // Day parse check
865            {
866                let date = generate_date(2021, 4, 22, 3, 4, 5);
867                let ts2 =
868                    Date::parse("2021-04-22 03:04:05 thu", "yyyy-mm-dd hh24:mi:ss dy").unwrap();
869                let ts3 = Date::parse("2021-04-22 03:04:05 5", "yyyy-mm-dd hh24:mi:ss d").unwrap();
870                assert_eq!(date, ts2);
871                assert_eq!(date, ts3);
872
873                let ts2 =
874                    Date::parse("2021-04-22 03:04:05 thu", "yyyy-mm-dd hh24:mi:ss dy").unwrap();
875                assert_eq!(date, ts2);
876
877                let ts2 = Date::parse("2021-04-22 03:04:05 thursday", "yyyy-mm-dd hh24:mi:ss day")
878                    .unwrap();
879                assert_eq!(date, ts2);
880
881                let ts2 =
882                    Date::parse("2021-04-22 03:04:05 thu", "yyyy-mm-dd hh24:mi:ss Dy").unwrap();
883                assert_eq!(date, ts2);
884
885                let ts2 =
886                    Date::parse("2021-04-22 03:04:05 Thu", "yyyy-mm-dd hh24:mi:ss dy").unwrap();
887                assert_eq!(date, ts2);
888
889                let date2 = Date::parse("2021 112 3:4:5", "yyyy ddd hh24:mi:ss").unwrap();
890                let date3 =
891                    Date::parse("2021-4-22 3:4:5 112", "yyyy-mm-dd hh24:mi:ss ddd").unwrap();
892                assert_eq!(date, date2);
893                assert_eq!(date, date3);
894
895                assert!(Date::parse("2022-6-21 112", "yyyy-mm-dd ddd").is_err());
896
897                assert!(
898                    Date::parse("2021-04-23 03:04:05 thu", "yyyy-mm-dd hh24:mi:ss dy").is_err()
899                );
900
901                assert!(Date::parse("2021-04-23 03:04:05 5", "yyyy-mm-dd hh24:mi:ss d").is_err());
902
903                assert!(Date::parse("2021-04-22 03:04:05 ", "yyyy-mm-dd hh24:mi:ss d",).is_err());
904            }
905
906            // Duplicate format
907            {
908                let date = generate_date(2021, 4, 25, 3, 4, 5);
909                assert_eq!(
910                    format!(
911                        "{}",
912                        date.format("DAY DaY DY D DDD W WW WW MM MM yyyy YYYY MI MI")
913                            .unwrap()
914                    ),
915                    "SUNDAY Sunday SUN 1 115 4 17 17 04 04 2021 2021 04 04"
916                );
917
918                assert_eq!(
919                    format!(
920                        "{}",
921                        date.format("DAYDaYDYDWWWWWDMMMMyyyyYYYYMIMIDDD").unwrap()
922                    ),
923                    "SUNDAYSundaySUN11717410404202120210404115"
924                );
925            }
926
927            // Invalid
928            {
929                // Parse
930                assert!(Date::parse("2021-04-22 03:04:05", "yyyy-mmX-dd hh24:mi:ss").is_err());
931
932                assert!(Date::parse("2021-04-22 03:04:05", "yyyy-mm-dd mi:ss").is_err());
933
934                assert!(Date::parse("2021-04-22 03:04:05", "yyy-mm-dd hh24:mi:ss").is_err());
935
936                assert!(Date::parse("2021-04-32 03:04:05", "yyyy-mm-dd mi:ss").is_err());
937
938                assert!(Date::parse("10000-04-31 03:04:05", "yyyy-mm-dd mi:ss").is_err());
939
940                assert!(Date::parse("10000-04-31 33:04:05", "yyyy-mm-dd mi:ss").is_err());
941
942                assert!(Date::parse("2021-04-22 03:04:05", "ABCD-mm-dd hh24:mi:ss").is_err());
943
944                assert!(
945                    Date::parse("2021-04-23 03:04:05 thu", "yyyy-mm-dd hh24:mi:ss dy").is_err()
946                );
947
948                assert!(
949                    Date::parse("2021-04-22 03:04:05.12345", "yyyy-mm-dd hh24:mi:ss.ff").is_err()
950                );
951
952                assert!(Date::parse("2021423 03:04:05", "yyyymmdd hh24:mi:ss").is_err());
953
954                assert!(Date::parse("2021423 03:04:05", "yyyymmdd hh24:mi:ss").is_err());
955
956                assert!(Date::parse("2021-04-23 03:04:05 4", "yyyy-mm-dd hh24:mi:ss w").is_err());
957
958                assert!(Date::parse("2021-04-23 03:04:05 17", "yyyy-mm-dd hh24:mi:ss ww").is_err());
959
960                let date = generate_date(1234, 5, 6, 7, 8, 9);
961                assert!(date.format("testtest").is_err());
962            }
963
964            // todo
965            // Wrong order of some specific Field, wrong format, extra format.
966        }
967    }
968
969    #[test]
970    fn test_date_truncate() {
971        assert_eq!(
972            Date::parse("9999-12-31T23:59:59.999999Z", "yyyy-mm-ddThh24:mi:ss.ff"),
973            Ok(Date::MAX),
974            "Should truncate for 6 digits",
975        );
976        assert_eq!(
977            Date::parse("9999-12-31T23:59:59.999999999Z", "yyyy-mm-ddThh24:mi:ss.ff"),
978            Ok(Date::MAX),
979            "Should truncate for 9 digits",
980        );
981        assert!(
982            Date::parse(
983                "9999-12-31T23:59:59.9999999999Z",
984                "yyyy-mm-ddThh24:mi:ss.ff"
985            )
986            .is_err(),
987            "Should error for >9 digits",
988        );
989    }
990
991    #[test]
992    fn test_date_to_sql_date_time() {
993        let date = generate_date(1, 1, 1, 0, 0, 0);
994        assert_eq!(date.date(), generate_sql_date(1, 1, 1));
995        assert_eq!(date.time(), generate_time(0, 0, 0, 0));
996
997        let date = generate_date(1, 1, 1, 23, 59, 59);
998        assert_eq!(date.date(), generate_sql_date(1, 1, 1));
999        assert_eq!(date.time(), generate_time(23, 59, 59, 0));
1000
1001        let date = generate_date(1969, 12, 30, 0, 0, 0);
1002        assert_eq!(date.date(), generate_sql_date(1969, 12, 30));
1003        assert_eq!(date.time(), generate_time(0, 0, 0, 0));
1004
1005        let date = generate_date(1969, 12, 30, 23, 59, 59);
1006        assert_eq!(date.date(), generate_sql_date(1969, 12, 30));
1007        assert_eq!(date.time(), generate_time(23, 59, 59, 0));
1008
1009        let date = generate_date(1969, 12, 31, 0, 0, 0);
1010        assert_eq!(date.date(), generate_sql_date(1969, 12, 31));
1011        assert_eq!(date.time(), generate_time(0, 0, 0, 0));
1012
1013        let date = generate_date(1969, 12, 31, 23, 59, 59);
1014        assert_eq!(date.date(), generate_sql_date(1969, 12, 31));
1015        assert_eq!(date.time(), generate_time(23, 59, 59, 0));
1016
1017        let date = generate_date(1970, 1, 1, 0, 0, 0);
1018        assert_eq!(date.date(), generate_sql_date(1970, 1, 1));
1019        assert_eq!(date.time(), generate_time(0, 0, 0, 0));
1020
1021        let date = generate_date(1970, 1, 1, 23, 59, 59);
1022        assert_eq!(date.date(), generate_sql_date(1970, 1, 1));
1023        assert_eq!(date.time(), generate_time(23, 59, 59, 0));
1024
1025        let date = generate_date(9999, 1, 1, 0, 0, 0);
1026        assert_eq!(date.date(), generate_sql_date(9999, 1, 1));
1027        assert_eq!(date.time(), generate_time(0, 0, 0, 0));
1028
1029        let date = generate_date(9999, 1, 1, 23, 59, 59);
1030        assert_eq!(date.date(), generate_sql_date(9999, 1, 1));
1031        assert_eq!(date.time(), generate_time(23, 59, 59, 0));
1032
1033        let date = generate_date(9999, 12, 31, 0, 0, 0);
1034        assert_eq!(date.date(), generate_sql_date(9999, 12, 31));
1035        assert_eq!(date.time(), generate_time(0, 0, 0, 0));
1036
1037        let date = generate_date(9999, 12, 31, 23, 59, 59);
1038        assert_eq!(date.date(), generate_sql_date(9999, 12, 31));
1039        assert_eq!(date.time(), generate_time(23, 59, 59, 0));
1040    }
1041
1042    #[test]
1043    fn test_date_add_sub_interval_dt() {
1044        // Normal add positive interval test
1045        let date = generate_date(2001, 3, 31, 12, 5, 6);
1046        let interval = IntervalDT::try_from_dhms(1, 2, 3, 4, 5).unwrap();
1047        let expect = generate_date(2001, 4, 1, 14, 8, 10);
1048        assert_eq!(date.add_interval_dt(interval).unwrap(), expect);
1049
1050        // Normal sub negative interval test
1051        let interval = -IntervalDT::try_from_dhms(1, 2, 3, 4, 5).unwrap();
1052        assert_eq!(date.sub_interval_dt(interval).unwrap(), expect);
1053
1054        // Add positive interval with carry test
1055        let date = generate_date(2001, 12, 31, 23, 59, 59);
1056        let interval = IntervalDT::try_from_dhms(0, 0, 0, 1, 1).unwrap();
1057        let expect = generate_date(2002, 1, 1, 0, 0, 0);
1058        assert_eq!(date.add_interval_dt(interval).unwrap(), expect);
1059
1060        // Sub negative interval with carry test
1061        let interval = -IntervalDT::try_from_dhms(0, 0, 0, 1, 1).unwrap();
1062        assert_eq!(date.sub_interval_dt(interval).unwrap(), expect);
1063
1064        // Normal add negative interval test
1065        let date = generate_date(2001, 3, 31, 12, 5, 6);
1066        let interval = -IntervalDT::try_from_dhms(1, 2, 3, 4, 5).unwrap();
1067        let expect = generate_date(2001, 3, 30, 10, 2, 1);
1068        assert_eq!(date.add_interval_dt(interval).unwrap(), expect);
1069
1070        // Normal sub positive interval test
1071        let interval = IntervalDT::try_from_dhms(1, 2, 3, 4, 5).unwrap();
1072        assert_eq!(date.sub_interval_dt(interval).unwrap(), expect);
1073
1074        // Add negative interval with carry test
1075        let date = generate_date(1970, 1, 1, 0, 0, 0);
1076        let interval = -IntervalDT::try_from_dhms(0, 0, 0, 0, 1).unwrap();
1077        let expect = generate_date(1969, 12, 31, 23, 59, 59);
1078        assert_eq!(date.add_interval_dt(interval).unwrap(), expect);
1079
1080        // Sub positive interval with carry test
1081        let interval = IntervalDT::try_from_dhms(0, 0, 0, 0, 1).unwrap();
1082        assert_eq!(date.sub_interval_dt(interval).unwrap(), expect);
1083
1084        // Boundary test
1085        let date = generate_date(9999, 12, 31, 23, 59, 59);
1086        let interval = IntervalDT::try_from_dhms(5, 4, 3, 2, 1).unwrap();
1087        let expect = generate_date(9999, 12, 26, 19, 56, 56);
1088        assert_eq!(date.sub_interval_dt(interval).unwrap(), expect);
1089
1090        let interval = IntervalDT::try_from_dhms(0, 0, 0, 1, 0).unwrap();
1091        assert!(date.add_interval_dt(interval).is_err());
1092
1093        let interval = IntervalDT::try_from_dhms(12345, 12, 3, 5, 6).unwrap();
1094        assert!(date.add_interval_dt(interval).is_err());
1095
1096        let date = generate_date(1, 1, 1, 0, 0, 0);
1097        let interval = IntervalDT::try_from_dhms(5, 4, 3, 2, 1).unwrap();
1098        let expect = generate_date(1, 1, 6, 4, 3, 2);
1099        assert_eq!(date.add_interval_dt(interval).unwrap(), expect);
1100
1101        let interval = IntervalDT::try_from_dhms(0, 0, 0, 0, 1).unwrap();
1102        assert!(date.sub_interval_dt(interval).is_err());
1103
1104        let interval = IntervalDT::try_from_dhms(12345, 12, 3, 5, 6).unwrap();
1105        assert!(date.sub_interval_dt(interval).is_err());
1106    }
1107
1108    #[test]
1109    fn test_date_add_sub_interval_ym() {
1110        // Add positive
1111        let date = generate_date(2001, 3, 31, 12, 5, 6);
1112        let interval = IntervalYM::try_from_ym(0, 2).unwrap();
1113        assert_eq!(
1114            date.add_interval_ym(interval).unwrap(),
1115            generate_date(2001, 5, 31, 12, 5, 6)
1116        );
1117
1118        let interval = IntervalYM::try_from_ym(1, 2).unwrap();
1119        assert_eq!(
1120            date.add_interval_ym(interval).unwrap(),
1121            generate_date(2002, 5, 31, 12, 5, 6)
1122        );
1123
1124        // Sub negative
1125        let date = generate_date(2001, 3, 31, 12, 5, 6);
1126        let interval = IntervalYM::try_from_ym(0, 2).unwrap();
1127        assert_eq!(
1128            date.sub_interval_ym(-interval).unwrap(),
1129            generate_date(2001, 5, 31, 12, 5, 6)
1130        );
1131
1132        let interval = IntervalYM::try_from_ym(1, 2).unwrap();
1133        assert_eq!(
1134            date.sub_interval_ym(-interval).unwrap(),
1135            generate_date(2002, 5, 31, 12, 5, 6)
1136        );
1137
1138        // Sub positive
1139        let interval = IntervalYM::try_from_ym(0, 2).unwrap();
1140        assert_eq!(
1141            date.sub_interval_ym(interval).unwrap(),
1142            generate_date(2001, 1, 31, 12, 5, 6)
1143        );
1144
1145        let interval = IntervalYM::try_from_ym(1, 2).unwrap();
1146        assert_eq!(
1147            date.sub_interval_ym(interval).unwrap(),
1148            generate_date(2000, 1, 31, 12, 5, 6)
1149        );
1150
1151        // Add negative
1152        let interval = IntervalYM::try_from_ym(0, 2).unwrap();
1153        assert_eq!(
1154            date.add_interval_ym(-interval).unwrap(),
1155            generate_date(2001, 1, 31, 12, 5, 6)
1156        );
1157
1158        let interval = IntervalYM::try_from_ym(1, 2).unwrap();
1159        assert_eq!(
1160            date.add_interval_ym(-interval).unwrap(),
1161            generate_date(2000, 1, 31, 12, 5, 6)
1162        );
1163
1164        // Boundary test
1165        let upper_date = generate_date(9999, 12, 31, 23, 59, 59);
1166        let lower_date = generate_date(1, 1, 1, 0, 0, 0);
1167        let interval = IntervalYM::try_from_ym(0, 1).unwrap();
1168
1169        assert!(upper_date.add_interval_ym(interval).is_err());
1170        assert!(lower_date.sub_interval_ym(interval).is_err());
1171
1172        // Month day overflow
1173        let interval = IntervalYM::try_from_ym(1, 1).unwrap();
1174        assert!(date.add_interval_ym(interval).is_err());
1175
1176        let interval = IntervalYM::try_from_ym(0, 11).unwrap();
1177        assert!(date.add_interval_ym(interval).is_err());
1178
1179        let interval = IntervalYM::try_from_ym(2, 11).unwrap();
1180        assert!(date.add_interval_ym(interval).is_err());
1181
1182        let interval = IntervalYM::try_from_ym(1, 1).unwrap();
1183        assert!(date.sub_interval_ym(-interval).is_err());
1184
1185        let interval = IntervalYM::try_from_ym(0, 11).unwrap();
1186        assert!(date.sub_interval_ym(-interval).is_err());
1187
1188        let interval = IntervalYM::try_from_ym(2, 11).unwrap();
1189        assert!(date.sub_interval_ym(-interval).is_err());
1190
1191        let interval = IntervalYM::try_from_ym(1, 1).unwrap();
1192        assert!(date.sub_interval_ym(interval).is_err());
1193
1194        let interval = IntervalYM::try_from_ym(0, 11).unwrap();
1195        assert!(date.sub_interval_ym(interval).is_err());
1196
1197        let interval = IntervalYM::try_from_ym(2, 1).unwrap();
1198        assert!(date.sub_interval_ym(interval).is_err());
1199
1200        let interval = IntervalYM::try_from_ym(2, 1).unwrap();
1201        assert!(date.sub_interval_ym(interval).is_err());
1202
1203        let interval = IntervalYM::try_from_ym(1, 1).unwrap();
1204        assert!(date.add_interval_ym(-interval).is_err());
1205
1206        let interval = IntervalYM::try_from_ym(0, 11).unwrap();
1207        assert!(date.add_interval_ym(-interval).is_err());
1208
1209        let interval = IntervalYM::try_from_ym(2, 1).unwrap();
1210        assert!(date.add_interval_ym(-interval).is_err());
1211    }
1212
1213    #[test]
1214    fn test_date_sub_date() {
1215        let upper_ts = generate_date(9999, 12, 31, 23, 59, 59);
1216        let lower_ts = generate_date(1, 1, 1, 0, 0, 0);
1217        let date = generate_date(5000, 6, 15, 12, 30, 30);
1218        dbg!(upper_ts.sub_date(lower_ts));
1219        dbg!(upper_ts.sub_date(date));
1220        dbg!(lower_ts.sub_date(upper_ts));
1221    }
1222
1223    #[test]
1224    fn test_date_sub_timestamp() {
1225        let upper_ts = generate_date(9999, 12, 31, 23, 59, 59);
1226        let lower_ts = generate_date(1, 1, 1, 0, 0, 0);
1227        let lower_timestamp = generate_ts(1, 1, 1, 0, 0, 0, 0);
1228        let upper_timestamp = generate_ts(9999, 12, 31, 23, 59, 59, 999999);
1229        let timestamp = generate_ts(5000, 6, 15, 12, 30, 30, 500000);
1230
1231        assert_eq!(
1232            upper_ts.sub_timestamp(lower_timestamp),
1233            IntervalDT::try_from_dhms(3652058, 23, 59, 59, 000000).unwrap()
1234        );
1235
1236        assert_eq!(
1237            upper_ts.sub_timestamp(timestamp),
1238            IntervalDT::try_from_dhms(1826046, 11, 29, 28, 500000).unwrap()
1239        );
1240
1241        assert_eq!(
1242            lower_ts.sub_timestamp(upper_timestamp),
1243            -IntervalDT::try_from_dhms(3652058, 23, 59, 59, 999999).unwrap()
1244        );
1245    }
1246
1247    #[test]
1248    fn test_date_add_sub_days() {
1249        let upper_ts = generate_date(9999, 12, 31, 23, 59, 59);
1250        let lower_ts = generate_date(1, 1, 1, 0, 0, 0);
1251
1252        // Out of range
1253        assert!(lower_ts.add_days(213435445784784.13).is_err());
1254        assert!(lower_ts.add_days(f64::NAN).is_err());
1255        assert!(lower_ts.add_days(f64::INFINITY).is_err());
1256        assert!(lower_ts.add_days(f64::NEG_INFINITY).is_err());
1257        assert!(lower_ts.add_days(f64::MAX).is_err());
1258        assert!(lower_ts.add_days(f64::MIN).is_err());
1259        assert!(upper_ts.add_days(0.0001).is_err());
1260
1261        assert!(lower_ts.sub_days(213435445784784.13).is_err());
1262        assert!(lower_ts.sub_days(f64::NAN).is_err());
1263        assert!(lower_ts.sub_days(f64::INFINITY).is_err());
1264        assert!(lower_ts.sub_days(f64::NEG_INFINITY).is_err());
1265        assert!(lower_ts.sub_days(f64::MAX).is_err());
1266        assert!(lower_ts.sub_days(f64::MIN).is_err());
1267        assert!(lower_ts.sub_days(0.0001).is_err());
1268
1269        // Round
1270        assert_eq!(
1271            lower_ts.add_days(1.123456789).unwrap(),
1272            generate_date(1, 1, 2, 2, 57, 47)
1273        );
1274        assert_eq!(
1275            upper_ts.sub_days(1.123456789).unwrap(),
1276            generate_date(9999, 12, 30, 21, 2, 12)
1277        );
1278
1279        // Normal
1280        assert_eq!(upper_ts.sub_days(0.0).unwrap(), upper_ts);
1281        assert_eq!(upper_ts.add_days(0.0).unwrap(), upper_ts);
1282        assert_eq!(
1283            upper_ts.sub_days(1.0).unwrap(),
1284            generate_date(9999, 12, 30, 23, 59, 59)
1285        );
1286        assert_eq!(
1287            lower_ts.add_days(1.0).unwrap(),
1288            generate_date(1, 1, 2, 0, 0, 0)
1289        );
1290
1291        let date = generate_date(5000, 6, 15, 12, 30, 30);
1292        assert_eq!(
1293            date.sub_days(1.12).unwrap(),
1294            generate_date(5000, 6, 14, 9, 37, 42)
1295        );
1296        assert_eq!(
1297            date.add_days(1.12).unwrap(),
1298            generate_date(5000, 6, 16, 15, 23, 18)
1299        );
1300        assert_eq!(date.sub_days(1.12).unwrap(), date.add_days(-1.12).unwrap());
1301        assert_eq!(date.sub_days(-1.12).unwrap(), date.add_days(1.12).unwrap());
1302    }
1303
1304    #[test]
1305    fn test_date_cmp_timestamp() {
1306        let date = generate_date(1970, 1, 1, 1, 1, 1);
1307        let timestamp = generate_ts(1971, 1, 1, 12, 4, 5, 0);
1308        assert!(date < timestamp);
1309        let date = generate_date(1971, 1, 1, 12, 4, 5);
1310        assert!(date == timestamp);
1311    }
1312
1313    #[allow(clippy::float_cmp)]
1314    fn test_extract(year: i32, month: u32, day: u32, hour: u32, min: u32, sec: u32) {
1315        let date = generate_date(year, month, day, hour, min, sec);
1316        assert_eq!(year, date.year().unwrap());
1317        assert_eq!(month as i32, date.month().unwrap());
1318        assert_eq!(day as i32, date.day().unwrap());
1319        assert_eq!(hour as i32, date.hour().unwrap());
1320        assert_eq!(min as i32, date.minute().unwrap());
1321        assert_eq!(sec as f64, date.second().unwrap());
1322    }
1323
1324    #[test]
1325    fn test_timestamp_extract() {
1326        test_extract(1960, 12, 31, 23, 59, 59);
1327        test_extract(1, 1, 1, 0, 0, 0);
1328        test_extract(1, 1, 1, 1, 1, 1);
1329        test_extract(1969, 12, 31, 1, 2, 3);
1330        test_extract(1969, 12, 30, 23, 59, 59);
1331        test_extract(1969, 12, 30, 0, 0, 0);
1332        test_extract(1970, 1, 1, 0, 0, 0);
1333        test_extract(1970, 1, 1, 12, 30, 30);
1334        test_extract(1999, 10, 21, 12, 30, 30);
1335        test_extract(9999, 12, 31, 23, 59, 59);
1336    }
1337
1338    #[test]
1339    fn test_from_timestamp() {
1340        let timestamp = generate_ts(1969, 12, 31, 23, 0, 0, 0);
1341        assert_eq!(Date::from(timestamp), generate_date(1969, 12, 31, 23, 0, 0));
1342
1343        let timestamp = generate_ts(1970, 1, 1, 0, 0, 0, 0);
1344        assert_eq!(Date::from(timestamp), generate_date(1970, 1, 1, 0, 0, 0));
1345
1346        let timestamp = generate_ts(1969, 12, 30, 0, 0, 1, 0);
1347        assert_eq!(Date::from(timestamp), generate_date(1969, 12, 30, 0, 0, 1));
1348
1349        let timestamp = generate_ts(1969, 12, 31, 0, 0, 0, 0);
1350        assert_eq!(Date::from(timestamp), generate_date(1969, 12, 31, 0, 0, 0));
1351
1352        let timestamp = generate_ts(1970, 1, 1, 0, 0, 1, 0);
1353        assert_eq!(Date::from(timestamp), generate_date(1970, 1, 1, 0, 0, 1));
1354
1355        let timestamp = generate_ts(9999, 12, 31, 23, 59, 59, 0);
1356        assert_eq!(
1357            Date::from(timestamp),
1358            generate_date(9999, 12, 31, 23, 59, 59)
1359        );
1360
1361        let timestamp = generate_ts(1, 1, 1, 0, 0, 0, 0);
1362        assert_eq!(Date::from(timestamp), generate_date(1, 1, 1, 0, 0, 0));
1363
1364        let timestamp = generate_ts(1, 1, 1, 0, 0, 0, 1);
1365        assert_eq!(Date::from(timestamp), generate_date(1, 1, 1, 0, 0, 0));
1366
1367        let timestamp = generate_ts(1, 1, 1, 0, 0, 0, 999999);
1368        assert_eq!(Date::from(timestamp), generate_date(1, 1, 1, 0, 0, 0));
1369
1370        let timestamp = generate_ts(2000, 1, 1, 0, 0, 0, 999999);
1371        assert_eq!(Date::from(timestamp), generate_date(2000, 1, 1, 0, 0, 0));
1372
1373        let timestamp = generate_ts(2000, 1, 1, 0, 0, 0, 1);
1374        assert_eq!(Date::from(timestamp), generate_date(2000, 1, 1, 0, 0, 0));
1375    }
1376
1377    #[test]
1378    fn test_timestamp_sub_date() {
1379        let upper_ts = generate_ts(9999, 12, 31, 23, 59, 59, 999999);
1380        let lower_ts = generate_ts(1, 1, 1, 0, 0, 0, 0);
1381        let upper_date = generate_date(9999, 12, 31, 23, 59, 59);
1382        let lower_date = generate_date(1, 1, 1, 0, 0, 0);
1383        let date = generate_date(5000, 6, 15, 12, 30, 30);
1384
1385        assert_eq!(
1386            upper_ts.oracle_sub_date(lower_date),
1387            IntervalDT::try_from_dhms(3652058, 23, 59, 59, 999999).unwrap()
1388        );
1389
1390        assert_eq!(
1391            upper_ts.oracle_sub_date(date),
1392            IntervalDT::try_from_dhms(1826046, 11, 29, 29, 999999).unwrap()
1393        );
1394
1395        assert_eq!(
1396            lower_ts.oracle_sub_date(upper_date),
1397            -IntervalDT::try_from_dhms(3652058, 23, 59, 59, 0).unwrap()
1398        );
1399    }
1400
1401    #[test]
1402    fn test_timestamp_add_sub_days() {
1403        let upper_ts = generate_ts(9999, 12, 31, 23, 59, 59, 999999);
1404        let lower_ts = generate_ts(1, 1, 1, 0, 0, 0, 0);
1405        let upper_date = generate_date(9999, 12, 31, 23, 59, 59);
1406
1407        // Out of range
1408        assert!(lower_ts.oracle_add_days(213435445784784.13).is_err());
1409        assert!(lower_ts.oracle_add_days(f64::NAN).is_err());
1410        assert!(lower_ts.oracle_add_days(f64::INFINITY).is_err());
1411        assert!(lower_ts.oracle_add_days(f64::NEG_INFINITY).is_err());
1412        assert!(lower_ts.oracle_add_days(f64::MAX).is_err());
1413        assert!(lower_ts.oracle_add_days(f64::MIN).is_err());
1414        assert!(upper_ts.oracle_add_days(0.0001).is_err());
1415
1416        assert!(lower_ts.oracle_sub_days(213435445784784.13).is_err());
1417        assert!(lower_ts.oracle_sub_days(f64::NAN).is_err());
1418        assert!(lower_ts.oracle_sub_days(f64::INFINITY).is_err());
1419        assert!(lower_ts.oracle_sub_days(f64::NEG_INFINITY).is_err());
1420        assert!(lower_ts.oracle_sub_days(f64::MAX).is_err());
1421        assert!(lower_ts.oracle_sub_days(f64::MIN).is_err());
1422        assert!(lower_ts.oracle_sub_days(0.0001).is_err());
1423
1424        // Round
1425        assert_eq!(
1426            lower_ts.oracle_add_days(1.123456789).unwrap(),
1427            generate_date(1, 1, 2, 2, 57, 47)
1428        );
1429        assert_eq!(
1430            lower_ts.oracle_add_days(0.0000104).unwrap(),
1431            generate_date(1, 1, 1, 0, 0, 1)
1432        );
1433        assert_eq!(
1434            upper_ts.oracle_sub_days(1.123456789).unwrap(),
1435            generate_date(9999, 12, 30, 21, 2, 12)
1436        );
1437
1438        // Normal
1439        assert_eq!(upper_ts.oracle_sub_days(0.0).unwrap(), upper_date);
1440        assert_eq!(upper_ts.oracle_add_days(0.0).unwrap(), upper_date);
1441        assert_eq!(
1442            upper_ts.oracle_sub_days(1.0).unwrap(),
1443            generate_date(9999, 12, 30, 23, 59, 59)
1444        );
1445        assert_eq!(
1446            lower_ts.add_days(1.0).unwrap(),
1447            generate_date(1, 1, 2, 0, 0, 0)
1448        );
1449
1450        let ts = generate_ts(5000, 6, 15, 12, 30, 30, 555555);
1451        assert_eq!(
1452            ts.oracle_sub_days(1.12).unwrap(),
1453            generate_date(5000, 6, 14, 9, 37, 42)
1454        );
1455        assert_eq!(
1456            ts.oracle_sub_days(1.12).unwrap(),
1457            ts.oracle_add_days(-1.12).unwrap()
1458        );
1459        assert_eq!(
1460            ts.oracle_add_days(1.12).unwrap(),
1461            generate_date(5000, 6, 16, 15, 23, 18)
1462        );
1463        assert_eq!(
1464            ts.oracle_sub_days(-1.12).unwrap(),
1465            ts.oracle_add_days(1.12).unwrap()
1466        );
1467
1468        let ts = generate_ts(1, 1, 1, 0, 0, 0, 8);
1469        assert_eq!(
1470            ts.oracle_add_days(0.00000578).unwrap(),
1471            generate_date(1, 1, 1, 0, 0, 0)
1472        );
1473
1474        let ts = generate_ts(1971, 1, 1, 0, 0, 0, 8);
1475        assert_eq!(
1476            ts.oracle_add_days(0.00000578).unwrap(),
1477            generate_date(1971, 1, 1, 0, 0, 0)
1478        );
1479    }
1480
1481    #[test]
1482    fn test_oracle_date_add_sub_time() {
1483        assert!(Date::MAX
1484            .add_time(generate_time(23, 59, 59, 12345))
1485            .is_err());
1486
1487        assert!(Date::MIN
1488            .sub_time(generate_time(23, 59, 59, 12345))
1489            .is_err());
1490
1491        assert_eq!(
1492            Date::MAX.sub_time(generate_time(1, 2, 3, 4)).unwrap(),
1493            generate_ts(9999, 12, 31, 22, 57, 55, 999996)
1494        );
1495
1496        assert_eq!(
1497            generate_date(2000, 10, 2, 3, 4, 5)
1498                .sub_time(generate_time(23, 5, 6, 7))
1499                .unwrap(),
1500            generate_ts(2000, 10, 1, 3, 58, 58, 999993)
1501        );
1502
1503        assert_eq!(
1504            Date::MIN.add_time(generate_time(1, 2, 3, 4)).unwrap(),
1505            generate_ts(1, 1, 1, 1, 2, 3, 4)
1506        );
1507
1508        assert_eq!(
1509            generate_date(2000, 10, 2, 3, 4, 5)
1510                .add_time(generate_time(23, 5, 6, 7))
1511                .unwrap(),
1512            generate_ts(2000, 10, 3, 2, 9, 11, 7)
1513        );
1514    }
1515
1516    #[test]
1517    fn test_now() {
1518        let now = Local::now();
1519        let dt = Date::now().unwrap();
1520        assert_eq!(now.year(), dt.year().unwrap());
1521        assert_eq!(now.month() as i32, dt.month().unwrap());
1522        assert_eq!(now.day() as i32, dt.day().unwrap());
1523        assert_eq!(now.hour() as i32, dt.hour().unwrap());
1524    }
1525
1526    #[test]
1527    fn test_trunc() {
1528        let dt = generate_date(1996, 10, 24, 0, 0, 0);
1529
1530        assert_eq!(
1531            generate_date(1901, 1, 1, 0, 0, 0),
1532            dt.trunc_century().unwrap()
1533        );
1534        assert_eq!(generate_date(1996, 1, 1, 0, 0, 0), dt.trunc_year().unwrap());
1535        assert_eq!(
1536            generate_date(1996, 1, 1, 0, 0, 0),
1537            dt.trunc_iso_year().unwrap()
1538        );
1539        assert_eq!(
1540            generate_date(1996, 10, 1, 0, 0, 0),
1541            dt.trunc_quarter().unwrap()
1542        );
1543        assert_eq!(
1544            generate_date(1996, 10, 1, 0, 0, 0),
1545            dt.trunc_month().unwrap()
1546        );
1547        assert_eq!(
1548            generate_date(1996, 10, 21, 0, 0, 0),
1549            dt.trunc_week().unwrap()
1550        );
1551        assert_eq!(
1552            generate_date(1996, 10, 21, 0, 0, 0),
1553            dt.trunc_iso_week().unwrap()
1554        );
1555        assert_eq!(
1556            generate_date(1996, 10, 22, 0, 0, 0),
1557            dt.trunc_month_start_week().unwrap()
1558        );
1559        assert_eq!(
1560            generate_date(1996, 10, 24, 0, 0, 0),
1561            dt.trunc_day().unwrap()
1562        );
1563        assert_eq!(
1564            generate_date(1996, 10, 20, 0, 0, 0),
1565            dt.trunc_sunday_start_week().unwrap()
1566        );
1567        assert_eq!(
1568            generate_date(2015, 4, 11, 13, 0, 0),
1569            generate_date(2015, 4, 11, 13, 59, 59).trunc_hour().unwrap()
1570        );
1571        assert_eq!(
1572            generate_date(2015, 4, 11, 13, 59, 0),
1573            generate_date(2015, 4, 11, 13, 59, 59)
1574                .trunc_minute()
1575                .unwrap()
1576        );
1577    }
1578
1579    #[test]
1580    fn test_round() {
1581        let dt = generate_date(1996, 10, 24, 0, 0, 0);
1582
1583        assert_eq!(
1584            generate_date(2001, 1, 1, 0, 0, 0),
1585            dt.round_century().unwrap()
1586        );
1587        assert_eq!(generate_date(1997, 1, 1, 0, 0, 0), dt.round_year().unwrap());
1588        assert_eq!(
1589            generate_date(1996, 12, 30, 0, 0, 0),
1590            dt.round_iso_year().unwrap()
1591        );
1592        assert_eq!(
1593            generate_date(1996, 10, 1, 0, 0, 0),
1594            dt.round_quarter().unwrap()
1595        );
1596        assert_eq!(
1597            generate_date(2022, 1, 1, 0, 0, 0),
1598            generate_date(2021, 11, 16, 0, 0, 0)
1599                .round_quarter()
1600                .unwrap()
1601        );
1602        assert_eq!(
1603            generate_date(1996, 11, 1, 0, 0, 0),
1604            dt.round_month().unwrap()
1605        );
1606        assert_eq!(
1607            generate_date(2021, 10, 15, 0, 0, 0),
1608            generate_date(2021, 10, 13, 0, 0, 0).round_week().unwrap()
1609        );
1610        assert_eq!(
1611            generate_date(2021, 10, 18, 0, 0, 0),
1612            generate_date(2021, 10, 15, 0, 0, 0)
1613                .round_iso_week()
1614                .unwrap()
1615        );
1616        assert_eq!(
1617            generate_date(2021, 11, 8, 0, 0, 0),
1618            generate_date(2021, 11, 5, 0, 0, 0)
1619                .round_month_start_week()
1620                .unwrap()
1621        );
1622        assert_eq!(
1623            generate_date(1996, 10, 25, 0, 0, 0),
1624            generate_date(1996, 10, 24, 12, 0, 0).round_day().unwrap()
1625        );
1626        assert_eq!(
1627            generate_date(1996, 10, 27, 0, 0, 0),
1628            dt.round_sunday_start_week().unwrap()
1629        );
1630        assert_eq!(
1631            generate_date(2015, 3, 3, 12, 0, 0),
1632            generate_date(2015, 3, 3, 11, 30, 59).round_hour().unwrap()
1633        );
1634        assert_eq!(
1635            generate_date(2015, 3, 4, 0, 0, 0),
1636            generate_date(2015, 3, 3, 23, 30, 0).round_hour().unwrap()
1637        );
1638        assert_eq!(
1639            generate_date(2015, 3, 3, 11, 30, 0),
1640            generate_date(2015, 3, 3, 11, 29, 30)
1641                .round_minute()
1642                .unwrap()
1643        );
1644        assert_eq!(
1645            generate_date(2015, 3, 4, 0, 0, 0),
1646            generate_date(2015, 3, 3, 23, 59, 30)
1647                .round_minute()
1648                .unwrap()
1649        );
1650    }
1651
1652    #[test]
1653    fn test_last_day_of_month() {
1654        assert_eq!(
1655            generate_date(2021, 9, 23, 14, 15, 16).last_day_of_month(),
1656            generate_date(2021, 9, 30, 14, 15, 16)
1657        );
1658        assert_eq!(
1659            generate_date(1970, 1, 1, 0, 0, 0).last_day_of_month(),
1660            generate_date(1970, 1, 31, 0, 0, 0)
1661        );
1662        assert_eq!(
1663            generate_date(1704, 2, 1, 23, 59, 59).last_day_of_month(),
1664            generate_date(1704, 2, 29, 23, 59, 59)
1665        );
1666        assert_eq!(
1667            generate_date(1705, 2, 10, 5, 6, 7).last_day_of_month(),
1668            generate_date(1705, 2, 28, 5, 6, 7)
1669        );
1670        assert_eq!(
1671            generate_date(1, 1, 1, 0, 0, 0).last_day_of_month(),
1672            generate_date(1, 1, 31, 0, 0, 0)
1673        );
1674        assert_eq!(
1675            generate_date(9999, 12, 31, 23, 59, 59).last_day_of_month(),
1676            generate_date(9999, 12, 31, 23, 59, 59)
1677        );
1678    }
1679
1680    #[test]
1681    fn test_months_between() {
1682        assert_eq!(
1683            generate_date(1, 2, 1, 0, 0, 0).months_between(generate_date(1, 1, 1, 0, 0, 0)),
1684            (1, 0)
1685        );
1686        assert_eq!(
1687            generate_date(1, 2, 1, 23, 0, 0).months_between(generate_date(1, 1, 1, 0, 0, 0)),
1688            (1, 0)
1689        );
1690        assert_eq!(
1691            generate_date(1, 2, 1, 0, 0, 0).months_between(generate_date(1, 1, 1, 0, 0, 0)),
1692            (1, 0)
1693        );
1694        assert_eq!(
1695            generate_date(1, 3, 1, 0, 0, 0).months_between(generate_date(1, 2, 28, 0, 0, 0)),
1696            (0, 4 * USECONDS_PER_DAY)
1697        );
1698        assert_eq!(
1699            generate_date(1, 3, 31, 0, 0, 0).months_between(generate_date(1, 2, 28, 0, 0, 0)),
1700            (1, 0)
1701        );
1702        assert_eq!(
1703            generate_date(1, 3, 31, 23, 0, 0).months_between(generate_date(1, 2, 28, 0, 0, 0)),
1704            (1, 0)
1705        );
1706        assert_eq!(
1707            generate_date(1, 2, 2, 0, 0, 0).months_between(generate_date(1, 2, 1, 23, 0, 0)),
1708            (0, USECONDS_PER_HOUR)
1709        );
1710        assert_eq!(
1711            generate_date(1, 3, 2, 0, 0, 0).months_between(generate_date(1, 2, 1, 23, 0, 0)),
1712            (1, USECONDS_PER_HOUR)
1713        );
1714        assert_eq!(
1715            generate_date(1, 3, 1, 23, 0, 0).months_between(generate_date(1, 2, 2, 0, 0, 0)),
1716            (0, 30 * USECONDS_PER_DAY + 23 * USECONDS_PER_HOUR)
1717        );
1718    }
1719
1720    #[test]
1721    fn test_iso_format() {
1722        const FMT: &str = "YYYY-MM-DDTHH24:MI:SS.FF";
1723        fn assert_iso_fmt(input: &str, output: &str) {
1724            let date = Date::parse(input, FMT).unwrap();
1725            assert_eq!(format!("{}", date.format(FMT).unwrap()), output);
1726        }
1727
1728        fn assert_invalid_iso_str(input: &str) {
1729            assert!(Date::parse(input, FMT).is_err());
1730        }
1731
1732        assert_iso_fmt("2023-05-26", "2023-05-26T00:00:00");
1733        assert_iso_fmt("2023-05-26 ", "2023-05-26T00:00:00");
1734        assert_iso_fmt("2023-05-26T00:00:00", "2023-05-26T00:00:00");
1735        assert_iso_fmt("2023-05-26T00:00:00.000", "2023-05-26T00:00:00");
1736        assert_iso_fmt("2023-05-26T00:00:00.999999", "2023-05-26T00:00:00");
1737        assert_iso_fmt("2023-05-26T00:00:00.123456789", "2023-05-26T00:00:00");
1738        assert_iso_fmt("2023-05-26T00:00:00Z", "2023-05-26T00:00:00");
1739        assert_iso_fmt("2023-05-26T00:00:00.123Z", "2023-05-26T00:00:00");
1740
1741        assert_invalid_iso_str("2023-05");
1742        assert_invalid_iso_str("2023-05-26.123");
1743        assert_invalid_iso_str("2023-05-26T00");
1744        assert_invalid_iso_str("2023-05-26T00:00");
1745        assert_invalid_iso_str("2023-05-26T00:00:");
1746        assert_invalid_iso_str("2023-05-26T00:00.123");
1747        assert_invalid_iso_str("2023-05Z");
1748        assert_invalid_iso_str("2023-05-26Z");
1749        assert_invalid_iso_str("2023-05-26T00Z");
1750        assert_invalid_iso_str("2023-05-26T00:00Z");
1751        assert_invalid_iso_str("2023-05-26T00:00:Z");
1752        assert_invalid_iso_str("2023-05-26T00:00.123Z");
1753    }
1754}