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#[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 pub const MIN: Self = Date(Timestamp::MIN);
23
24 pub const MAX: Self = Date(Timestamp::new(SqlDate::MAX, unsafe {
26 Time::from_hms_unchecked(23, 59, 59, 0)
27 }));
28
29 #[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 #[inline(always)]
44 pub const fn usecs(self) -> i64 {
45 self.0.usecs()
46 }
47
48 #[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 #[inline(always)]
70 pub const unsafe fn from_usecs_unchecked(usecs: i64) -> Self {
71 Date(Timestamp::from_usecs_unchecked(usecs))
72 }
73
74 #[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 #[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 #[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 #[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 #[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 #[inline]
117 pub const fn add_time(self, time: Time) -> Result<Timestamp> {
118 self.0.add_time(time)
119 }
120
121 #[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 #[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 #[inline]
139 pub fn sub_timestamp(self, timestamp: Timestamp) -> IntervalDT {
140 self.0.sub_timestamp(timestamp)
141 }
142
143 #[inline]
145 pub fn sub_interval_dt(self, interval: IntervalDT) -> Result<Date> {
146 self.add_interval_dt(-interval)
147 }
148
149 #[inline]
151 pub const fn sub_time(self, time: Time) -> Result<Timestamp> {
152 self.0.sub_time(time)
153 }
154
155 #[inline]
157 pub fn sub_interval_ym(self, interval: IntervalYM) -> Result<Date> {
158 self.add_interval_ym(-interval)
159 }
160
161 #[inline]
163 pub fn sub_days(self, days: f64) -> Result<Date> {
164 self.add_days(-days)
165 }
166
167 #[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 #[inline]
179 pub fn last_day_of_month(self) -> Date {
180 self.0.last_day_of_month().into()
181 }
182
183 #[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 #[inline]
334 pub const fn oracle_sub_date(self, date: Date) -> IntervalDT {
335 self.sub_timestamp(date.0)
336 }
337
338 #[inline]
340 pub fn oracle_add_days(self, days: f64) -> Result<Date> {
341 Date::from(self).add_days(days)
342 }
343
344 #[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 {
666 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 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 {
692 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 }
719
720 {
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 {
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 {
776 assert!(Date::parse("2022-4", "yyyy-mm-dd").is_err());
777 }
778
779 {
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 {
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 {
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 {
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 {
929 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 }
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 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 let interval = -IntervalDT::try_from_dhms(1, 2, 3, 4, 5).unwrap();
1052 assert_eq!(date.sub_interval_dt(interval).unwrap(), expect);
1053
1054 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 let interval = -IntervalDT::try_from_dhms(0, 0, 0, 1, 1).unwrap();
1062 assert_eq!(date.sub_interval_dt(interval).unwrap(), expect);
1063
1064 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 let interval = IntervalDT::try_from_dhms(1, 2, 3, 4, 5).unwrap();
1072 assert_eq!(date.sub_interval_dt(interval).unwrap(), expect);
1073
1074 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 let interval = IntervalDT::try_from_dhms(0, 0, 0, 0, 1).unwrap();
1082 assert_eq!(date.sub_interval_dt(interval).unwrap(), expect);
1083
1084 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 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 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 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 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 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 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 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 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 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 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 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 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}