sqldatetime/
timestamp.rs

1//! Timestamp implementation.
2
3use crate::common::*;
4use crate::error::{Error, Result};
5use crate::format::{Formatter, LazyFormat, NaiveDateTime};
6use crate::local::Local;
7use crate::{Date, DateTime, IntervalDT, IntervalYM, Round, Time, Trunc};
8use std::cmp::Ordering;
9use std::convert::TryFrom;
10use std::fmt::Display;
11
12/// Timestamp represents a valid time at a valid Gregorian date.
13///
14/// This is an SQL `TIMESTAMP` value, with the specification of fractional seconds to a precision of microseconds.
15#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
16#[repr(transparent)]
17pub struct Timestamp(i64);
18
19impl Timestamp {
20    /// The smallest timestamp that can be represented by `Date`, i.e. `0001-01-01 00:00:00.000000`.
21    pub const MIN: Self = Timestamp::new(Date::MIN, Time::ZERO);
22
23    /// The largest timestamp that can be represented by `Date`, i.e. `9999-12-31 23:59:59.999999`.
24    pub const MAX: Self = Timestamp::new(Date::MAX, Time::MAX);
25
26    /// Creates a new `Timestamp` from a date and a time.
27    #[inline]
28    pub const fn new(date: Date, time: Time) -> Self {
29        let usecs = date.days() as i64 * USECONDS_PER_DAY + time.usecs();
30        Timestamp(usecs)
31    }
32
33    /// Extracts `(Date, Time)` from the timestamp.
34    #[inline]
35    pub const fn extract(self) -> (Date, Time) {
36        let (date, time) = if self.0.is_negative() {
37            let temp_time = self.0 % USECONDS_PER_DAY;
38            if temp_time.is_negative() {
39                (self.0 / USECONDS_PER_DAY - 1, temp_time + USECONDS_PER_DAY)
40            } else {
41                (self.0 / USECONDS_PER_DAY, temp_time)
42            }
43        } else {
44            (self.0 / USECONDS_PER_DAY, self.0 % USECONDS_PER_DAY)
45        };
46
47        unsafe {
48            (
49                Date::from_days_unchecked(date as i32),
50                Time::from_usecs_unchecked(time),
51            )
52        }
53    }
54
55    #[inline]
56    pub(crate) fn date(self) -> Date {
57        let date = if self.0.is_negative() && self.0 % USECONDS_PER_DAY != 0 {
58            self.0 / USECONDS_PER_DAY - 1
59        } else {
60            self.0 / USECONDS_PER_DAY
61        };
62        unsafe { Date::from_days_unchecked(date as i32) }
63    }
64
65    #[inline]
66    pub(crate) fn time(self) -> Time {
67        let temp_time = self.0 % USECONDS_PER_DAY;
68        if temp_time.is_negative() {
69            unsafe { Time::from_usecs_unchecked(temp_time + USECONDS_PER_DAY) }
70        } else {
71            unsafe { Time::from_usecs_unchecked(temp_time) }
72        }
73    }
74
75    /// Gets the microseconds from Unix Epoch of `Timestamp`.
76    #[inline(always)]
77    pub const fn usecs(self) -> i64 {
78        self.0
79    }
80
81    /// Creates a `Timestamp` from the given microseconds from Unix Epoch without checking validity.
82    ///
83    /// # Safety
84    /// This function is unsafe because the microsecond value is not checked for validity!
85    /// Before using it, check that the value is correct.
86    #[inline(always)]
87    pub const unsafe fn from_usecs_unchecked(usecs: i64) -> Self {
88        Timestamp(usecs)
89    }
90
91    /// Formats `Timestamp` by given format string.
92    #[inline]
93    pub fn format<S: AsRef<str>>(self, fmt: S) -> Result<impl Display> {
94        let fmt = Formatter::try_new(fmt)?;
95        Ok(LazyFormat::new(fmt, self))
96    }
97
98    /// Parses `Timestamp` from given string and format.
99    #[inline]
100    pub fn parse<S1: AsRef<str>, S2: AsRef<str>>(input: S1, fmt: S2) -> Result<Self> {
101        let fmt = Formatter::try_new(fmt)?;
102        fmt.parse(input)
103    }
104
105    /// Creates a `Timestamp` from the given microseconds from Unix Epoch
106    #[inline]
107    pub const fn try_from_usecs(usecs: i64) -> Result<Self> {
108        if is_valid_timestamp(usecs) {
109            Ok(unsafe { Timestamp::from_usecs_unchecked(usecs) })
110        } else {
111            Err(Error::DateOutOfRange)
112        }
113    }
114
115    /// `Timestamp` adds `IntervalDT`
116    #[inline]
117    pub const fn add_interval_dt(self, interval: IntervalDT) -> Result<Timestamp> {
118        let result = self.usecs().checked_add(interval.usecs());
119        match result {
120            Some(ts) => Timestamp::try_from_usecs(ts),
121            None => Err(Error::DateOutOfRange),
122        }
123    }
124
125    /// `Timestamp` adds `IntervalYM`
126    #[inline]
127    pub fn add_interval_ym(self, interval: IntervalYM) -> Result<Timestamp> {
128        let (date, time) = self.extract();
129
130        Ok(Timestamp::new(
131            date.add_interval_ym_internal(interval)?,
132            time,
133        ))
134    }
135
136    /// `Timestamp` add `Time`
137    #[inline]
138    pub const fn add_time(self, time: Time) -> Result<Timestamp> {
139        Timestamp::try_from_usecs(self.usecs() + time.usecs())
140    }
141
142    /// `Timestamp` add days
143    #[inline]
144    pub fn add_days(self, days: f64) -> Result<Timestamp> {
145        let microseconds = (days * USECONDS_PER_DAY as f64).round();
146        if microseconds.is_infinite() {
147            Err(Error::NumericOverflow)
148        } else if microseconds.is_nan() {
149            Err(Error::InvalidNumber)
150        } else {
151            let result = self.usecs().checked_add(microseconds as i64);
152            match result {
153                Some(d) => Timestamp::try_from_usecs(d),
154                None => Err(Error::DateOutOfRange),
155            }
156        }
157    }
158
159    /// `Timestamp` subtracts `Date`
160    #[inline]
161    pub const fn sub_date(self, date: Date) -> IntervalDT {
162        let temp_timestamp = date.and_zero_time();
163        self.sub_timestamp(temp_timestamp)
164    }
165
166    /// `Timestamp` subtracts `Time`
167    #[inline]
168    pub const fn sub_time(self, time: Time) -> Result<Timestamp> {
169        Timestamp::try_from_usecs(self.usecs() - time.usecs())
170    }
171
172    /// `Timestamp` subtracts `Timestamp`
173    #[inline]
174    pub const fn sub_timestamp(self, timestamp: Timestamp) -> IntervalDT {
175        let microseconds = self.usecs() - timestamp.usecs();
176        unsafe { IntervalDT::from_usecs_unchecked(microseconds) }
177    }
178
179    /// `Timestamp` subtracts `IntervalDT`
180    #[inline]
181    pub const fn sub_interval_dt(self, interval: IntervalDT) -> Result<Timestamp> {
182        self.add_interval_dt(interval.negate())
183    }
184
185    /// `Timestamp` subtracts `IntervalYM`
186    #[inline]
187    pub fn sub_interval_ym(self, interval: IntervalYM) -> Result<Timestamp> {
188        self.add_interval_ym(interval.negate())
189    }
190
191    /// `Timestamp` subtracts days
192    #[inline]
193    pub fn sub_days(self, days: f64) -> Result<Timestamp> {
194        self.add_days(-days)
195    }
196
197    /// Get local system timestamp
198    #[inline]
199    pub fn now() -> Result<Timestamp> {
200        let now = Local::now();
201        Ok(Timestamp::new(
202            Date::try_from_ymd(now.year(), now.month(), now.day())?,
203            Time::try_from_hms(now.hour(), now.minute(), now.second(), now.usec())?,
204        ))
205    }
206
207    /// Gets the last day in month of `Timestamp`.
208    #[inline]
209    pub fn last_day_of_month(self) -> Timestamp {
210        let (sqldate, _) = self.extract();
211        let (year, month, day) = sqldate.extract();
212
213        let result_day = days_of_month(year, month);
214        let result = self.usecs() + (result_day - day) as i64 * USECONDS_PER_DAY;
215
216        unsafe { Timestamp::from_usecs_unchecked(result) }
217    }
218}
219
220impl Trunc for Timestamp {
221    #[inline]
222    fn trunc_century(self) -> Result<Self> {
223        Ok(self.date().trunc_century()?.and_zero_time())
224    }
225
226    #[inline]
227    fn trunc_year(self) -> Result<Self> {
228        Ok(self.date().trunc_year()?.and_zero_time())
229    }
230
231    #[inline]
232    fn trunc_iso_year(self) -> Result<Self> {
233        Ok(self.date().trunc_iso_year()?.and_zero_time())
234    }
235
236    #[inline]
237    fn trunc_quarter(self) -> Result<Self> {
238        Ok(self.date().trunc_quarter()?.and_zero_time())
239    }
240
241    #[inline]
242    fn trunc_month(self) -> Result<Self> {
243        Ok(self.date().trunc_month()?.and_zero_time())
244    }
245
246    #[inline]
247    fn trunc_week(self) -> Result<Self> {
248        Ok(self.date().trunc_week()?.and_zero_time())
249    }
250
251    #[inline]
252    fn trunc_iso_week(self) -> Result<Self> {
253        Ok(self.date().trunc_iso_week()?.and_zero_time())
254    }
255
256    #[inline]
257    fn trunc_month_start_week(self) -> Result<Self> {
258        Ok(self.date().trunc_month_start_week()?.and_zero_time())
259    }
260
261    #[inline]
262    fn trunc_day(self) -> Result<Self> {
263        Ok(self.date().and_zero_time())
264    }
265
266    #[inline]
267    fn trunc_sunday_start_week(self) -> Result<Self> {
268        Ok(self.date().trunc_sunday_start_week()?.and_zero_time())
269    }
270
271    #[inline]
272    fn trunc_hour(self) -> Result<Self> {
273        Ok(self
274            .date()
275            .and_time(unsafe { Time::from_hms_unchecked(self.hour().unwrap() as u32, 0, 0, 0) }))
276    }
277
278    #[inline]
279    fn trunc_minute(self) -> Result<Self> {
280        let (hour, minute, _, _) = self.time().extract();
281        Ok(self
282            .date()
283            .and_time(unsafe { Time::from_hms_unchecked(hour, minute, 0, 0) }))
284    }
285}
286
287impl Round for Timestamp {
288    #[inline]
289    fn round_century(self) -> Result<Self> {
290        Ok(self.date().round_century()?.and_zero_time())
291    }
292
293    #[inline]
294    fn round_year(self) -> Result<Self> {
295        Ok(self.date().round_year()?.and_zero_time())
296    }
297
298    #[inline]
299    fn round_iso_year(self) -> Result<Self> {
300        Ok(self.date().round_iso_year()?.and_zero_time())
301    }
302
303    #[inline]
304    fn round_quarter(self) -> Result<Self> {
305        Ok(self.date().round_quarter()?.and_zero_time())
306    }
307
308    #[inline]
309    fn round_month(self) -> Result<Self> {
310        Ok(self.date().round_month()?.and_zero_time())
311    }
312
313    #[inline]
314    fn round_week(self) -> Result<Self> {
315        let (mut date, time) = self.extract();
316        if time.hour().unwrap() >= 12 {
317            date = date.add_days(1)?;
318        }
319        let year = date.extract().0;
320
321        Ok(date.round_week_internal(year)?.and_zero_time())
322    }
323
324    #[inline]
325    fn round_iso_week(self) -> Result<Self> {
326        let (mut date, time) = self.extract();
327        if time.hour().unwrap() >= 12 {
328            date = date.add_days(1)?;
329        }
330        Ok(date.round_iso_week()?.and_zero_time())
331    }
332
333    #[inline]
334    fn round_month_start_week(self) -> Result<Self> {
335        let (mut date, time) = self.extract();
336        if time.hour().unwrap() >= 12 {
337            date = date.add_days(1)?;
338        }
339        let day = date.extract().2;
340
341        Ok(date
342            .round_month_start_week_internal(day as i32)?
343            .and_zero_time())
344    }
345
346    #[inline]
347    fn round_day(self) -> Result<Self> {
348        let mut date = self.date();
349        if self.hour().unwrap() >= 12 {
350            date = date.add_days(1)?;
351        }
352        Ok(date.and_zero_time())
353    }
354
355    #[inline]
356    fn round_sunday_start_week(self) -> Result<Self> {
357        let (mut date, time) = self.extract();
358        if time.hour().unwrap() >= 12 {
359            date = date.add_days(1)?;
360        }
361        Ok(date.round_sunday_start_week()?.and_zero_time())
362    }
363
364    #[inline]
365    fn round_hour(self) -> Result<Self> {
366        let mut date = self.date();
367        let (mut hour, minute, _, _) = self.time().extract();
368        if minute >= 30 {
369            if hour >= 23 {
370                date = date.add_days(1)?;
371                hour = 0;
372            } else {
373                hour += 1
374            }
375        }
376        Ok(date.and_time(unsafe { Time::from_hms_unchecked(hour, 0, 0, 0) }))
377    }
378
379    #[inline]
380    fn round_minute(self) -> Result<Self> {
381        let mut date = self.date();
382        let (mut hour, mut minute, sec, _) = self.time().extract();
383        if sec >= 30 {
384            if minute == 59 {
385                if hour == 23 {
386                    date = date.add_days(1)?;
387                    hour = 0;
388                } else {
389                    hour += 1;
390                }
391                minute = 0;
392            } else {
393                minute += 1;
394            }
395        }
396
397        Ok(date.and_time(unsafe { Time::from_hms_unchecked(hour, minute, 0, 0) }))
398    }
399}
400
401impl From<Timestamp> for NaiveDateTime {
402    #[inline]
403    fn from(ts: Timestamp) -> Self {
404        let (date, time) = ts.extract();
405        let (year, month, day) = date.extract();
406        let (hour, minute, sec, usec) = time.extract();
407
408        NaiveDateTime {
409            year,
410            month,
411            day,
412            hour,
413            minute,
414            sec,
415            usec,
416            ampm: None,
417            negative: false,
418        }
419    }
420}
421
422impl TryFrom<NaiveDateTime> for Timestamp {
423    type Error = Error;
424
425    #[inline]
426    fn try_from(dt: NaiveDateTime) -> Result<Self> {
427        Date::validate_ymd(dt.year, dt.month, dt.day)?;
428        Time::validate_hms(dt.hour, dt.minute, dt.sec)?;
429
430        let days = date2julian(dt.year, dt.month, dt.day) - UNIX_EPOCH_JULIAN;
431        let total_usec = days as i64 * USECONDS_PER_DAY
432            + dt.hour as i64 * USECONDS_PER_HOUR
433            + dt.minute as i64 * USECONDS_PER_MINUTE
434            + dt.sec as i64 * USECONDS_PER_SECOND
435            + dt.usec as i64;
436
437        Timestamp::try_from_usecs(total_usec)
438    }
439}
440
441impl PartialEq<Date> for Timestamp {
442    #[inline]
443    fn eq(&self, other: &Date) -> bool {
444        *self == other.and_zero_time()
445    }
446}
447
448impl PartialOrd<Date> for Timestamp {
449    #[inline]
450    fn partial_cmp(&self, other: &Date) -> Option<Ordering> {
451        Some(self.usecs().cmp(&other.and_zero_time().usecs()))
452    }
453}
454
455impl From<Date> for Timestamp {
456    #[inline]
457    fn from(date: Date) -> Self {
458        date.and_zero_time()
459    }
460}
461
462impl TryFrom<Time> for Timestamp {
463    type Error = Error;
464
465    #[inline]
466    fn try_from(time: Time) -> Result<Self> {
467        let now = Local::now();
468        Ok(Timestamp::new(
469            Date::try_from_ymd(now.year(), now.month(), now.day())?,
470            time,
471        ))
472    }
473}
474
475impl DateTime for Timestamp {
476    #[inline]
477    fn year(&self) -> Option<i32> {
478        Timestamp::date(*self).year()
479    }
480
481    #[inline]
482    fn month(&self) -> Option<i32> {
483        Timestamp::date(*self).month()
484    }
485
486    #[inline]
487    fn day(&self) -> Option<i32> {
488        Timestamp::date(*self).day()
489    }
490
491    #[inline]
492    fn hour(&self) -> Option<i32> {
493        self.time().hour()
494    }
495
496    #[inline]
497    fn minute(&self) -> Option<i32> {
498        self.time().minute()
499    }
500
501    #[inline]
502    fn second(&self) -> Option<f64> {
503        self.time().second()
504    }
505
506    #[inline]
507    fn date(&self) -> Option<Date> {
508        Some(Timestamp::date(*self))
509    }
510}
511
512#[cfg(test)]
513mod tests {
514    use super::*;
515    use crate::common::DATE_MAX_YEAR;
516
517    fn generate_ts(
518        year: i32,
519        month: u32,
520        day: u32,
521        hour: u32,
522        min: u32,
523        sec: u32,
524        usec: u32,
525    ) -> Timestamp {
526        Timestamp::new(
527            Date::try_from_ymd(year, month, day).unwrap(),
528            Time::try_from_hms(hour, min, sec, usec).unwrap(),
529        )
530    }
531
532    fn generate_date(year: i32, month: u32, day: u32) -> Date {
533        Date::try_from_ymd(year, month, day).unwrap()
534    }
535
536    fn generate_time(hour: u32, min: u32, sec: u32, usec: u32) -> Time {
537        Time::try_from_hms(hour, min, sec, usec).unwrap()
538    }
539
540    #[test]
541    fn test_timestamp() {
542        {
543            let date = Date::try_from_ymd(1970, 1, 1).unwrap();
544            let time = Time::try_from_hms(0, 0, 0, 0).unwrap();
545            let ts = Timestamp::new(date, time);
546            assert_eq!(ts.usecs(), 0);
547
548            let (date, time) = ts.extract();
549            assert_eq!(date.extract(), (1970, 1, 1));
550            assert_eq!(time.extract(), (0, 0, 0, 0));
551
552            let ts = generate_ts(1, 1, 1, 0, 0, 0, 0);
553            let (date, time) = ts.extract();
554            assert_eq!(date.extract(), (1, 1, 1));
555            assert_eq!(time.extract(), (0, 0, 0, 0));
556
557            let ts = generate_ts(1, 1, 1, 23, 59, 59, 999999);
558            let (date, time) = ts.extract();
559            assert_eq!(date.extract(), (1, 1, 1));
560            assert_eq!(time.extract(), (23, 59, 59, 999999));
561
562            let ts = generate_ts(1, 12, 31, 0, 0, 0, 0);
563            let (date, time) = ts.extract();
564            assert_eq!(date.extract(), (1, 12, 31));
565            assert_eq!(time.extract(), (0, 0, 0, 0));
566
567            let ts = generate_ts(1, 12, 31, 23, 59, 59, 999999);
568            let (date, time) = ts.extract();
569            assert_eq!(date.extract(), (1, 12, 31));
570            assert_eq!(time.extract(), (23, 59, 59, 999999));
571
572            let ts = generate_ts(1969, 12, 30, 0, 0, 0, 0);
573            let (date, time) = ts.extract();
574            assert_eq!(date.extract(), (1969, 12, 30));
575            assert_eq!(time.extract(), (0, 0, 0, 0));
576
577            let ts = generate_ts(1969, 12, 30, 23, 59, 59, 999999);
578            let (date, time) = ts.extract();
579            assert_eq!(date.extract(), (1969, 12, 30));
580            assert_eq!(time.extract(), (23, 59, 59, 999999));
581
582            let ts = generate_ts(1969, 12, 31, 0, 0, 0, 0);
583            let (date, time) = ts.extract();
584            assert_eq!(date.extract(), (1969, 12, 31));
585            assert_eq!(time.extract(), (0, 0, 0, 0));
586
587            let ts = generate_ts(1969, 12, 31, 23, 59, 59, 999999);
588            let (date, time) = ts.extract();
589            assert_eq!(date.extract(), (1969, 12, 31));
590            assert_eq!(time.extract(), (23, 59, 59, 999999));
591
592            let ts = generate_ts(1970, 1, 1, 0, 0, 0, 0);
593            let (date, time) = ts.extract();
594            assert_eq!(date.extract(), (1970, 1, 1));
595            assert_eq!(time.extract(), (0, 0, 0, 0));
596
597            let ts = generate_ts(1970, 1, 1, 23, 59, 59, 999999);
598            let (date, time) = ts.extract();
599            assert_eq!(date.extract(), (1970, 1, 1));
600            assert_eq!(time.extract(), (23, 59, 59, 999999));
601
602            let ts = generate_ts(1970, 3, 4, 23, 12, 30, 123456);
603            let (date, time) = ts.extract();
604            assert_eq!(date.extract(), (1970, 3, 4));
605            assert_eq!(time.extract(), (23, 12, 30, 123456));
606
607            let ts = generate_ts(9999, 12, 31, 0, 0, 0, 0);
608            let (date, time) = ts.extract();
609            assert_eq!(date.extract(), (9999, 12, 31));
610            assert_eq!(time.extract(), (0, 0, 0, 0));
611
612            let ts = generate_ts(9999, 12, 31, 23, 59, 59, 999999);
613            let (date, time) = ts.extract();
614            assert_eq!(date.extract(), (9999, 12, 31));
615            assert_eq!(time.extract(), (23, 59, 59, 999999));
616
617            let ts = generate_ts(1969, 10, 31, 1, 1, 1, 1);
618            let (date, time) = ts.extract();
619            assert_eq!(date.extract(), (1969, 10, 31));
620            assert_eq!(time.extract(), (1, 1, 1, 1));
621
622            // Test parse with rounding usec
623            {
624                // Round usec
625                // Day
626                assert_eq!(
627                    Timestamp::new(
628                        Date::try_from_ymd(2022, 10, 24).unwrap(),
629                        Time::try_from_hms(0, 0, 0, 0).unwrap(),
630                    ),
631                    Timestamp::parse("2022-10-23 23:59:59.9999999", "yyyy-mm-dd hh24:mi:ss.ff")
632                        .unwrap()
633                );
634                // Month
635                assert_eq!(
636                    Timestamp::new(
637                        Date::try_from_ymd(2022, 11, 1).unwrap(),
638                        Time::try_from_hms(0, 0, 0, 0).unwrap(),
639                    ),
640                    Timestamp::parse("2022-10-31 23:59:59.9999999", "yyyy-mm-dd hh24:mi:ss.ff")
641                        .unwrap()
642                );
643                // Year
644                assert_eq!(
645                    Timestamp::new(
646                        Date::try_from_ymd(2023, 1, 1).unwrap(),
647                        Time::try_from_hms(0, 0, 0, 0).unwrap(),
648                    ),
649                    Timestamp::parse("2022-12-31 23:59:59.9999999", "yyyy-mm-dd hh24:mi:ss.ff")
650                        .unwrap()
651                );
652
653                // No round
654                assert_eq!(
655                    Timestamp::new(
656                        Date::try_from_ymd(2022, 6, 18).unwrap(),
657                        Time::try_from_hms(3, 4, 5, 6).unwrap(),
658                    ),
659                    Timestamp::parse("2022-06-18 03:04:05.000006", "yyyy-mm-dd hh24:mi:ss.ff")
660                        .unwrap()
661                );
662                assert_eq!(
663                    Timestamp::MAX,
664                    Timestamp::parse("9999-12-31 23:59:59.999999", "yyyy-mm-dd hh24:mi:ss.ff")
665                        .unwrap()
666                );
667                assert_eq!(
668                    Timestamp::MAX,
669                    Timestamp::parse("9999-12-31 23:59:59.9999991", "yyyy-mm-dd hh24:mi:ss.ff")
670                        .unwrap()
671                );
672                assert_eq!(
673                    Timestamp::MAX,
674                    Timestamp::parse("9999-12-31 23:59:59.999999119", "yyyy-mm-dd hh24:mi:ss.ff")
675                        .unwrap()
676                );
677                assert_eq!(
678                    Timestamp::MAX,
679                    Timestamp::parse("9999-12-31 23:59:59.9999994", "yyyy-mm-dd hh24:mi:ss.ff")
680                        .unwrap()
681                );
682
683                // Out of range
684                // Year
685                assert!(Timestamp::parse(
686                    "10000-12-31 23:59:59.999999",
687                    "yyyy-mm-dd hh24:mi:ss.ff"
688                )
689                .is_err());
690                assert!(Timestamp::parse(
691                    "20000-12-31 23:59:59.999999",
692                    "yyyy-mm-dd hh24:mi:ss.ff"
693                )
694                .is_err());
695                // Month
696                assert_eq!(
697                    Err(Error::InvalidMonth),
698                    Timestamp::parse("9999-13-31 24:60:59.999999", "yyyy-mm-dd hh24:mi:ss.ff")
699                );
700                assert_eq!(
701                    Err(Error::InvalidMonth),
702                    Timestamp::parse("9999-20-31 24:60:59.999999", "yyyy-mm-dd hh24:mi:ss.ff")
703                );
704                // Day
705                assert_eq!(
706                    Err(Error::InvalidDay),
707                    Timestamp::parse("9999-12-32 24:59:60.999999", "yyyy-mm-dd hh24:mi:ss.ff")
708                );
709                assert_eq!(
710                    Err(Error::InvalidDay),
711                    Timestamp::parse("9999-12-40 24:59:60.999999", "yyyy-mm-dd hh24:mi:ss.ff")
712                );
713                // Hour
714                assert_eq!(
715                    Err(Error::TimeOutOfRange),
716                    Timestamp::parse("9999-12-31 24:59:59.999999", "yyyy-mm-dd hh24:mi:ss.ff")
717                );
718                assert_eq!(
719                    Err(Error::TimeOutOfRange),
720                    Timestamp::parse("9999-12-31 25:59:59.999999", "yyyy-mm-dd hh24:mi:ss.ff")
721                );
722                // Minute
723                assert_eq!(
724                    Err(Error::InvalidMinute),
725                    Timestamp::parse("9999-12-31 23:60:59.999999", "yyyy-mm-dd hh24:mi:ss.ff")
726                );
727                // Second
728                assert_eq!(
729                    Err(Error::InvalidSecond),
730                    Timestamp::parse("9999-12-31 23:59:60.999999", "yyyy-mm-dd hh24:mi:ss.ff")
731                );
732                // Maximum Value
733                assert_eq!(
734                    Err(Error::DateOutOfRange),
735                    Timestamp::parse("9999-12-31 23:59:59.9999995", "yyyy-mm-dd hh24:mi:ss.ff")
736                );
737                assert_eq!(
738                    Err(Error::DateOutOfRange),
739                    Timestamp::parse("9999-12-31 23:59:59.99999999", "yyyy-mm-dd hh24:mi:ss.ff")
740                );
741            }
742
743            // Out of order
744            {
745                // Parse
746                let time = Time::try_from_hms(23, 59, 59, 999999).unwrap();
747                let ts = Date::try_from_ymd(9999, 12, 31).unwrap().and_time(time);
748                let ts2 = Timestamp::parse(
749                    "PM 9999\\12-31 11/59:59.999999",
750                    "AM yyyy\\mm-dd hh/mi:ss.ff",
751                )
752                .unwrap();
753                assert_eq!(ts2, ts);
754
755                let ts2 =
756                    Timestamp::parse("PM 11-9999-59.999999 12-59-31", "PM HH-YYYY-MI.FF MM-SS-DD")
757                        .unwrap();
758                assert_eq!(ts2, ts);
759                assert!(Timestamp::parse(
760                    "P.M. 11-9999-59.999999 12-59-31",
761                    "PM HH-YYYY-MI.FF MM-SS-DD"
762                )
763                .is_err());
764
765                let ts2 =
766                    Timestamp::parse("23-9999-59.999999 12 59 31", "HH24-YYYY-MI.FF MM SS DD")
767                        .unwrap();
768                assert_eq!(ts, ts2);
769
770                let ts2 = Timestamp::parse(
771                    "T23--59.999999 12 59 31.9999;",
772                    "THH24--MI.FF MM SS DD.yyyy;",
773                )
774                .unwrap();
775                assert_eq!(ts, ts2);
776
777                // Format
778                let fmt = ts.format("TAM HH\\YYYY\\MI.FF MM-SS/DD").unwrap();
779                assert_eq!(format!("{}", fmt), "TPM 11\\9999\\59.999999 12-59/31");
780
781                let fmt = ts.format("HH\\YYYY\\MI MM-SS/DD.FF4;").unwrap();
782                assert_eq!(format!("{}", fmt), "11\\9999\\59 12-59/31.9999;");
783            }
784
785            // Duplicate parse
786            {
787                // Parse
788                assert!(Timestamp::parse(
789                    "AM PM 9999\\12-31 11/59:59.999999",
790                    "AM PM yyyy\\mm-dd hh/mi:ss.ff"
791                )
792                .is_err());
793
794                assert!(Timestamp::parse(
795                    "pm PM 9999\\12-31 11/59:59.999999",
796                    "AM PM yyyy\\mm-dd hh/mi:ss.ff"
797                )
798                .is_err());
799
800                assert!(Timestamp::parse(
801                    "9999 9999\\12-31 11/59:59.999999",
802                    "yyyy yyyy\\mm-dd hh/mi:ss.ff"
803                )
804                .is_err());
805
806                assert!(Timestamp::parse(
807                    "9999\\12-31 11/59:59.999999 59",
808                    "yyyy\\mm-dd hh/mi:ss.ff mi"
809                )
810                .is_err());
811
812                assert_eq!(
813                    Timestamp::parse("23:60:00", "hh24:mi:ss").err().unwrap(),
814                    Error::InvalidMinute
815                );
816
817                assert_eq!(
818                    Timestamp::parse("23:00:60", "hh24:mi:ss").err().unwrap(),
819                    Error::InvalidSecond
820                );
821
822                assert!(Timestamp::parse(
823                    "2021-04-25 03:04:05.000006 thu 5",
824                    "yyyy-mm-dd hh24:mi:ss.FF6 dy d",
825                )
826                .is_err());
827
828                // todo duplication special check, including parse and format
829            }
830
831            // Default
832            {
833                let now = Local::now();
834                let year = now.year();
835                let month = now.month();
836
837                let timestamp = generate_ts(year, month, 1, 0, 0, 5, 0);
838                let ts = Timestamp::parse("5", "ss").unwrap();
839                assert_eq!(timestamp, ts);
840
841                let timestamp = generate_ts(year, month, 1, 0, 0, 0, 0);
842                let ts = Timestamp::parse("", "").unwrap();
843                assert_eq!(timestamp, ts);
844
845                let timestamp = generate_ts(year, 1, 1, 0, 0, 0, 0);
846                let ts = Timestamp::parse("jan", "mm").unwrap();
847                assert_eq!(timestamp, ts);
848
849                let ts = Timestamp::parse("January", "mm").unwrap();
850                assert_eq!(timestamp, ts);
851
852                let ts = Timestamp::parse("JANUARY", "mm").unwrap();
853                assert_eq!(timestamp, ts);
854
855                let ts = Timestamp::parse("jan", "MONTH").unwrap();
856                assert_eq!(timestamp, ts);
857
858                let ts = Timestamp::parse("January", "mon").unwrap();
859                assert_eq!(timestamp, ts);
860
861                let timestamp = generate_ts(year - year % 10, month, 1, 0, 0, 0, 0);
862                let ts = Timestamp::parse("0", "y").unwrap();
863                assert_eq!(timestamp, ts);
864
865                let timestamp = generate_ts(year - year % 10 + 2, month, 1, 0, 0, 0, 0);
866                let ts = Timestamp::parse("2", "y").unwrap();
867                assert_eq!(timestamp, ts);
868
869                let timestamp = generate_ts(year - year % 100, month, 1, 0, 0, 0, 0);
870                let ts = Timestamp::parse("0", "yy").unwrap();
871                assert_eq!(timestamp, ts);
872
873                let timestamp = generate_ts(year - year % 100 + 1, month, 1, 0, 0, 0, 0);
874                let ts = Timestamp::parse("1", "yy").unwrap();
875                assert_eq!(timestamp, ts);
876
877                let timestamp = generate_ts(year - year % 100 + 12, month, 1, 0, 0, 0, 0);
878                let ts = Timestamp::parse("12", "yy").unwrap();
879                assert_eq!(timestamp, ts);
880
881                let timestamp = generate_ts(123, month, 1, 0, 0, 0, 0);
882                let ts = Timestamp::parse("123", "yy").unwrap();
883                assert_eq!(timestamp, ts);
884
885                let timestamp = generate_ts(1234, month, 1, 0, 0, 0, 0);
886                let ts = Timestamp::parse("1234", "yy").unwrap();
887                assert_eq!(timestamp, ts);
888
889                let timestamp = generate_ts(year - year % 1000 + 1, month, 1, 0, 0, 0, 0);
890                let ts = Timestamp::parse("1", "yyy").unwrap();
891                assert_eq!(timestamp, ts);
892
893                let timestamp = generate_ts(year - year % 1000 + 12, month, 1, 0, 0, 0, 0);
894                let ts = Timestamp::parse("12", "yyy").unwrap();
895                assert_eq!(timestamp, ts);
896
897                let timestamp = generate_ts(year - year % 1000 + 12, month, 1, 0, 0, 0, 0);
898                let ts = Timestamp::parse("012", "yyy").unwrap();
899                assert_eq!(timestamp, ts);
900
901                let timestamp = generate_ts(year - year % 1000 + 123, month, 1, 0, 0, 0, 0);
902                let ts = Timestamp::parse("123", "yyy").unwrap();
903                assert_eq!(timestamp, ts);
904
905                let timestamp = generate_ts(2, month, 1, 0, 0, 0, 0);
906                let ts = Timestamp::parse("2", "yyyy").unwrap();
907                assert_eq!(timestamp, ts);
908
909                let timestamp = generate_ts(1234, month, 1, 0, 0, 0, 0);
910                let ts = Timestamp::parse("1234", "yyyy").unwrap();
911                assert_eq!(timestamp, ts);
912            }
913
914            // positive
915            {
916                let timestamp =
917                    Timestamp::parse("+2020-+11-+12 +11:+12:+13", "YYYY-MM-DD HH24:mi:ss").unwrap();
918                assert_eq!(timestamp, generate_ts(2020, 11, 12, 11, 12, 13, 0));
919            }
920
921            // Absence of time
922            {
923                let timestamp = Timestamp::parse("2020-11-12", "YYYY-MM-DD HH24:MI:SS").unwrap();
924                assert_eq!(timestamp, generate_ts(2020, 11, 12, 0, 0, 0, 0));
925
926                let timestamp = Timestamp::parse("2020-11-12", "YYYY-MM-DD HH24-MI-SS").unwrap();
927                assert_eq!(timestamp, generate_ts(2020, 11, 12, 0, 0, 0, 0));
928
929                let timestamp = Timestamp::parse("2020-11-12 11", "YYYY-MM-DD HH24:MI:SS").unwrap();
930                assert_eq!(timestamp, generate_ts(2020, 11, 12, 11, 0, 0, 0));
931
932                let timestamp =
933                    Timestamp::parse("2020-11-12 11:23", "YYYY-MM-DD HH24:MI:SS").unwrap();
934                assert_eq!(timestamp, generate_ts(2020, 11, 12, 11, 23, 0, 0));
935
936                let timestamp =
937                    Timestamp::parse("2020-11-12 11:23:25", "YYYY-MM-DD HH24:MI:SS.ff").unwrap();
938                assert_eq!(timestamp, generate_ts(2020, 11, 12, 11, 23, 25, 0));
939
940                let timestamp =
941                    Timestamp::parse("2021-12-15", "YYYY-MM-DD HH:MI:SS.ff AM").unwrap();
942                assert_eq!(timestamp, generate_ts(2021, 12, 15, 0, 0, 0, 0));
943
944                assert!(Timestamp::parse("2021-12-15 0", "YYYY-MM-DD HH").is_err());
945                assert!(Timestamp::parse("2021-12-15 0", "YYYY-MM-DD HH12").is_err());
946                assert!(Timestamp::parse("2021-12-15 0", "YYYY-MM-DD HH:MI:SS.ff AM").is_err());
947
948                let timestamp =
949                    Timestamp::parse("2021-12-15 11", "YYYY-MM-DD HH:MI:SS.ff AM").unwrap();
950                assert_eq!(timestamp, generate_ts(2021, 12, 15, 11, 0, 0, 0));
951
952                let timestamp =
953                    Timestamp::parse("2021-12-15 11:23", "YYYY-MM-DD HH:MI:SS.ff AM").unwrap();
954                assert_eq!(timestamp, generate_ts(2021, 12, 15, 11, 23, 0, 0));
955
956                let timestamp =
957                    Timestamp::parse("2021-12-15 11:23:25", "YYYY-MM-DD HH:MI:SS.ff AM").unwrap();
958                assert_eq!(timestamp, generate_ts(2021, 12, 15, 11, 23, 25, 0));
959
960                let timestamp =
961                    Timestamp::parse("2020-11-12 11:23:25.123456", "YYYY-MM-DD HH:MI:SS.ff AM")
962                        .unwrap();
963                assert_eq!(timestamp, generate_ts(2020, 11, 12, 11, 23, 25, 123456));
964
965                let timestamp =
966                    Timestamp::parse("2020-11-12 11:23:25.123", "YYYY-MM-DD HH:MI:SS.ff A.M.")
967                        .unwrap();
968                assert_eq!(timestamp, generate_ts(2020, 11, 12, 11, 23, 25, 123000));
969
970                let timestamp =
971                    Timestamp::parse("2020-11-12 11:23:25.123", "YYYY-MM-DD HH:MI:SS.ff PM")
972                        .unwrap();
973                assert_eq!(timestamp, generate_ts(2020, 11, 12, 11, 23, 25, 123000));
974
975                let timestamp =
976                    Timestamp::parse("2020-11-12 11:23:25      ", "YYYY-MM-DD HH:MI:SS.ff PM")
977                        .unwrap();
978                assert_eq!(timestamp, generate_ts(2020, 11, 12, 11, 23, 25, 0));
979            }
980
981            // Can not absence of year\month\day
982            {
983                assert!(Timestamp::parse("2022-4", "YYYY-MM-DD HH24:MI:SS.FF").is_err());
984            }
985
986            // Short format
987            {
988                let ts = generate_ts(1234, 8, 6, 7, 8, 9, 10);
989                assert_eq!(format!("{}", ts.format("YYYY").unwrap()), "1234");
990                assert_eq!(format!("{}", ts.format("DD").unwrap()), "06");
991                assert_eq!(format!("{}", ts.format("MON").unwrap()), "AUG");
992                assert_eq!(format!("{}", ts.format("Mon").unwrap()), "Aug");
993                assert_eq!(format!("{}", ts.format("mon").unwrap()), "aug");
994                assert_eq!(format!("{}", ts.format("MONTH").unwrap()), "AUGUST");
995                assert_eq!(format!("{}", ts.format("MONtH").unwrap()), "AUGUST");
996                assert_eq!(format!("{}", ts.format("Month").unwrap()), "August");
997                assert_eq!(format!("{}", ts.format("month").unwrap()), "august");
998                assert_eq!(format!("{}", ts.format("WW").unwrap()), "32");
999                assert_eq!(format!("{}", ts.format("W").unwrap()), "1");
1000                assert_eq!(format!("{}", ts.format("DAY").unwrap()), "SUNDAY");
1001                assert_eq!(format!("{}", ts.format("DAy").unwrap()), "SUNDAY");
1002                assert_eq!(format!("{}", ts.format("Day").unwrap()), "Sunday");
1003                assert_eq!(format!("{}", ts.format("DaY").unwrap()), "Sunday");
1004                assert_eq!(format!("{}", ts.format("day").unwrap()), "sunday");
1005                assert_eq!(format!("{}", ts.format("daY").unwrap()), "sunday");
1006                assert_eq!(format!("{}", ts.format("DY").unwrap()), "SUN");
1007                assert_eq!(format!("{}", ts.format("Dy").unwrap()), "Sun");
1008                assert_eq!(format!("{}", ts.format("dy").unwrap()), "sun");
1009                assert_eq!(format!("{}", ts.format("D").unwrap()), "1");
1010                assert_eq!(format!("{}", ts.format("DDD").unwrap()), "218");
1011                assert_eq!(format!("{}", ts.format("mi").unwrap()), "08");
1012                assert_eq!(format!("{}", ts.format("hh").unwrap()), "07");
1013                assert_eq!(format!("{}", ts.format("ss").unwrap()), "09");
1014                assert_eq!(format!("{}", ts.format("FF").unwrap()), "000010");
1015                assert_eq!(format!("{}", ts.format("y").unwrap()), "4");
1016                assert_eq!(format!("{}", ts.format("yy").unwrap()), "34");
1017                assert_eq!(format!("{}", ts.format("yyy").unwrap()), "234");
1018
1019                assert!(Timestamp::parse("1234", "yyy").is_err());
1020                assert!(Timestamp::parse("1234", "y").is_err());
1021                assert!(Timestamp::parse("123", "y").is_err());
1022                assert!(Timestamp::parse("12", "y").is_err());
1023
1024                assert!(Timestamp::parse("-12", "yyyy").is_err());
1025                assert!(Timestamp::parse("-12", "mm").is_err());
1026                assert!(Timestamp::parse("-12", "dd").is_err());
1027                assert!(Timestamp::parse("-12", "hh24").is_err());
1028                assert!(Timestamp::parse("-1", "hh12").is_err());
1029                assert!(Timestamp::parse("-123456", "ff").is_err());
1030                assert!(Timestamp::parse("-12", "yyyy").is_err());
1031                assert!(Timestamp::parse("-12", "mi").is_err());
1032                assert!(Timestamp::parse("-12", "ss").is_err());
1033
1034                let ts = generate_ts(1970, 1, 1, 7, 8, 9, 10);
1035                assert_eq!(format!("{}", ts.format("day").unwrap()), "thursday");
1036                assert_eq!(format!("{}", ts.format("d").unwrap()), "5");
1037                assert_eq!(format!("{}", ts.format("ddd").unwrap()), "001");
1038                assert_eq!(format!("{}", ts.format("ww").unwrap()), "01");
1039                assert_eq!(format!("{}", ts.format("w").unwrap()), "1");
1040
1041                let ts = generate_ts(1970, 1, 2, 7, 8, 9, 10);
1042                assert_eq!(format!("{}", ts.format("day").unwrap()), "friday");
1043
1044                let ts = generate_ts(1969, 12, 31, 7, 8, 9, 10);
1045                assert_eq!(format!("{}", ts.format("day").unwrap()), "wednesday");
1046                assert_eq!(format!("{}", ts.format("d").unwrap()), "4");
1047                assert_eq!(format!("{}", ts.format("ddd").unwrap()), "365");
1048                assert_eq!(format!("{}", ts.format("ww").unwrap()), "53");
1049                assert_eq!(format!("{}", ts.format("w").unwrap()), "5");
1050
1051                let ts = generate_ts(1969, 10, 1, 7, 8, 9, 10);
1052                assert_eq!(format!("{}", ts.format("day").unwrap()), "wednesday");
1053
1054                let ts = generate_ts(9999, 11, 14, 7, 8, 9, 10);
1055                assert_eq!(format!("{}", ts.format("day").unwrap()), "sunday");
1056            }
1057
1058            // Normal
1059            {
1060                let ts = generate_ts(2000, 1, 1, 0, 0, 0, 0);
1061                let fmt = format!("{}", ts.format("yyyy-MONTH-dd hh:mi:ss.ff1").unwrap());
1062                assert_eq!(fmt, "2000-JANUARY-01 12:00:00.0");
1063
1064                let fmt = format!("{}", ts.format("yyyy-Mon-dd hh:mi:ss.ff1").unwrap());
1065                assert_eq!(fmt, "2000-Jan-01 12:00:00.0");
1066
1067                let fmt = format!("{}", ts.format("Day yyyy-Mon-dd hh:mi:ss.ff1").unwrap());
1068                assert_eq!(fmt, "Saturday 2000-Jan-01 12:00:00.0");
1069
1070                let fmt = format!("{}", ts.format("yyyyMMdd hh24miss.ff1").unwrap());
1071                assert_eq!(fmt, "20000101 000000.0");
1072
1073                let ts = generate_ts(2001, 1, 2, 3, 4, 5, 6);
1074                assert_eq!(
1075                    format!("{}", ts.format("YYYYMMDDHHMISSFF").unwrap()),
1076                    "20010102030405000006"
1077                );
1078
1079                assert_eq!(
1080                    ts,
1081                    Timestamp::parse("20010102030405000006", "YYYYMMDDHHMISSFF").unwrap()
1082                );
1083
1084                assert_eq!(
1085                    ts,
1086                    Timestamp::parse("2001012 030405000006", "YYYYMMDD HHMISSFF").unwrap()
1087                );
1088            }
1089
1090            // fraction rounding and etc
1091            {
1092                let now = Local::now();
1093                let year = now.year();
1094                let month = now.month();
1095
1096                assert_eq!(
1097                    Timestamp::parse(".12345", ".ff").unwrap(),
1098                    generate_ts(year, month, 1, 0, 0, 0, 123450)
1099                );
1100                assert_eq!(
1101                    Timestamp::parse(".123456789", ".ff").unwrap(),
1102                    generate_ts(year, month, 1, 0, 0, 0, 123457)
1103                );
1104                assert_eq!(
1105                    Timestamp::parse(".12345678", ".ff").unwrap(),
1106                    generate_ts(year, month, 1, 0, 0, 0, 123457)
1107                );
1108                assert_eq!(
1109                    Timestamp::parse(".1234567", ".ff7").unwrap(),
1110                    generate_ts(year, month, 1, 0, 0, 0, 123457)
1111                );
1112                assert!(Timestamp::parse(".12345678", ".ff7").is_err());
1113                assert_eq!(
1114                    Timestamp::parse(".123456", ".ff6").unwrap(),
1115                    generate_ts(year, month, 1, 0, 0, 0, 123456)
1116                );
1117                assert!(Timestamp::parse(".123456789", ".ff2").is_err());
1118
1119                let timestamp = generate_ts(1, 2, 3, 4, 5, 6, 123456);
1120                assert_eq!(format!("{}", timestamp.format("ff6").unwrap()), "123456");
1121                assert_eq!(format!("{}", timestamp.format("ff").unwrap()), "123456");
1122                assert_eq!(format!("{}", timestamp.format("ff9").unwrap()), "123456000");
1123                assert_eq!(format!("{}", timestamp.format("ff5").unwrap()), "12345");
1124            }
1125
1126            // Month parse check
1127            {
1128                let ts = generate_ts(2021, 4, 22, 3, 4, 5, 6);
1129                let ts1 =
1130                    Timestamp::parse("2021-04-22 03:04:05.000006", "yyyy-mm-dd hh24:mi:ss.ff")
1131                        .unwrap();
1132                let ts2 =
1133                    Timestamp::parse("2021-APRIL-22 03:04:05.000006", "yyyy-mm-dd hh24:mi:ss.ff")
1134                        .unwrap();
1135                let ts3 =
1136                    Timestamp::parse("2021-APR-22 03:04:05.000006", "yyyy-mm-dd hh24:mi:ss.ff")
1137                        .unwrap();
1138                let ts4 =
1139                    Timestamp::parse("2021-April-22 03:04:05.000006", "yyyy-mm-dd hh24:mi:ss.ff")
1140                        .unwrap();
1141                let ts5 =
1142                    Timestamp::parse("2021-Apr-22 03:04:05.000006", "yyyy-mm-dd hh24:mi:ss.ff")
1143                        .unwrap();
1144                let ts6 =
1145                    Timestamp::parse("2021-april-22 03:04:05.000006", "yyyy-mm-dd hh24:mi:ss.ff")
1146                        .unwrap();
1147                let ts7 =
1148                    Timestamp::parse("2021-apr-22 03:04:05.000006", "yyyy-mm-dd hh24:mi:ss.ff")
1149                        .unwrap();
1150                assert_eq!(ts, ts1);
1151                assert_eq!(ts, ts2);
1152                assert_eq!(ts, ts3);
1153                assert_eq!(ts, ts4);
1154                assert_eq!(ts, ts5);
1155                assert_eq!(ts, ts6);
1156                assert_eq!(ts, ts7);
1157            }
1158
1159            // Day parse check
1160            {
1161                let ts = generate_ts(2021, 4, 22, 3, 4, 5, 6);
1162                let ts2 = Timestamp::parse(
1163                    "2021-04-22 03:04:05.000006 thu",
1164                    "yyyy-mm-dd hh24:mi:ss.FF6 dy",
1165                )
1166                .unwrap();
1167                let ts3 = Timestamp::parse(
1168                    "2021-04-22 03:04:05.000006 5",
1169                    "yyyy-mm-dd hh24:mi:ss.FF6 d",
1170                )
1171                .unwrap();
1172                let ts4 =
1173                    Timestamp::parse("2021 112 3:4:5.000006", "yyyy ddd hh24:mi:ss.FF6").unwrap();
1174                let ts5 = Timestamp::parse(
1175                    "2021-4-22 3:4:5.000006 112",
1176                    "yyyy-mm-dd hh24:mi:ss.FF6 ddd",
1177                )
1178                .unwrap();
1179                assert_eq!(ts, ts2);
1180                assert_eq!(ts, ts3);
1181                assert_eq!(ts, ts4);
1182                assert_eq!(ts, ts5);
1183
1184                let ts2 = Timestamp::parse(
1185                    "2021-04-22 03:04:05.000006 thu",
1186                    "yyyy-mm-dd hh24:mi:ss.FF6 dy",
1187                )
1188                .unwrap();
1189                assert_eq!(ts, ts2);
1190
1191                let ts2 = Timestamp::parse(
1192                    "2021-04-22 03:04:05.000006 thursday",
1193                    "yyyy-mm-dd hh24:mi:ss.FF6 day",
1194                )
1195                .unwrap();
1196                assert_eq!(ts, ts2);
1197
1198                let ts2 = Timestamp::parse(
1199                    "2021-04-22 03:04:05.000006 thu",
1200                    "yyyy-mm-dd hh24:mi:ss.FF6 Dy",
1201                )
1202                .unwrap();
1203                assert_eq!(ts, ts2);
1204
1205                let ts2 = Timestamp::parse(
1206                    "2021-04-22 03:04:05.000006 Thu",
1207                    "yyyy-mm-dd hh24:mi:ss.FF6 dy",
1208                )
1209                .unwrap();
1210                assert_eq!(ts, ts2);
1211
1212                assert!(Timestamp::parse(
1213                    "2021-04-23 03:04:05.000006 thu",
1214                    "yyyy-mm-dd hh24:mi:ss.FF6 dy",
1215                )
1216                .is_err());
1217
1218                assert!(Timestamp::parse(
1219                    "2021-04-23 03:04:05.000006 5",
1220                    "yyyy-mm-dd hh24:mi:ss.FF6 d",
1221                )
1222                .is_err());
1223
1224                assert!(Timestamp::parse(
1225                    "2021-04-22 03:04:05.000006 ",
1226                    "yyyy-mm-dd hh24:mi:ss.FF6 d",
1227                )
1228                .is_err());
1229
1230                assert!(Timestamp::parse("2021-04-22 172", "yyyy-mm-dd ddd",).is_err());
1231            }
1232
1233            // Duplicate format
1234            {
1235                let ts = generate_ts(2021, 4, 25, 3, 4, 5, 6);
1236                assert_eq!(
1237                    format!(
1238                        "{}",
1239                        ts.format("DAY DaY DY D DDD W WW WW MM MM yyyy YYYY MI MI")
1240                            .unwrap()
1241                    ),
1242                    "SUNDAY Sunday SUN 1 115 4 17 17 04 04 2021 2021 04 04"
1243                );
1244
1245                assert_eq!(
1246                    format!(
1247                        "{}",
1248                        ts.format("DAYDaYDYDWWWWWDMMMMyyyyYYYYMIMIDDD").unwrap()
1249                    ),
1250                    "SUNDAYSundaySUN11717410404202120210404115"
1251                );
1252            }
1253
1254            // Invalid
1255            {
1256                // Parse
1257                assert!(Timestamp::parse(
1258                    "2021-04-22 03:04:05.000006",
1259                    "yyyy-mmX-dd hh24:mi:ss.FF6",
1260                )
1261                .is_err());
1262
1263                assert!(
1264                    Timestamp::parse("2021-04-22 03:04:05.000006", "yyyy-mm-dd mi:ss.FF7").is_err()
1265                );
1266
1267                assert!(
1268                    Timestamp::parse("2021-04-22 03:04:05.000006", "yyy-mm-dd hh24:mi:ss.FF7")
1269                        .is_err()
1270                );
1271
1272                assert!(
1273                    Timestamp::parse("2021-04-32 03:04:05.000006", "yyyy-mm-dd mi:ss.FF7").is_err()
1274                );
1275
1276                assert!(
1277                    Timestamp::parse("10000-04-31 03:04:05.000006", "yyyy-mm-dd mi:ss.FF6")
1278                        .is_err()
1279                );
1280
1281                assert!(
1282                    Timestamp::parse("10000-04-31 33:04:05.000006", "yyyy-mm-dd mi:ss.FF6")
1283                        .is_err()
1284                );
1285
1286                assert!(Timestamp::parse(
1287                    "2021-04-22 03:04:05.000006",
1288                    "ABCD-mm-dd hh24:mi:ss.FF10",
1289                )
1290                .is_err());
1291
1292                assert!(Timestamp::parse(
1293                    "2021-04-23 03:04:05.000006 thur",
1294                    "yyyy-mm-dd hh24:mi:ss.FF6 dy",
1295                )
1296                .is_err());
1297
1298                assert!(
1299                    Timestamp::parse("2021423 03:04:05.000006", "yyyymmdd hh24:mi:ss.FF6").is_err()
1300                );
1301
1302                assert!(
1303                    Timestamp::parse("2021423 03:04:05.000006", "yyyymmdd hh24:mi:ss.FF3").is_err()
1304                );
1305
1306                let timestamp = generate_ts(1234, 5, 6, 7, 8, 9, 10);
1307                assert!(timestamp.format("testtest").is_err());
1308
1309                assert!(Timestamp::parse("2021423 03:04:05", "yyyymmdd am hh:mi:ss").is_err());
1310
1311                assert!(Timestamp::parse(
1312                    "2021-04-23 03:04:05.000006 4",
1313                    "yyyy-mm-dd hh24:mi:ss.FF6 w",
1314                )
1315                .is_err());
1316            }
1317
1318            // todo
1319            // Wrong order of some specific Field, wrong format, extra format.
1320        }
1321    }
1322
1323    #[test]
1324    fn test_timestamp_date_time() {
1325        let ts = generate_ts(1, 1, 1, 0, 0, 0, 0);
1326        assert_eq!(ts.date(), generate_date(1, 1, 1));
1327        assert_eq!(ts.time(), generate_time(0, 0, 0, 0));
1328
1329        let ts = generate_ts(1, 1, 1, 23, 59, 59, 999999);
1330        assert_eq!(ts.date(), generate_date(1, 1, 1));
1331        assert_eq!(ts.time(), generate_time(23, 59, 59, 999999));
1332
1333        let ts = generate_ts(1969, 12, 30, 0, 0, 0, 0);
1334        assert_eq!(ts.date(), generate_date(1969, 12, 30));
1335        assert_eq!(ts.time(), generate_time(0, 0, 0, 0));
1336
1337        let ts = generate_ts(1969, 12, 30, 23, 59, 59, 999999);
1338        assert_eq!(ts.date(), generate_date(1969, 12, 30));
1339        assert_eq!(ts.time(), generate_time(23, 59, 59, 999999));
1340
1341        let ts = generate_ts(1969, 12, 31, 0, 0, 0, 0);
1342        assert_eq!(ts.date(), generate_date(1969, 12, 31));
1343        assert_eq!(ts.time(), generate_time(0, 0, 0, 0));
1344
1345        let ts = generate_ts(1969, 12, 31, 23, 59, 59, 999999);
1346        assert_eq!(ts.date(), generate_date(1969, 12, 31));
1347        assert_eq!(ts.time(), generate_time(23, 59, 59, 999999));
1348
1349        let ts = generate_ts(1970, 1, 1, 0, 0, 0, 0);
1350        assert_eq!(ts.date(), generate_date(1970, 1, 1));
1351        assert_eq!(ts.time(), generate_time(0, 0, 0, 0));
1352
1353        let ts = generate_ts(1970, 1, 1, 23, 59, 59, 999999);
1354        assert_eq!(ts.date(), generate_date(1970, 1, 1));
1355        assert_eq!(ts.time(), generate_time(23, 59, 59, 999999));
1356
1357        let ts = generate_ts(9999, 1, 1, 0, 0, 0, 0);
1358        assert_eq!(ts.date(), generate_date(9999, 1, 1));
1359        assert_eq!(ts.time(), generate_time(0, 0, 0, 0));
1360
1361        let ts = generate_ts(9999, 1, 1, 23, 59, 59, 999999);
1362        assert_eq!(ts.date(), generate_date(9999, 1, 1));
1363        assert_eq!(ts.time(), generate_time(23, 59, 59, 999999));
1364
1365        let ts = generate_ts(9999, 12, 31, 0, 0, 0, 0);
1366        assert_eq!(ts.date(), generate_date(9999, 12, 31));
1367        assert_eq!(ts.time(), generate_time(0, 0, 0, 0));
1368
1369        let ts = generate_ts(9999, 12, 31, 23, 59, 59, 999999);
1370        assert_eq!(ts.date(), generate_date(9999, 12, 31));
1371        assert_eq!(ts.time(), generate_time(23, 59, 59, 999999));
1372    }
1373
1374    #[test]
1375    fn test_timestamp_add_sub_interval_dt() {
1376        // Normal add positive interval test
1377        let ts = generate_ts(2001, 3, 31, 12, 5, 6, 7);
1378        let interval = IntervalDT::try_from_dhms(1, 2, 3, 4, 5).unwrap();
1379        let expect = generate_ts(2001, 4, 1, 14, 8, 10, 12);
1380        assert_eq!(ts.add_interval_dt(interval).unwrap(), expect);
1381
1382        // Normal sub negative interval test
1383        let interval = -IntervalDT::try_from_dhms(1, 2, 3, 4, 5).unwrap();
1384        assert_eq!(ts.sub_interval_dt(interval).unwrap(), expect);
1385
1386        // Add positive interval with carry test
1387        let ts = generate_ts(2001, 12, 31, 23, 59, 59, 999999);
1388        let interval = IntervalDT::try_from_dhms(0, 0, 0, 0, 1).unwrap();
1389        let expect = generate_ts(2002, 1, 1, 0, 0, 0, 0);
1390        assert_eq!(ts.add_interval_dt(interval).unwrap(), expect);
1391
1392        // Sub negative interval with carry test
1393        let interval = -IntervalDT::try_from_dhms(0, 0, 0, 0, 1).unwrap();
1394        assert_eq!(ts.sub_interval_dt(interval).unwrap(), expect);
1395
1396        // Normal add negative interval test
1397        let ts = generate_ts(2001, 3, 31, 12, 5, 6, 7);
1398        let interval = -IntervalDT::try_from_dhms(1, 2, 3, 4, 5).unwrap();
1399        let expect = generate_ts(2001, 3, 30, 10, 2, 2, 2);
1400        assert_eq!(ts.add_interval_dt(interval).unwrap(), expect);
1401
1402        // Normal sub positive interval test
1403        let interval = IntervalDT::try_from_dhms(1, 2, 3, 4, 5).unwrap();
1404        assert_eq!(ts.sub_interval_dt(interval).unwrap(), expect);
1405
1406        // Add negative interval with carry test
1407        let ts = generate_ts(1970, 1, 1, 0, 0, 0, 0);
1408        let interval = -IntervalDT::try_from_dhms(0, 0, 0, 0, 1).unwrap();
1409        let expect = generate_ts(1969, 12, 31, 23, 59, 59, 999999);
1410        assert_eq!(ts.add_interval_dt(interval).unwrap(), expect);
1411
1412        // Sub positive interval with carry test
1413        let interval = IntervalDT::try_from_dhms(0, 0, 0, 0, 1).unwrap();
1414        assert_eq!(ts.sub_interval_dt(interval).unwrap(), expect);
1415
1416        // Boundary test
1417        let ts = generate_ts(9999, 12, 31, 23, 59, 59, 999999);
1418        let interval = IntervalDT::try_from_dhms(5, 4, 3, 2, 1).unwrap();
1419        let expect = generate_ts(9999, 12, 26, 19, 56, 57, 999998);
1420        assert_eq!(ts.sub_interval_dt(interval).unwrap(), expect);
1421
1422        let interval = IntervalDT::try_from_dhms(0, 0, 0, 0, 1).unwrap();
1423        assert!(ts.add_interval_dt(interval).is_err());
1424
1425        let interval = IntervalDT::try_from_dhms(12345, 12, 3, 5, 6).unwrap();
1426        assert!(ts.add_interval_dt(interval).is_err());
1427
1428        let ts = generate_ts(1, 1, 1, 0, 0, 0, 0);
1429        let interval = IntervalDT::try_from_dhms(5, 4, 3, 2, 1).unwrap();
1430        let expect = generate_ts(1, 1, 6, 4, 3, 2, 1);
1431        assert_eq!(ts.add_interval_dt(interval).unwrap(), expect);
1432
1433        let interval = IntervalDT::try_from_dhms(0, 0, 0, 0, 1).unwrap();
1434        assert!(ts.sub_interval_dt(interval).is_err());
1435
1436        let interval = IntervalDT::try_from_dhms(12345, 12, 3, 5, 6).unwrap();
1437        assert!(ts.sub_interval_dt(interval).is_err());
1438    }
1439
1440    #[test]
1441    fn test_timestamp_add_sub_interval_ym() {
1442        // Add positive
1443        let ts = generate_ts(2001, 3, 31, 12, 5, 6, 7);
1444        let interval = IntervalYM::try_from_ym(0, 2).unwrap();
1445        assert_eq!(
1446            ts.add_interval_ym(interval).unwrap(),
1447            generate_ts(2001, 5, 31, 12, 5, 6, 7)
1448        );
1449
1450        let interval = IntervalYM::try_from_ym(1, 2).unwrap();
1451        assert_eq!(
1452            ts.add_interval_ym(interval).unwrap(),
1453            generate_ts(2002, 5, 31, 12, 5, 6, 7)
1454        );
1455
1456        // Sub negative
1457        let ts = generate_ts(2001, 3, 31, 12, 5, 6, 7);
1458        let interval = IntervalYM::try_from_ym(0, 2).unwrap();
1459        assert_eq!(
1460            ts.sub_interval_ym(-interval).unwrap(),
1461            generate_ts(2001, 5, 31, 12, 5, 6, 7)
1462        );
1463
1464        let interval = IntervalYM::try_from_ym(1, 2).unwrap();
1465        assert_eq!(
1466            ts.sub_interval_ym(-interval).unwrap(),
1467            generate_ts(2002, 5, 31, 12, 5, 6, 7)
1468        );
1469
1470        // Sub positive
1471        let interval = IntervalYM::try_from_ym(0, 2).unwrap();
1472        assert_eq!(
1473            ts.sub_interval_ym(interval).unwrap(),
1474            generate_ts(2001, 1, 31, 12, 5, 6, 7)
1475        );
1476
1477        let interval = IntervalYM::try_from_ym(1, 2).unwrap();
1478        assert_eq!(
1479            ts.sub_interval_ym(interval).unwrap(),
1480            generate_ts(2000, 1, 31, 12, 5, 6, 7)
1481        );
1482
1483        // Add negative
1484        let interval = IntervalYM::try_from_ym(0, 2).unwrap();
1485        assert_eq!(
1486            ts.add_interval_ym(-interval).unwrap(),
1487            generate_ts(2001, 1, 31, 12, 5, 6, 7)
1488        );
1489
1490        let interval = IntervalYM::try_from_ym(1, 2).unwrap();
1491        assert_eq!(
1492            ts.add_interval_ym(-interval).unwrap(),
1493            generate_ts(2000, 1, 31, 12, 5, 6, 7)
1494        );
1495
1496        // Boundary test
1497        let upper_ts = generate_ts(9999, 12, 31, 23, 59, 59, 999999);
1498        let lower_ts = generate_ts(1, 1, 1, 0, 0, 0, 0);
1499        let interval = IntervalYM::try_from_ym(0, 1).unwrap();
1500
1501        assert!(upper_ts.add_interval_ym(interval).is_err());
1502        assert!(lower_ts.sub_interval_ym(interval).is_err());
1503
1504        // Month day overflow
1505        let interval = IntervalYM::try_from_ym(1, 1).unwrap();
1506        assert!(ts.add_interval_ym(interval).is_err());
1507
1508        let interval = IntervalYM::try_from_ym(0, 11).unwrap();
1509        assert!(ts.add_interval_ym(interval).is_err());
1510
1511        let interval = IntervalYM::try_from_ym(2, 11).unwrap();
1512        assert!(ts.add_interval_ym(interval).is_err());
1513
1514        let interval = IntervalYM::try_from_ym(1, 1).unwrap();
1515        assert!(ts.sub_interval_ym(-interval).is_err());
1516
1517        let interval = IntervalYM::try_from_ym(0, 11).unwrap();
1518        assert!(ts.sub_interval_ym(-interval).is_err());
1519
1520        let interval = IntervalYM::try_from_ym(2, 11).unwrap();
1521        assert!(ts.sub_interval_ym(-interval).is_err());
1522
1523        let interval = IntervalYM::try_from_ym(1, 1).unwrap();
1524        assert!(ts.sub_interval_ym(interval).is_err());
1525
1526        let interval = IntervalYM::try_from_ym(0, 11).unwrap();
1527        assert!(ts.sub_interval_ym(interval).is_err());
1528
1529        let interval = IntervalYM::try_from_ym(2, 1).unwrap();
1530        assert!(ts.sub_interval_ym(interval).is_err());
1531
1532        let interval = IntervalYM::try_from_ym(2, 1).unwrap();
1533        assert!(ts.sub_interval_ym(interval).is_err());
1534
1535        let interval = IntervalYM::try_from_ym(1, 1).unwrap();
1536        assert!(ts.add_interval_ym(-interval).is_err());
1537
1538        let interval = IntervalYM::try_from_ym(0, 11).unwrap();
1539        assert!(ts.add_interval_ym(-interval).is_err());
1540
1541        let interval = IntervalYM::try_from_ym(2, 1).unwrap();
1542        assert!(ts.add_interval_ym(-interval).is_err());
1543    }
1544
1545    #[test]
1546    fn test_timestamp_add_sub_time() {
1547        // Normal test
1548        let ts = generate_ts(1234, 5, 6, 7, 8, 9, 10);
1549        let time = Time::try_from_hms(1, 2, 3, 4).unwrap();
1550        let expect = generate_ts(1234, 5, 6, 8, 10, 12, 14);
1551        assert_eq!(ts.add_time(time).unwrap(), expect);
1552
1553        let expect = generate_ts(1234, 5, 6, 6, 6, 6, 6);
1554        assert_eq!(ts.sub_time(time).unwrap(), expect);
1555
1556        let time = Time::try_from_hms(23, 59, 59, 999999).unwrap();
1557        let expect = generate_ts(1234, 5, 7, 7, 8, 9, 9);
1558        assert_eq!(ts.add_time(time).unwrap(), expect);
1559
1560        let expect = generate_ts(1234, 5, 5, 7, 8, 9, 11);
1561        assert_eq!(ts.sub_time(time).unwrap(), expect);
1562
1563        // Boundary test
1564        let ts = generate_ts(9999, 12, 31, 23, 59, 59, 999999);
1565        let time = Time::try_from_hms(5, 4, 3, 2).unwrap();
1566        assert!(ts.add_time(time).is_err());
1567
1568        let time = Time::try_from_hms(0, 0, 0, 1).unwrap();
1569        assert!(ts.add_time(time).is_err());
1570
1571        let ts = generate_ts(1, 1, 1, 0, 0, 0, 0);
1572        let time = Time::try_from_hms(5, 4, 3, 2).unwrap();
1573        assert!(ts.sub_time(time).is_err());
1574
1575        let time = Time::try_from_hms(0, 0, 0, 1).unwrap();
1576        assert!(ts.sub_time(time).is_err());
1577    }
1578
1579    #[test]
1580    fn test_timestamp_sub_timestamp() {
1581        let upper_ts = generate_ts(9999, 12, 31, 23, 59, 59, 999999);
1582        let lower_ts = generate_ts(1, 1, 1, 0, 0, 0, 0);
1583        let ts = generate_ts(5000, 6, 15, 12, 30, 30, 500000);
1584
1585        assert_eq!(
1586            upper_ts.sub_timestamp(lower_ts),
1587            IntervalDT::try_from_dhms(3652058, 23, 59, 59, 999999).unwrap()
1588        );
1589
1590        assert_eq!(
1591            upper_ts.sub_timestamp(ts),
1592            IntervalDT::try_from_dhms(1826046, 11, 29, 29, 499999).unwrap()
1593        );
1594
1595        assert_eq!(
1596            lower_ts.sub_timestamp(upper_ts),
1597            -IntervalDT::try_from_dhms(3652058, 23, 59, 59, 999999).unwrap()
1598        );
1599    }
1600
1601    #[test]
1602    fn test_timestamp_sub_date() {
1603        let upper_ts = generate_ts(9999, 12, 31, 23, 59, 59, 999999);
1604        let lower_ts = generate_ts(1, 1, 1, 0, 0, 0, 0);
1605        let lower_date = Date::try_from_ymd(1, 1, 1).unwrap();
1606        let upper_date = Date::try_from_ymd(9999, 12, 31).unwrap();
1607        let date = Date::try_from_ymd(5000, 6, 15).unwrap();
1608
1609        assert_eq!(
1610            upper_ts.sub_date(lower_date),
1611            IntervalDT::try_from_dhms(3652058, 23, 59, 59, 999999).unwrap()
1612        );
1613
1614        assert_eq!(
1615            upper_ts.sub_date(date),
1616            IntervalDT::try_from_dhms(1826046, 23, 59, 59, 999999).unwrap()
1617        );
1618
1619        assert_eq!(
1620            lower_ts.sub_date(upper_date),
1621            -IntervalDT::try_from_dhms(3652058, 0, 0, 0, 0).unwrap()
1622        );
1623    }
1624
1625    #[test]
1626    fn test_timestamp_add_sub_days() {
1627        let upper_ts = generate_ts(9999, 12, 31, 23, 59, 59, 999999);
1628        let lower_ts = generate_ts(1, 1, 1, 0, 0, 0, 0);
1629
1630        // Out of range
1631        assert!(lower_ts.add_days(213435445784784.13).is_err());
1632        assert!(lower_ts.add_days(f64::NAN).is_err());
1633        assert!(lower_ts.add_days(f64::INFINITY).is_err());
1634        assert!(lower_ts.add_days(f64::NEG_INFINITY).is_err());
1635        assert!(lower_ts.add_days(f64::MAX).is_err());
1636        assert!(lower_ts.add_days(f64::MIN).is_err());
1637        assert!(upper_ts.add_days(0.0001).is_err());
1638
1639        assert!(lower_ts.sub_days(213435445784784.13).is_err());
1640        assert!(lower_ts.sub_days(f64::NAN).is_err());
1641        assert!(lower_ts.sub_days(f64::INFINITY).is_err());
1642        assert!(lower_ts.sub_days(f64::NEG_INFINITY).is_err());
1643        assert!(lower_ts.sub_days(f64::MAX).is_err());
1644        assert!(lower_ts.sub_days(f64::MIN).is_err());
1645        assert!(lower_ts.sub_days(0.0001).is_err());
1646
1647        // Round
1648        assert_eq!(
1649            lower_ts.add_days(1.123456789).unwrap(),
1650            generate_ts(1, 1, 2, 2, 57, 46, 666570)
1651        );
1652        assert_eq!(
1653            upper_ts.sub_days(1.123456789).unwrap(),
1654            generate_ts(9999, 12, 30, 21, 2, 13, 333429)
1655        );
1656
1657        // Normal
1658        assert_eq!(upper_ts.sub_days(0.0).unwrap(), upper_ts);
1659        assert_eq!(upper_ts.add_days(0.0).unwrap(), upper_ts);
1660        assert_eq!(
1661            upper_ts.sub_days(1.0).unwrap(),
1662            generate_ts(9999, 12, 30, 23, 59, 59, 999999)
1663        );
1664        assert_eq!(
1665            lower_ts.add_days(1.0).unwrap(),
1666            generate_ts(1, 1, 2, 0, 0, 0, 0)
1667        );
1668
1669        let ts = generate_ts(5000, 6, 15, 12, 30, 30, 555555);
1670        assert_eq!(ts.sub_days(1.12).unwrap(), ts.add_days(-1.12).unwrap());
1671        assert_eq!(ts.sub_days(-1.12).unwrap(), ts.add_days(1.12).unwrap());
1672    }
1673
1674    #[test]
1675    fn test_timestamp_cmp_date() {
1676        let ts = generate_ts(1970, 1, 1, 1, 1, 1, 1);
1677        let date = generate_date(1970, 1, 1);
1678        assert!(ts > date);
1679        let ts = generate_ts(1970, 1, 1, 0, 0, 0, 0);
1680        assert!(ts == date);
1681    }
1682
1683    #[allow(clippy::float_cmp)]
1684    fn test_extract(year: i32, month: u32, day: u32, hour: u32, min: u32, sec: u32, usec: u32) {
1685        let ts = generate_ts(year, month, day, hour, min, sec, usec);
1686        assert_eq!(year, ts.year().unwrap());
1687        assert_eq!(month as i32, ts.month().unwrap());
1688        assert_eq!(day as i32, ts.day().unwrap());
1689        assert_eq!(hour as i32, ts.hour().unwrap());
1690        assert_eq!(min as i32, ts.minute().unwrap());
1691        assert_eq!(
1692            (sec as f64 + (usec as f64) / 1_000_000f64),
1693            ts.second().unwrap()
1694        );
1695    }
1696
1697    #[test]
1698    fn test_timestamp_extract() {
1699        test_extract(1960, 12, 31, 23, 59, 59, 999999);
1700        test_extract(1, 1, 1, 0, 0, 0, 0);
1701        test_extract(1, 1, 1, 1, 1, 1, 1);
1702        test_extract(1969, 12, 31, 1, 2, 3, 4);
1703        test_extract(1969, 12, 30, 23, 59, 59, 999999);
1704        test_extract(1969, 12, 30, 0, 0, 0, 0);
1705        test_extract(1970, 1, 1, 0, 0, 0, 0);
1706        test_extract(1970, 1, 1, 12, 30, 30, 30);
1707        test_extract(1999, 10, 21, 12, 30, 30, 30);
1708        test_extract(9999, 12, 31, 23, 59, 59, 999999);
1709    }
1710
1711    #[test]
1712    fn test_now() {
1713        let now = Local::now();
1714        let dt = Timestamp::now().unwrap();
1715        assert_eq!(now.year(), dt.year().unwrap());
1716        assert_eq!(now.month() as i32, dt.month().unwrap());
1717        assert_eq!(now.day() as i32, dt.day().unwrap());
1718        assert_eq!(now.hour() as i32, dt.hour().unwrap());
1719    }
1720
1721    #[test]
1722    fn test_round_error() {
1723        let ts = generate_ts(DATE_MAX_YEAR, 12, 31, 23, 59, 30, 0);
1724
1725        // Would not overflow
1726        assert!(ts.round_century().is_err());
1727        assert!(ts.round_year().is_err());
1728        assert!(ts.round_iso_year().is_err());
1729        assert!(ts.round_quarter().is_err());
1730        assert!(ts.round_month().is_err());
1731        assert!(ts.round_week().is_err());
1732        assert!(ts.round_iso_week().is_err());
1733        assert!(ts.round_month_start_week().is_err());
1734        assert!(ts.round_day().is_err());
1735        assert!(ts.round_sunday_start_week().is_err());
1736        assert!(ts.round_hour().is_err());
1737        assert!(ts.round_minute().is_err());
1738    }
1739
1740    #[test]
1741    fn test_trunc() {
1742        let ts = generate_ts(1996, 10, 24, 0, 0, 0, 0);
1743
1744        // Century
1745        assert_eq!(
1746            generate_ts(1901, 1, 1, 0, 0, 0, 0),
1747            ts.trunc_century().unwrap()
1748        );
1749        assert_eq!(
1750            generate_ts(1801, 1, 1, 0, 0, 0, 0),
1751            generate_ts(1900, 10, 24, 0, 0, 0, 0)
1752                .trunc_century()
1753                .unwrap()
1754        );
1755
1756        // Year
1757        assert_eq!(
1758            generate_ts(1996, 1, 1, 0, 0, 0, 0),
1759            ts.trunc_year().unwrap()
1760        );
1761
1762        // ISO Year
1763        assert_eq!(
1764            generate_ts(1996, 1, 1, 0, 0, 0, 0),
1765            ts.trunc_iso_year().unwrap()
1766        );
1767        assert_eq!(
1768            generate_ts(2021, 1, 4, 0, 0, 0, 0),
1769            generate_ts(2021, 10, 24, 0, 0, 0, 0)
1770                .trunc_iso_year()
1771                .unwrap()
1772        );
1773
1774        // Quarter
1775        assert_eq!(
1776            generate_ts(1996, 10, 1, 0, 0, 0, 0),
1777            ts.trunc_quarter().unwrap()
1778        );
1779
1780        // Month
1781        assert_eq!(
1782            generate_ts(1996, 10, 1, 0, 0, 0, 0),
1783            ts.trunc_month().unwrap()
1784        );
1785
1786        // Week
1787        assert_eq!(
1788            generate_ts(1996, 10, 21, 0, 0, 0, 0),
1789            ts.trunc_week().unwrap()
1790        );
1791
1792        // ISO Week
1793        assert_eq!(
1794            generate_ts(1996, 10, 21, 0, 0, 0, 0),
1795            ts.trunc_iso_week().unwrap()
1796        );
1797
1798        // The first day of the month as the first day of week
1799        assert_eq!(
1800            generate_ts(1996, 10, 22, 0, 0, 0, 0),
1801            ts.trunc_month_start_week().unwrap()
1802        );
1803
1804        // Day
1805        assert_eq!(
1806            generate_ts(1996, 10, 24, 0, 0, 0, 0),
1807            ts.trunc_day().unwrap()
1808        );
1809
1810        // Start day of the week
1811        assert_eq!(
1812            generate_ts(1996, 10, 20, 0, 0, 0, 0),
1813            ts.trunc_sunday_start_week().unwrap()
1814        );
1815
1816        // Hour
1817        assert_eq!(
1818            generate_ts(2015, 4, 11, 13, 0, 0, 0),
1819            generate_ts(2015, 4, 11, 13, 59, 59, 0)
1820                .trunc_hour()
1821                .unwrap()
1822        );
1823
1824        // Minute
1825        assert_eq!(
1826            generate_ts(2015, 4, 11, 13, 59, 0, 0),
1827            generate_ts(2015, 4, 11, 13, 59, 59, 0)
1828                .trunc_minute()
1829                .unwrap()
1830        );
1831    }
1832
1833    #[test]
1834    fn test_round() {
1835        let ts = generate_ts(1996, 10, 24, 0, 0, 0, 0);
1836
1837        assert_eq!(
1838            generate_ts(2001, 1, 1, 0, 0, 0, 0),
1839            ts.round_century().unwrap()
1840        );
1841        assert_eq!(
1842            generate_ts(1901, 1, 1, 0, 0, 0, 0),
1843            generate_ts(2000, 1, 1, 0, 0, 0, 0).round_century().unwrap()
1844        );
1845        assert_eq!(
1846            generate_ts(1997, 1, 1, 0, 0, 0, 0),
1847            ts.round_year().unwrap()
1848        );
1849        assert_eq!(
1850            generate_ts(1996, 12, 30, 0, 0, 0, 0),
1851            ts.round_iso_year().unwrap()
1852        );
1853        assert_eq!(
1854            generate_ts(1996, 10, 1, 0, 0, 0, 0),
1855            ts.round_quarter().unwrap()
1856        );
1857        assert_eq!(
1858            generate_ts(2022, 1, 1, 0, 0, 0, 0),
1859            generate_ts(2021, 11, 16, 0, 0, 0, 0)
1860                .round_quarter()
1861                .unwrap()
1862        );
1863        assert_eq!(
1864            generate_ts(2021, 10, 1, 0, 0, 0, 0),
1865            generate_ts(2021, 9, 1, 0, 0, 0, 0).round_quarter().unwrap()
1866        );
1867        assert_eq!(
1868            generate_ts(2022, 1, 1, 0, 0, 0, 0),
1869            generate_ts(2021, 12, 1, 0, 0, 0, 0)
1870                .round_quarter()
1871                .unwrap()
1872        );
1873        assert_eq!(
1874            generate_ts(1996, 11, 1, 0, 0, 0, 0),
1875            ts.round_month().unwrap()
1876        );
1877
1878        // No hour
1879        assert_eq!(
1880            generate_ts(2021, 10, 15, 0, 0, 0, 0),
1881            generate_ts(2021, 10, 13, 0, 0, 0, 0).round_week().unwrap()
1882        );
1883        assert_eq!(
1884            generate_ts(2021, 1, 1, 0, 0, 0, 0),
1885            generate_ts(2021, 1, 1, 0, 0, 0, 0).round_week().unwrap()
1886        );
1887        assert_eq!(
1888            generate_ts(2021, 12, 31, 0, 0, 0, 0),
1889            generate_ts(2021, 12, 31, 0, 0, 0, 0).round_week().unwrap()
1890        );
1891        // Round day by hour
1892        // Change date in the same month
1893        assert_eq!(
1894            generate_ts(2021, 1, 1, 0, 0, 0, 0),
1895            generate_ts(2021, 1, 4, 11, 59, 59, 59)
1896                .round_week()
1897                .unwrap()
1898        );
1899        assert_eq!(
1900            generate_ts(2021, 1, 8, 0, 0, 0, 0),
1901            generate_ts(2021, 1, 4, 12, 0, 0, 0).round_week().unwrap()
1902        );
1903        // Round month
1904        assert_eq!(
1905            generate_ts(2021, 1, 29, 0, 0, 0, 0),
1906            generate_ts(2021, 2, 1, 11, 59, 59, 59)
1907                .round_week()
1908                .unwrap()
1909        );
1910        assert_eq!(
1911            generate_ts(2021, 2, 5, 0, 0, 0, 0),
1912            generate_ts(2021, 2, 1, 12, 0, 0, 0).round_week().unwrap()
1913        );
1914        // Round to next year
1915        assert_eq!(
1916            generate_ts(2021, 12, 31, 0, 0, 0, 0),
1917            generate_ts(2021, 12, 31, 11, 59, 59, 59)
1918                .round_week()
1919                .unwrap()
1920        );
1921        assert_eq!(
1922            generate_ts(2022, 1, 1, 0, 0, 0, 0),
1923            generate_ts(2021, 12, 31, 12, 0, 0, 0).round_week().unwrap()
1924        );
1925
1926        // No hour
1927        assert_eq!(
1928            generate_ts(2021, 10, 18, 0, 0, 0, 0),
1929            generate_ts(2021, 10, 15, 0, 0, 0, 0)
1930                .round_iso_week()
1931                .unwrap()
1932        );
1933        // Round day by hour
1934        // Change date in the same month
1935        assert_eq!(
1936            generate_ts(2021, 10, 11, 0, 0, 0, 0),
1937            generate_ts(2021, 10, 14, 11, 59, 59, 59)
1938                .round_iso_week()
1939                .unwrap()
1940        );
1941        assert_eq!(
1942            generate_ts(2021, 10, 18, 0, 0, 0, 0),
1943            generate_ts(2021, 10, 15, 12, 0, 0, 0)
1944                .round_iso_week()
1945                .unwrap()
1946        );
1947        // Round month
1948        assert_eq!(
1949            generate_ts(2021, 2, 22, 0, 0, 0, 0),
1950            generate_ts(2021, 2, 25, 11, 59, 59, 59)
1951                .round_iso_week()
1952                .unwrap()
1953        );
1954        assert_eq!(
1955            generate_ts(2021, 3, 1, 0, 0, 0, 0),
1956            generate_ts(2021, 2, 25, 12, 0, 0, 0)
1957                .round_iso_week()
1958                .unwrap()
1959        );
1960        // Round Year
1961        assert_eq!(
1962            generate_ts(2021, 12, 27, 0, 0, 0, 0),
1963            generate_ts(2021, 12, 30, 11, 59, 59, 59)
1964                .round_iso_week()
1965                .unwrap()
1966        );
1967        assert_eq!(
1968            generate_ts(2022, 1, 3, 0, 0, 0, 0),
1969            generate_ts(2021, 12, 30, 12, 0, 0, 0)
1970                .round_iso_week()
1971                .unwrap()
1972        );
1973
1974        // No hour
1975        assert_eq!(
1976            generate_ts(2021, 11, 8, 0, 0, 0, 0),
1977            generate_ts(2021, 11, 5, 0, 0, 0, 0)
1978                .round_month_start_week()
1979                .unwrap()
1980        );
1981        // Round day by hour
1982        // Change date in the same month
1983        assert_eq!(
1984            generate_ts(2021, 11, 1, 0, 0, 0, 0),
1985            generate_ts(2021, 11, 4, 11, 59, 59, 59)
1986                .round_month_start_week()
1987                .unwrap()
1988        );
1989        assert_eq!(
1990            generate_ts(2021, 11, 8, 0, 0, 0, 0),
1991            generate_ts(2021, 11, 4, 12, 0, 0, 0)
1992                .round_month_start_week()
1993                .unwrap()
1994        );
1995        // Round to next month
1996        assert_eq!(
1997            generate_ts(2021, 11, 29, 0, 0, 0, 0),
1998            generate_ts(2021, 11, 30, 11, 59, 59, 59)
1999                .round_month_start_week()
2000                .unwrap()
2001        );
2002        assert_eq!(
2003            generate_ts(2021, 12, 1, 0, 0, 0, 0),
2004            generate_ts(2021, 11, 30, 12, 0, 0, 0)
2005                .round_month_start_week()
2006                .unwrap()
2007        );
2008        // Round to next year
2009        assert_eq!(
2010            generate_ts(2021, 12, 29, 0, 0, 0, 0),
2011            generate_ts(2021, 12, 31, 11, 59, 59, 59)
2012                .round_month_start_week()
2013                .unwrap()
2014        );
2015        assert_eq!(
2016            generate_ts(2022, 1, 1, 0, 0, 0, 0),
2017            generate_ts(2021, 12, 31, 12, 0, 0, 0)
2018                .round_month_start_week()
2019                .unwrap()
2020        );
2021
2022        assert_eq!(
2023            generate_ts(1996, 10, 25, 0, 0, 0, 0),
2024            generate_ts(1996, 10, 24, 12, 0, 0, 0).round_day().unwrap()
2025        );
2026
2027        // No hour
2028        assert_eq!(
2029            generate_ts(1996, 10, 27, 0, 0, 0, 0),
2030            ts.round_sunday_start_week().unwrap()
2031        );
2032        // Round day by hour
2033        // Change date in the same month
2034        assert_eq!(
2035            generate_ts(2021, 10, 10, 0, 0, 0, 0),
2036            generate_ts(2021, 10, 13, 11, 59, 59, 59)
2037                .round_sunday_start_week()
2038                .unwrap()
2039        );
2040        assert_eq!(
2041            generate_ts(2021, 10, 17, 0, 0, 0, 0),
2042            generate_ts(2021, 10, 13, 12, 0, 0, 0)
2043                .round_sunday_start_week()
2044                .unwrap()
2045        );
2046        // Round month
2047        assert_eq!(
2048            generate_ts(2021, 3, 28, 0, 0, 0, 0),
2049            generate_ts(2021, 3, 31, 11, 59, 59, 59)
2050                .round_sunday_start_week()
2051                .unwrap()
2052        );
2053        assert_eq!(
2054            generate_ts(2021, 4, 4, 0, 0, 0, 0),
2055            generate_ts(2021, 3, 31, 12, 0, 0, 0)
2056                .round_sunday_start_week()
2057                .unwrap()
2058        );
2059        // Round Year
2060        assert_eq!(
2061            generate_ts(2021, 12, 26, 0, 0, 0, 0),
2062            generate_ts(2021, 12, 29, 11, 59, 59, 59)
2063                .round_sunday_start_week()
2064                .unwrap()
2065        );
2066        assert_eq!(
2067            generate_ts(2022, 1, 2, 0, 0, 0, 0),
2068            generate_ts(2021, 12, 29, 12, 0, 0, 0)
2069                .round_sunday_start_week()
2070                .unwrap()
2071        );
2072
2073        assert_eq!(
2074            generate_ts(2015, 3, 3, 12, 0, 0, 0),
2075            generate_ts(2015, 3, 3, 11, 30, 59, 0).round_hour().unwrap()
2076        );
2077        assert_eq!(
2078            generate_ts(2015, 3, 4, 0, 0, 0, 0),
2079            generate_ts(2015, 3, 3, 23, 30, 0, 0).round_hour().unwrap()
2080        );
2081        assert_eq!(
2082            generate_ts(2015, 3, 3, 11, 30, 0, 0),
2083            generate_ts(2015, 3, 3, 11, 29, 30, 0)
2084                .round_minute()
2085                .unwrap()
2086        );
2087        assert_eq!(
2088            generate_ts(2015, 3, 4, 0, 0, 0, 0),
2089            generate_ts(2015, 3, 3, 23, 59, 30, 0)
2090                .round_minute()
2091                .unwrap()
2092        );
2093    }
2094
2095    #[test]
2096    fn test_last_day_of_month() {
2097        assert_eq!(
2098            generate_ts(2021, 9, 23, 14, 15, 16, 17).last_day_of_month(),
2099            generate_ts(2021, 9, 30, 14, 15, 16, 17)
2100        );
2101        assert_eq!(
2102            generate_ts(1970, 1, 1, 0, 0, 0, 0).last_day_of_month(),
2103            generate_ts(1970, 1, 31, 0, 0, 0, 0)
2104        );
2105        assert_eq!(
2106            generate_ts(1704, 2, 1, 23, 59, 59, 999999).last_day_of_month(),
2107            generate_ts(1704, 2, 29, 23, 59, 59, 999999)
2108        );
2109        assert_eq!(
2110            generate_ts(1705, 2, 10, 20, 40, 50, 56789).last_day_of_month(),
2111            generate_ts(1705, 2, 28, 20, 40, 50, 56789)
2112        );
2113        assert_eq!(
2114            generate_ts(1, 1, 1, 0, 0, 0, 0).last_day_of_month(),
2115            generate_ts(1, 1, 31, 0, 0, 0, 0)
2116        );
2117        assert_eq!(
2118            generate_ts(9999, 12, 31, 23, 59, 59, 999999).last_day_of_month(),
2119            generate_ts(9999, 12, 31, 23, 59, 59, 999999)
2120        );
2121    }
2122
2123    #[test]
2124    fn test_iso_format() {
2125        const FMT: &str = "YYYY-MM-DDTHH24:MI:SS.FF";
2126        fn assert_iso_fmt(input: &str, output: &str) {
2127            let ts = Timestamp::parse(input, FMT).unwrap();
2128            assert_eq!(format!("{}", ts.format(FMT).unwrap()), output);
2129        }
2130
2131        fn assert_invalid_iso_str(input: &str) {
2132            assert!(Timestamp::parse(input, FMT).is_err());
2133        }
2134
2135        assert_invalid_iso_str("2023-05-26 23:59");
2136        assert_invalid_iso_str("2023-05-26T");
2137        assert_invalid_iso_str("2023-05-26T ");
2138        assert_invalid_iso_str("2023-05-26 T");
2139
2140        assert_iso_fmt("2023-05-26", "2023-05-26T00:00:00");
2141        assert_iso_fmt("2023-05-26 ", "2023-05-26T00:00:00");
2142        assert_iso_fmt("2023-05-2600:00:01", "2023-05-26T00:00:01");
2143        assert_iso_fmt("2023-05-26 00:00:01", "2023-05-26T00:00:01");
2144        assert_iso_fmt("2023-05-26 T00:00:01", "2023-05-26T00:00:01");
2145        assert_iso_fmt("2023-05-26T 00:00:01", "2023-05-26T00:00:01");
2146        assert_iso_fmt("2023-05-26 T 00:00:01", "2023-05-26T00:00:01");
2147        assert_iso_fmt("2023-05-26  ", "2023-05-26T00:00:00");
2148        assert_iso_fmt("2023-05-26  00:00:01", "2023-05-26T00:00:01");
2149        assert_iso_fmt("2023-05-26               00:00:01", "2023-05-26T00:00:01");
2150        assert_iso_fmt("2023-05-26T00:00:00", "2023-05-26T00:00:00");
2151        assert_iso_fmt("2023-05-26T00:00:00.000", "2023-05-26T00:00:00");
2152        assert_iso_fmt("2023-05-26T00:00:00.123000", "2023-05-26T00:00:00.123000");
2153        assert_iso_fmt("2023-05-26T00:00:00.123456", "2023-05-26T00:00:00.123456");
2154        assert_iso_fmt(
2155            "2023-05-26T00:00:00.123456789",
2156            "2023-05-26T00:00:00.123457",
2157        );
2158        assert_iso_fmt("2023-05-26T00:00:00Z", "2023-05-26T00:00:00");
2159        assert_iso_fmt("2023-05-26T00:00:00.123Z", "2023-05-26T00:00:00.123000");
2160
2161        assert_invalid_iso_str("2023-05");
2162        assert_invalid_iso_str("2023-05-26T00");
2163        assert_invalid_iso_str("2023-05-26T00:00");
2164        assert_invalid_iso_str("2023-05-26T00:00:");
2165        assert_invalid_iso_str("2023-05-26T00:00.123");
2166        assert_invalid_iso_str("2023-05Z");
2167        assert_invalid_iso_str("2023-05-26T00Z");
2168        assert_invalid_iso_str("2023-05-26T00:00Z");
2169        assert_invalid_iso_str("2023-05-26T00:00:Z");
2170        assert_invalid_iso_str("2023-05-26T00:00.123Z");
2171    }
2172}