1use core::default::Default;
16use std::cmp::Ordering;
17use std::fmt::{self, Display, Formatter, Write};
18use std::hash::{Hash, Hasher};
19use std::time::Duration;
20
21use arrow::datatypes::TimeUnit as ArrowTimeUnit;
22use chrono::{
23 DateTime, Days, LocalResult, Months, NaiveDate, NaiveDateTime, NaiveTime, TimeDelta,
24 TimeZone as ChronoTimeZone, Utc,
25};
26use serde::{Deserialize, Serialize};
27use snafu::{OptionExt, ResultExt};
28
29use crate::error;
30use crate::error::{ArithmeticOverflowSnafu, ParseTimestampSnafu, Result, TimestampOverflowSnafu};
31use crate::interval::{IntervalDayTime, IntervalMonthDayNano, IntervalYearMonth};
32use crate::timezone::{get_timezone, Timezone};
33use crate::util::{datetime_to_utc, div_ceil};
34
35#[derive(Clone, Default, Copy, Serialize, Deserialize)]
46pub struct Timestamp {
47 value: i64,
48 unit: TimeUnit,
49}
50
51impl Timestamp {
52 pub fn current_millis() -> Self {
54 Self {
55 value: crate::util::current_time_millis(),
56 unit: TimeUnit::Millisecond,
57 }
58 }
59
60 pub fn current_time(unit: TimeUnit) -> Timestamp {
62 let now = chrono::Utc::now();
63 let value = match unit {
64 TimeUnit::Second => now.timestamp(),
65 TimeUnit::Millisecond => now.timestamp_millis(),
66 TimeUnit::Microsecond => now.timestamp_micros(),
67 TimeUnit::Nanosecond => now.timestamp_nanos_opt().unwrap_or_default(),
68 };
69 Timestamp { value, unit }
70 }
71
72 pub fn sub_duration(&self, duration: Duration) -> error::Result<Self> {
78 let duration: i64 = match self.unit {
79 TimeUnit::Second => {
80 i64::try_from(duration.as_secs()).context(TimestampOverflowSnafu)?
81 }
82 TimeUnit::Millisecond => {
83 i64::try_from(duration.as_millis()).context(TimestampOverflowSnafu)?
84 }
85 TimeUnit::Microsecond => {
86 i64::try_from(duration.as_micros()).context(TimestampOverflowSnafu)?
87 }
88 TimeUnit::Nanosecond => {
89 i64::try_from(duration.as_nanos()).context(TimestampOverflowSnafu)?
90 }
91 };
92
93 let value = self
94 .value
95 .checked_sub(duration)
96 .with_context(|| ArithmeticOverflowSnafu {
97 msg: format!(
98 "Try to subtract timestamp: {:?} with duration: {:?}",
99 self, duration
100 ),
101 })?;
102 Ok(Timestamp {
103 value,
104 unit: self.unit,
105 })
106 }
107
108 pub fn add_duration(&self, duration: Duration) -> error::Result<Self> {
114 let duration: i64 = match self.unit {
115 TimeUnit::Second => {
116 i64::try_from(duration.as_secs()).context(TimestampOverflowSnafu)?
117 }
118 TimeUnit::Millisecond => {
119 i64::try_from(duration.as_millis()).context(TimestampOverflowSnafu)?
120 }
121 TimeUnit::Microsecond => {
122 i64::try_from(duration.as_micros()).context(TimestampOverflowSnafu)?
123 }
124 TimeUnit::Nanosecond => {
125 i64::try_from(duration.as_nanos()).context(TimestampOverflowSnafu)?
126 }
127 };
128
129 let value = self
130 .value
131 .checked_add(duration)
132 .with_context(|| ArithmeticOverflowSnafu {
133 msg: format!(
134 "Try to add timestamp: {:?} with duration: {:?}",
135 self, duration
136 ),
137 })?;
138 Ok(Timestamp {
139 value,
140 unit: self.unit,
141 })
142 }
143
144 pub fn add_year_month(&self, interval: IntervalYearMonth) -> Option<Timestamp> {
147 let naive_datetime = self.to_chrono_datetime()?;
148
149 let naive_datetime =
150 naive_datetime.checked_add_months(Months::new(interval.months as u32))?;
151
152 Timestamp::from_chrono_datetime(naive_datetime).and_then(|ts| ts.convert_to(self.unit))
154 }
155
156 pub fn add_day_time(&self, interval: IntervalDayTime) -> Option<Timestamp> {
158 let naive_datetime = self.to_chrono_datetime()?;
159
160 let naive_datetime = naive_datetime
161 .checked_add_days(Days::new(interval.days as u64))?
162 .checked_add_signed(TimeDelta::milliseconds(interval.milliseconds as i64))?;
163
164 Timestamp::from_chrono_datetime(naive_datetime).and_then(|ts| ts.convert_to(self.unit))
166 }
167
168 pub fn add_month_day_nano(&self, interval: IntervalMonthDayNano) -> Option<Timestamp> {
170 let naive_datetime = self.to_chrono_datetime()?;
171
172 let naive_datetime = naive_datetime
173 .checked_add_months(Months::new(interval.months as u32))?
174 .checked_add_days(Days::new(interval.days as u64))?
175 .checked_add_signed(TimeDelta::nanoseconds(interval.nanoseconds))?;
176
177 Timestamp::from_chrono_datetime(naive_datetime).and_then(|ts| ts.convert_to(self.unit))
179 }
180
181 pub fn sub_year_month(&self, interval: IntervalYearMonth) -> Option<Timestamp> {
183 let naive_datetime = self.to_chrono_datetime()?;
184
185 let naive_datetime =
186 naive_datetime.checked_sub_months(Months::new(interval.months as u32))?;
187
188 Timestamp::from_chrono_datetime(naive_datetime).and_then(|ts| ts.convert_to(self.unit))
190 }
191
192 pub fn sub_day_time(&self, interval: IntervalDayTime) -> Option<Timestamp> {
194 let naive_datetime = self.to_chrono_datetime()?;
195
196 let naive_datetime = naive_datetime
197 .checked_sub_days(Days::new(interval.days as u64))?
198 .checked_sub_signed(TimeDelta::milliseconds(interval.milliseconds as i64))?;
199
200 Timestamp::from_chrono_datetime(naive_datetime).and_then(|ts| ts.convert_to(self.unit))
202 }
203
204 pub fn sub_month_day_nano(&self, interval: IntervalMonthDayNano) -> Option<Timestamp> {
206 let naive_datetime = self.to_chrono_datetime()?;
207
208 let naive_datetime = naive_datetime
209 .checked_sub_months(Months::new(interval.months as u32))?
210 .checked_sub_days(Days::new(interval.days as u64))?
211 .checked_sub_signed(TimeDelta::nanoseconds(interval.nanoseconds))?;
212
213 Timestamp::from_chrono_datetime(naive_datetime).and_then(|ts| ts.convert_to(self.unit))
215 }
216
217 pub fn sub(&self, rhs: &Self) -> Option<chrono::Duration> {
219 let lhs = self.to_chrono_datetime()?;
220 let rhs = rhs.to_chrono_datetime()?;
221 Some(lhs - rhs)
222 }
223
224 pub fn new(value: i64, unit: TimeUnit) -> Self {
225 Self { unit, value }
226 }
227
228 pub const fn new_second(value: i64) -> Self {
229 Self {
230 value,
231 unit: TimeUnit::Second,
232 }
233 }
234
235 pub const fn new_millisecond(value: i64) -> Self {
236 Self {
237 value,
238 unit: TimeUnit::Millisecond,
239 }
240 }
241
242 pub const fn new_microsecond(value: i64) -> Self {
243 Self {
244 value,
245 unit: TimeUnit::Microsecond,
246 }
247 }
248
249 pub const fn new_nanosecond(value: i64) -> Self {
250 Self {
251 value,
252 unit: TimeUnit::Nanosecond,
253 }
254 }
255
256 pub fn unit(&self) -> TimeUnit {
257 self.unit
258 }
259
260 pub fn value(&self) -> i64 {
261 self.value
262 }
263
264 pub fn convert_to(&self, unit: TimeUnit) -> Option<Timestamp> {
268 if self.unit().factor() >= unit.factor() {
269 let mul = self.unit().factor() / unit.factor();
270 let value = self.value.checked_mul(mul as i64)?;
271 Some(Timestamp::new(value, unit))
272 } else {
273 let mul = unit.factor() / self.unit().factor();
274 Some(Timestamp::new(self.value.div_euclid(mul as i64), unit))
275 }
276 }
277
278 pub fn convert_to_ceil(&self, unit: TimeUnit) -> Option<Timestamp> {
283 if self.unit().factor() >= unit.factor() {
284 let mul = self.unit().factor() / unit.factor();
285 let value = self.value.checked_mul(mul as i64)?;
286 Some(Timestamp::new(value, unit))
287 } else {
288 let mul = unit.factor() / self.unit().factor();
289 Some(Timestamp::new(div_ceil(self.value, mul as i64), unit))
290 }
291 }
292
293 pub fn split(&self) -> (i64, u32) {
296 let sec_mul = (TimeUnit::Second.factor() / self.unit.factor()) as i64;
297 let nsec_mul = (self.unit.factor() / TimeUnit::Nanosecond.factor()) as i64;
298
299 let sec_div = self.value.div_euclid(sec_mul);
300 let sec_mod = self.value.rem_euclid(sec_mul);
301 let nsec = u32::try_from(sec_mod * nsec_mul).unwrap();
303 (sec_div, nsec)
304 }
305
306 fn from_splits(sec: i64, nsec: u32) -> Option<Self> {
309 if nsec == 0 {
310 Some(Timestamp::new_second(sec))
311 } else if nsec % 1_000_000 == 0 {
312 let millis = nsec / 1_000_000;
313 sec.checked_mul(1000)
314 .and_then(|v| v.checked_add(millis as i64))
315 .map(Timestamp::new_millisecond)
316 } else if nsec % 1000 == 0 {
317 let micros = nsec / 1000;
318 sec.checked_mul(1_000_000)
319 .and_then(|v| v.checked_add(micros as i64))
320 .map(Timestamp::new_microsecond)
321 } else {
322 let mut sec = sec;
334 let mut nsec = nsec as i64;
335 if sec < 0 && nsec > 0 {
336 nsec -= 1_000_000_000;
337 sec += 1;
338 }
339
340 sec.checked_mul(1_000_000_000)
341 .and_then(|v| v.checked_add(nsec))
342 .map(Timestamp::new_nanosecond)
343 }
344 }
345
346 pub fn to_iso8601_string(&self) -> String {
349 self.as_formatted_string("%Y-%m-%d %H:%M:%S%.f%z", None)
351 .unwrap()
352 }
353
354 pub fn to_local_string(&self) -> String {
356 self.as_formatted_string("%Y-%m-%d %H:%M:%S%.f", None)
358 .unwrap()
359 }
360
361 pub fn to_timezone_aware_string(&self, tz: Option<&Timezone>) -> String {
364 self.as_formatted_string("%Y-%m-%d %H:%M:%S%.f", tz)
366 .unwrap()
367 }
368
369 pub fn as_formatted_string(self, pattern: &str, timezone: Option<&Timezone>) -> Result<String> {
372 if let Some(v) = self.to_chrono_datetime() {
373 let mut formatted = String::new();
374
375 match get_timezone(timezone) {
376 Timezone::Offset(offset) => {
377 write!(
378 formatted,
379 "{}",
380 offset.from_utc_datetime(&v).format(pattern)
381 )
382 .context(crate::error::FormatSnafu { pattern })?;
383 }
384 Timezone::Named(tz) => {
385 write!(formatted, "{}", tz.from_utc_datetime(&v).format(pattern))
386 .context(crate::error::FormatSnafu { pattern })?;
387 }
388 }
389
390 Ok(formatted)
391 } else {
392 Ok(format!("[Timestamp{}: {}]", self.unit, self.value))
393 }
394 }
395
396 pub fn to_chrono_datetime(&self) -> Option<NaiveDateTime> {
397 let (sec, nsec) = self.split();
398 chrono::DateTime::from_timestamp(sec, nsec).map(|x| x.naive_utc())
399 }
400
401 pub fn to_chrono_datetime_with_timezone(&self, tz: Option<&Timezone>) -> Option<NaiveDateTime> {
402 let datetime = self.to_chrono_datetime();
403 datetime.map(|v| match tz {
404 Some(Timezone::Offset(offset)) => offset.from_utc_datetime(&v).naive_local(),
405 Some(Timezone::Named(tz)) => tz.from_utc_datetime(&v).naive_local(),
406 None => Utc.from_utc_datetime(&v).naive_local(),
407 })
408 }
409
410 pub fn to_chrono_date(&self) -> Option<NaiveDate> {
412 self.to_chrono_datetime().map(|ndt| ndt.date())
413 }
414
415 pub fn to_chrono_time(&self) -> Option<NaiveTime> {
417 self.to_chrono_datetime().map(|ndt| ndt.time())
418 }
419
420 pub fn from_chrono_datetime(ndt: NaiveDateTime) -> Option<Self> {
421 let sec = ndt.and_utc().timestamp();
422 let nsec = ndt.and_utc().timestamp_subsec_nanos();
423 Timestamp::from_splits(sec, nsec)
424 }
425
426 pub fn from_chrono_date(date: NaiveDate) -> Option<Self> {
427 Timestamp::from_chrono_datetime(date.and_time(NaiveTime::default()))
428 }
429
430 pub fn from_str_utc(s: &str) -> Result<Self> {
433 Self::from_str(s, None)
434 }
435
436 #[allow(deprecated)]
448 pub fn from_str(s: &str, timezone: Option<&Timezone>) -> Result<Self> {
449 let s = s.trim();
451 if let Ok(ts) = DateTime::parse_from_rfc3339(s) {
452 return Timestamp::from_chrono_datetime(ts.naive_utc())
453 .context(ParseTimestampSnafu { raw: s });
454 }
455 if let Ok(ts) = DateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S%.f%:z") {
456 return Timestamp::from_chrono_datetime(ts.naive_utc())
457 .context(ParseTimestampSnafu { raw: s });
458 }
459 if let Ok(ts) = chrono::Utc.datetime_from_str(s, "%Y-%m-%d %H:%M:%S%.fZ") {
460 return Timestamp::from_chrono_datetime(ts.naive_utc())
461 .context(ParseTimestampSnafu { raw: s });
462 }
463
464 if let Ok(ts) = NaiveDateTime::parse_from_str(s, "%Y-%m-%dT%H:%M:%S") {
465 return naive_datetime_to_timestamp(s, ts, timezone);
466 }
467
468 if let Ok(ts) = NaiveDateTime::parse_from_str(s, "%Y-%m-%dT%H:%M:%S%.f") {
469 return naive_datetime_to_timestamp(s, ts, timezone);
470 }
471
472 if let Ok(ts) = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") {
473 return naive_datetime_to_timestamp(s, ts, timezone);
474 }
475
476 if let Ok(ts) = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S%.f") {
477 return naive_datetime_to_timestamp(s, ts, timezone);
478 }
479
480 ParseTimestampSnafu { raw: s }.fail()
481 }
482
483 pub fn negative(mut self) -> Self {
484 self.value = -self.value;
485 self
486 }
487}
488
489impl Timestamp {
490 pub const MIN_SECOND: Self = Self::new_second(-8_334_601_228_800);
491 pub const MAX_SECOND: Self = Self::new_second(8_210_266_876_799);
492
493 pub const MIN_MILLISECOND: Self = Self::new_millisecond(-8_334_601_228_800_000);
494 pub const MAX_MILLISECOND: Self = Self::new_millisecond(8_210_266_876_799_999);
495
496 pub const MIN_MICROSECOND: Self = Self::new_microsecond(-8_334_601_228_800_000_000);
497 pub const MAX_MICROSECOND: Self = Self::new_microsecond(8_210_266_876_799_999_999);
498
499 pub const MIN_NANOSECOND: Self = Self::new_nanosecond(i64::MIN);
500 pub const MAX_NANOSECOND: Self = Self::new_nanosecond(i64::MAX);
501
502 pub fn is_overflow(value: i64, unit: TimeUnit) -> bool {
504 let (min_val, max_val) = match unit {
505 TimeUnit::Second => (Self::MIN_SECOND.value(), Self::MAX_SECOND.value()),
506 TimeUnit::Millisecond => (Self::MIN_MILLISECOND.value(), Self::MAX_MILLISECOND.value()),
507 TimeUnit::Microsecond => (Self::MIN_MICROSECOND.value(), Self::MAX_MICROSECOND.value()),
508 TimeUnit::Nanosecond => (Self::MIN_NANOSECOND.value(), Self::MAX_NANOSECOND.value()),
509 };
510 value < min_val || value > max_val
511 }
512}
513
514fn naive_datetime_to_timestamp(
517 s: &str,
518 datetime: NaiveDateTime,
519 timezone: Option<&Timezone>,
520) -> crate::error::Result<Timestamp> {
521 let Some(timezone) = timezone else {
522 return Timestamp::from_chrono_datetime(Utc.from_utc_datetime(&datetime).naive_utc())
523 .context(ParseTimestampSnafu { raw: s });
524 };
525
526 match datetime_to_utc(&datetime, timezone) {
527 LocalResult::None => ParseTimestampSnafu { raw: s }.fail(),
528 LocalResult::Single(utc) | LocalResult::Ambiguous(utc, _) => {
529 Timestamp::from_chrono_datetime(utc).context(ParseTimestampSnafu { raw: s })
530 }
531 }
532}
533
534impl From<i64> for Timestamp {
535 fn from(v: i64) -> Self {
536 Self {
537 value: v,
538 unit: TimeUnit::Millisecond,
539 }
540 }
541}
542
543impl From<Timestamp> for i64 {
544 fn from(t: Timestamp) -> Self {
545 t.value
546 }
547}
548
549impl From<Timestamp> for serde_json::Value {
550 fn from(d: Timestamp) -> Self {
551 serde_json::Value::String(d.to_iso8601_string())
552 }
553}
554
555impl fmt::Debug for Timestamp {
556 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
557 write!(f, "{}::{}", self.value, self.unit)
558 }
559}
560
561#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
562pub enum TimeUnit {
563 Second,
564 #[default]
565 Millisecond,
566 Microsecond,
567 Nanosecond,
568}
569
570impl From<&ArrowTimeUnit> for TimeUnit {
571 fn from(unit: &ArrowTimeUnit) -> Self {
572 match unit {
573 ArrowTimeUnit::Second => Self::Second,
574 ArrowTimeUnit::Millisecond => Self::Millisecond,
575 ArrowTimeUnit::Microsecond => Self::Microsecond,
576 ArrowTimeUnit::Nanosecond => Self::Nanosecond,
577 }
578 }
579}
580
581impl From<ArrowTimeUnit> for TimeUnit {
582 fn from(unit: ArrowTimeUnit) -> Self {
583 (&unit).into()
584 }
585}
586
587impl Display for TimeUnit {
588 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
589 match self {
590 TimeUnit::Second => {
591 write!(f, "Second")
592 }
593 TimeUnit::Millisecond => {
594 write!(f, "Millisecond")
595 }
596 TimeUnit::Microsecond => {
597 write!(f, "Microsecond")
598 }
599 TimeUnit::Nanosecond => {
600 write!(f, "Nanosecond")
601 }
602 }
603 }
604}
605
606impl TimeUnit {
607 pub fn factor(&self) -> u32 {
608 match self {
609 TimeUnit::Second => 1_000_000_000,
610 TimeUnit::Millisecond => 1_000_000,
611 TimeUnit::Microsecond => 1_000,
612 TimeUnit::Nanosecond => 1,
613 }
614 }
615
616 pub(crate) fn short_name(&self) -> &'static str {
617 match self {
618 TimeUnit::Second => "s",
619 TimeUnit::Millisecond => "ms",
620 TimeUnit::Microsecond => "us",
621 TimeUnit::Nanosecond => "ns",
622 }
623 }
624
625 pub fn as_arrow_time_unit(&self) -> ArrowTimeUnit {
626 match self {
627 Self::Second => ArrowTimeUnit::Second,
628 Self::Millisecond => ArrowTimeUnit::Millisecond,
629 Self::Microsecond => ArrowTimeUnit::Microsecond,
630 Self::Nanosecond => ArrowTimeUnit::Nanosecond,
631 }
632 }
633}
634
635impl PartialOrd for Timestamp {
636 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
637 Some(self.cmp(other))
638 }
639}
640
641impl Ord for Timestamp {
645 fn cmp(&self, other: &Self) -> Ordering {
646 if self.unit == other.unit {
648 return self.value.cmp(&other.value);
649 }
650
651 let (s_sec, s_nsec) = self.split();
652 let (o_sec, o_nsec) = other.split();
653 match s_sec.cmp(&o_sec) {
654 Ordering::Less => Ordering::Less,
655 Ordering::Greater => Ordering::Greater,
656 Ordering::Equal => s_nsec.cmp(&o_nsec),
657 }
658 }
659}
660
661impl PartialEq for Timestamp {
662 fn eq(&self, other: &Self) -> bool {
663 self.cmp(other) == Ordering::Equal
664 }
665}
666
667impl Eq for Timestamp {}
668
669impl Hash for Timestamp {
670 fn hash<H: Hasher>(&self, state: &mut H) {
671 let (sec, nsec) = self.split();
672 state.write_i64(sec);
673 state.write_u32(nsec);
674 }
675}
676
677#[cfg(test)]
678mod tests {
679 use std::collections::hash_map::DefaultHasher;
680
681 use chrono_tz::Tz;
682 use rand::Rng;
683 use serde_json::Value;
684
685 use super::*;
686 use crate::timezone::set_default_timezone;
687
688 #[test]
689 pub fn test_time_unit() {
690 assert_eq!(
691 TimeUnit::Millisecond.factor() * 1000,
692 TimeUnit::Second.factor()
693 );
694 assert_eq!(
695 TimeUnit::Microsecond.factor() * 1000000,
696 TimeUnit::Second.factor()
697 );
698 assert_eq!(
699 TimeUnit::Nanosecond.factor() * 1000000000,
700 TimeUnit::Second.factor()
701 );
702 }
703
704 #[test]
705 pub fn test_timestamp() {
706 let t = Timestamp::new(1, TimeUnit::Millisecond);
707 assert_eq!(TimeUnit::Millisecond, t.unit());
708 assert_eq!(1, t.value());
709 assert_eq!(Timestamp::new(1000, TimeUnit::Microsecond), t);
710 assert!(t > Timestamp::new(999, TimeUnit::Microsecond));
711 }
712
713 #[test]
714 fn test_timestamp_antisymmetry() {
715 let t1 = Timestamp::new(1, TimeUnit::Second);
716 let t2 = Timestamp::new(1000, TimeUnit::Millisecond);
717 assert!(t1 >= t2);
718 assert!(t2 >= t1);
719 assert_eq!(Ordering::Equal, t1.cmp(&t2));
720 }
721
722 fn gen_random_ts() -> Timestamp {
723 let units = [
724 TimeUnit::Second,
725 TimeUnit::Millisecond,
726 TimeUnit::Microsecond,
727 TimeUnit::Nanosecond,
728 ];
729 let mut rng = rand::rng();
730 let unit_idx: usize = rng.random_range(0..4);
731 let unit = units[unit_idx];
732 let value: i64 = rng.random();
733 Timestamp::new(value, unit)
734 }
735
736 #[test]
737 fn test_add_sub_interval() {
738 let ts = Timestamp::new(1000, TimeUnit::Millisecond);
739
740 let interval = IntervalDayTime::new(1, 200);
741
742 let new_ts = ts.add_day_time(interval).unwrap();
743 assert_eq!(new_ts.unit(), TimeUnit::Millisecond);
744 assert_eq!(new_ts.value(), 1000 + 3600 * 24 * 1000 + 200);
745
746 assert_eq!(ts, new_ts.sub_day_time(interval).unwrap());
747 }
748
749 #[test]
750 fn test_timestamp_reflexivity() {
751 for _ in 0..1000 {
752 let ts = gen_random_ts();
753 assert!(ts >= ts, "ts: {ts:?}");
754 }
755 }
756
757 fn gen_ts_le(threshold: &Timestamp) -> Timestamp {
759 let mut rng = rand::rng();
760 let timestamp = rng.random_range(i64::MIN..=threshold.value);
761 Timestamp::new(timestamp, threshold.unit)
762 }
763
764 #[test]
765 fn test_timestamp_transitivity() {
766 let t0 = Timestamp::new_millisecond(100);
767 let t1 = gen_ts_le(&t0);
768 let t2 = gen_ts_le(&t1);
769 assert!(t0 >= t1, "t0: {t0:?}, t1: {t1:?}");
770 assert!(t1 >= t2, "t1: {t1:?}, t2: {t2:?}");
771 assert!(t0 >= t2, "t0: {t0:?}, t2: {t2:?}");
772
773 let t0 = Timestamp::new_millisecond(-100);
774 let t1 = gen_ts_le(&t0); let t2 = gen_ts_le(&t1); assert!(t0 >= t1, "t0: {t0:?}, t1: {t1:?}");
777 assert!(t1 >= t2, "t1: {t1:?}, t2: {t2:?}");
778 assert!(t0 >= t2, "t0: {t0:?}, t2: {t2:?}"); }
780
781 #[test]
782 fn test_antisymmetry() {
783 let t0 = Timestamp::new(1, TimeUnit::Second);
784 let t1 = Timestamp::new(1000, TimeUnit::Millisecond);
785 assert!(t0 >= t1, "t0: {t0:?}, t1: {t1:?}");
786 assert!(t1 >= t0, "t0: {t0:?}, t1: {t1:?}");
787 assert_eq!(t1, t0, "t0: {t0:?}, t1: {t1:?}");
788 }
789
790 #[test]
791 fn test_strong_connectivity() {
792 let mut values = Vec::with_capacity(1000);
793 for _ in 0..1000 {
794 values.push(gen_random_ts());
795 }
796
797 for l in &values {
798 for r in &values {
799 assert!(l >= r || l <= r, "l: {l:?}, r: {r:?}");
800 }
801 }
802 }
803
804 #[test]
805 fn test_cmp_timestamp() {
806 let t1 = Timestamp::new(0, TimeUnit::Millisecond);
807 let t2 = Timestamp::new(0, TimeUnit::Second);
808 assert_eq!(t2, t1);
809
810 let t1 = Timestamp::new(1, TimeUnit::Millisecond);
811 let t2 = Timestamp::new(-1, TimeUnit::Second);
812 assert!(t1 > t2);
813
814 let t1 = Timestamp::new(i64::MAX / 1000 * 1000, TimeUnit::Millisecond);
815 let t2 = Timestamp::new(i64::MAX / 1000, TimeUnit::Second);
816 assert_eq!(t2, t1);
817
818 let t1 = Timestamp::new(i64::MAX, TimeUnit::Millisecond);
819 let t2 = Timestamp::new(i64::MAX / 1000 + 1, TimeUnit::Second);
820 assert!(t2 > t1);
821
822 let t1 = Timestamp::new(i64::MAX, TimeUnit::Millisecond);
823 let t2 = Timestamp::new(i64::MAX / 1000, TimeUnit::Second);
824 assert!(t2 < t1);
825
826 let t1 = Timestamp::new(10_010_001, TimeUnit::Millisecond);
827 let t2 = Timestamp::new(100, TimeUnit::Second);
828 assert!(t1 > t2);
829
830 let t1 = Timestamp::new(-100 * 10_001, TimeUnit::Millisecond);
831 let t2 = Timestamp::new(-100, TimeUnit::Second);
832 assert!(t2 > t1);
833
834 let t1 = Timestamp::new(i64::MIN, TimeUnit::Millisecond);
835 let t2 = Timestamp::new(i64::MIN / 1000 - 1, TimeUnit::Second);
836 assert!(t1 > t2);
837
838 let t1 = Timestamp::new(i64::MIN, TimeUnit::Millisecond);
839 let t2 = Timestamp::new(i64::MIN + 1, TimeUnit::Millisecond);
840 assert!(t2 > t1);
841
842 let t1 = Timestamp::new(i64::MAX, TimeUnit::Millisecond);
843 let t2 = Timestamp::new(i64::MIN, TimeUnit::Second);
844 assert!(t1 > t2);
845
846 let t1 = Timestamp::new(0, TimeUnit::Nanosecond);
847 let t2 = Timestamp::new(i64::MIN, TimeUnit::Second);
848 assert!(t1 > t2);
849 }
850
851 fn check_hash_eq(t1: Timestamp, t2: Timestamp) {
852 let mut hasher = DefaultHasher::new();
853 t1.hash(&mut hasher);
854 let t1_hash = hasher.finish();
855
856 let mut hasher = DefaultHasher::new();
857 t2.hash(&mut hasher);
858 let t2_hash = hasher.finish();
859 assert_eq!(t2_hash, t1_hash);
860 }
861
862 #[test]
863 fn test_hash() {
864 check_hash_eq(
865 Timestamp::new(0, TimeUnit::Millisecond),
866 Timestamp::new(0, TimeUnit::Second),
867 );
868 check_hash_eq(
869 Timestamp::new(1000, TimeUnit::Millisecond),
870 Timestamp::new(1, TimeUnit::Second),
871 );
872 check_hash_eq(
873 Timestamp::new(1_000_000, TimeUnit::Microsecond),
874 Timestamp::new(1, TimeUnit::Second),
875 );
876 check_hash_eq(
877 Timestamp::new(1_000_000_000, TimeUnit::Nanosecond),
878 Timestamp::new(1, TimeUnit::Second),
879 );
880 }
881
882 #[test]
883 pub fn test_from_i64() {
884 let t: Timestamp = 42.into();
885 assert_eq!(42, t.value());
886 assert_eq!(TimeUnit::Millisecond, t.unit());
887 }
888
889 fn check_from_str(s: &str, expect: &str) {
892 let ts = Timestamp::from_str_utc(s).unwrap();
893 let time = ts.to_chrono_datetime().unwrap();
894 assert_eq!(expect, time.to_string());
895 }
896
897 #[test]
898 fn test_from_str() {
899 check_from_str("2020-09-08 13:42:29Z", "2020-09-08 13:42:29");
901 check_from_str("2020-09-08T13:42:29+08:00", "2020-09-08 05:42:29");
902
903 check_from_str("2020-09-08 13:42:29", "2020-09-08 13:42:29");
904
905 check_from_str("2020-09-08 13:42:29.042Z", "2020-09-08 13:42:29.042");
906 check_from_str("2020-09-08 13:42:29.042+08:00", "2020-09-08 05:42:29.042");
907
908 check_from_str(
909 "2020-09-08T13:42:29.0042+08:00",
910 "2020-09-08 05:42:29.004200",
911 );
912 }
913
914 #[test]
915 fn test_to_iso8601_string() {
916 set_default_timezone(Some("Asia/Shanghai")).unwrap();
917 let datetime_str = "2020-09-08 13:42:29.042+0000";
918 let ts = Timestamp::from_str_utc(datetime_str).unwrap();
919 assert_eq!("2020-09-08 21:42:29.042+0800", ts.to_iso8601_string());
920
921 let ts_millis = 1668070237000;
922 let ts = Timestamp::new_millisecond(ts_millis);
923 assert_eq!("2022-11-10 16:50:37+0800", ts.to_iso8601_string());
924
925 let ts_millis = -1000;
926 let ts = Timestamp::new_millisecond(ts_millis);
927 assert_eq!("1970-01-01 07:59:59+0800", ts.to_iso8601_string());
928
929 let ts_millis = -1;
930 let ts = Timestamp::new_millisecond(ts_millis);
931 assert_eq!("1970-01-01 07:59:59.999+0800", ts.to_iso8601_string());
932
933 let ts_millis = -1001;
934 let ts = Timestamp::new_millisecond(ts_millis);
935 assert_eq!("1970-01-01 07:59:58.999+0800", ts.to_iso8601_string());
936 }
937
938 #[test]
939 fn test_serialize_to_json_value() {
940 set_default_timezone(Some("Asia/Shanghai")).unwrap();
941 assert_eq!(
942 "1970-01-01 08:00:01+0800",
943 match serde_json::Value::from(Timestamp::new(1, TimeUnit::Second)) {
944 Value::String(s) => s,
945 _ => unreachable!(),
946 }
947 );
948
949 assert_eq!(
950 "1970-01-01 08:00:00.001+0800",
951 match serde_json::Value::from(Timestamp::new(1, TimeUnit::Millisecond)) {
952 Value::String(s) => s,
953 _ => unreachable!(),
954 }
955 );
956
957 assert_eq!(
958 "1970-01-01 08:00:00.000001+0800",
959 match serde_json::Value::from(Timestamp::new(1, TimeUnit::Microsecond)) {
960 Value::String(s) => s,
961 _ => unreachable!(),
962 }
963 );
964
965 assert_eq!(
966 "1970-01-01 08:00:00.000000001+0800",
967 match serde_json::Value::from(Timestamp::new(1, TimeUnit::Nanosecond)) {
968 Value::String(s) => s,
969 _ => unreachable!(),
970 }
971 );
972 }
973
974 #[test]
975 fn test_convert_timestamp() {
976 let ts = Timestamp::new(1, TimeUnit::Second);
977 assert_eq!(
978 Timestamp::new(1000, TimeUnit::Millisecond),
979 ts.convert_to(TimeUnit::Millisecond).unwrap()
980 );
981 assert_eq!(
982 Timestamp::new(1_000_000, TimeUnit::Microsecond),
983 ts.convert_to(TimeUnit::Microsecond).unwrap()
984 );
985 assert_eq!(
986 Timestamp::new(1_000_000_000, TimeUnit::Nanosecond),
987 ts.convert_to(TimeUnit::Nanosecond).unwrap()
988 );
989
990 let ts = Timestamp::new(1_000_100_100, TimeUnit::Nanosecond);
991 assert_eq!(
992 Timestamp::new(1_000_100, TimeUnit::Microsecond),
993 ts.convert_to(TimeUnit::Microsecond).unwrap()
994 );
995 assert_eq!(
996 Timestamp::new(1000, TimeUnit::Millisecond),
997 ts.convert_to(TimeUnit::Millisecond).unwrap()
998 );
999 assert_eq!(
1000 Timestamp::new(1, TimeUnit::Second),
1001 ts.convert_to(TimeUnit::Second).unwrap()
1002 );
1003
1004 let ts = Timestamp::new(1_000_100_100, TimeUnit::Nanosecond);
1005 assert_eq!(ts, ts.convert_to(TimeUnit::Nanosecond).unwrap());
1006 let ts = Timestamp::new(1_000_100_100, TimeUnit::Microsecond);
1007 assert_eq!(ts, ts.convert_to(TimeUnit::Microsecond).unwrap());
1008 let ts = Timestamp::new(1_000_100_100, TimeUnit::Millisecond);
1009 assert_eq!(ts, ts.convert_to(TimeUnit::Millisecond).unwrap());
1010 let ts = Timestamp::new(1_000_100_100, TimeUnit::Second);
1011 assert_eq!(ts, ts.convert_to(TimeUnit::Second).unwrap());
1012
1013 assert_eq!(
1015 Timestamp::new(-9223372036854776, TimeUnit::Second),
1016 Timestamp::new(i64::MIN, TimeUnit::Millisecond)
1017 .convert_to(TimeUnit::Second)
1018 .unwrap()
1019 );
1020
1021 assert!(Timestamp::new(i64::MAX, TimeUnit::Second)
1022 .convert_to(TimeUnit::Millisecond)
1023 .is_none());
1024 }
1025
1026 #[test]
1027 fn test_split() {
1028 assert_eq!((0, 0), Timestamp::new(0, TimeUnit::Second).split());
1029 assert_eq!((1, 0), Timestamp::new(1, TimeUnit::Second).split());
1030 assert_eq!(
1031 (0, 1_000_000),
1032 Timestamp::new(1, TimeUnit::Millisecond).split()
1033 );
1034
1035 assert_eq!((0, 1_000), Timestamp::new(1, TimeUnit::Microsecond).split());
1036 assert_eq!((0, 1), Timestamp::new(1, TimeUnit::Nanosecond).split());
1037
1038 assert_eq!(
1039 (1, 1_000_000),
1040 Timestamp::new(1001, TimeUnit::Millisecond).split()
1041 );
1042
1043 assert_eq!(
1044 (-2, 999_000_000),
1045 Timestamp::new(-1001, TimeUnit::Millisecond).split()
1046 );
1047
1048 let (sec, nsec) = Timestamp::new(i64::MIN, TimeUnit::Nanosecond).split();
1050 assert_eq!(
1051 i64::MIN as i128,
1052 sec as i128 * (TimeUnit::Second.factor() / TimeUnit::Nanosecond.factor()) as i128
1053 + nsec as i128
1054 );
1055
1056 assert_eq!(
1057 (i64::MAX, 0),
1058 Timestamp::new(i64::MAX, TimeUnit::Second).split()
1059 );
1060 }
1061
1062 #[test]
1063 fn test_convert_to_ceil() {
1064 assert_eq!(
1065 Timestamp::new(1, TimeUnit::Second),
1066 Timestamp::new(1000, TimeUnit::Millisecond)
1067 .convert_to_ceil(TimeUnit::Second)
1068 .unwrap()
1069 );
1070
1071 assert_eq!(
1074 Timestamp::new(1, TimeUnit::Second),
1075 Timestamp::new(1001, TimeUnit::Millisecond)
1076 .convert_to(TimeUnit::Second)
1077 .unwrap()
1078 );
1079 assert_eq!(
1080 Timestamp::new(2, TimeUnit::Second),
1081 Timestamp::new(1001, TimeUnit::Millisecond)
1082 .convert_to_ceil(TimeUnit::Second)
1083 .unwrap()
1084 );
1085
1086 assert_eq!(
1087 Timestamp::new(-1, TimeUnit::Second),
1088 Timestamp::new(-1, TimeUnit::Millisecond)
1089 .convert_to(TimeUnit::Second)
1090 .unwrap()
1091 );
1092 assert_eq!(
1093 Timestamp::new(0, TimeUnit::Second),
1094 Timestamp::new(-1, TimeUnit::Millisecond)
1095 .convert_to_ceil(TimeUnit::Second)
1096 .unwrap()
1097 );
1098
1099 assert_eq!(
1102 Timestamp::new(-1, TimeUnit::Second).convert_to(TimeUnit::Millisecond),
1103 Timestamp::new(-1, TimeUnit::Second).convert_to_ceil(TimeUnit::Millisecond)
1104 );
1105 assert_eq!(
1106 Timestamp::new(1000, TimeUnit::Second).convert_to(TimeUnit::Millisecond),
1107 Timestamp::new(1000, TimeUnit::Second).convert_to_ceil(TimeUnit::Millisecond)
1108 );
1109 assert_eq!(
1110 Timestamp::new(1, TimeUnit::Second).convert_to(TimeUnit::Millisecond),
1111 Timestamp::new(1, TimeUnit::Second).convert_to_ceil(TimeUnit::Millisecond)
1112 );
1113 }
1114
1115 #[test]
1116 fn test_split_overflow() {
1117 let _ = Timestamp::new(i64::MAX, TimeUnit::Second).split();
1118 let _ = Timestamp::new(i64::MIN, TimeUnit::Second).split();
1119 let _ = Timestamp::new(i64::MAX, TimeUnit::Millisecond).split();
1120 let _ = Timestamp::new(i64::MIN, TimeUnit::Millisecond).split();
1121 let _ = Timestamp::new(i64::MAX, TimeUnit::Microsecond).split();
1122 let _ = Timestamp::new(i64::MIN, TimeUnit::Microsecond).split();
1123 let _ = Timestamp::new(i64::MAX, TimeUnit::Nanosecond).split();
1124 let _ = Timestamp::new(i64::MIN, TimeUnit::Nanosecond).split();
1125 let (sec, nsec) = Timestamp::new(i64::MIN, TimeUnit::Nanosecond).split();
1126 let time = DateTime::from_timestamp(sec, nsec).unwrap().naive_utc();
1127 assert_eq!(sec, time.and_utc().timestamp());
1128 assert_eq!(nsec, time.and_utc().timestamp_subsec_nanos());
1129 }
1130
1131 #[test]
1132 fn test_timestamp_sub() {
1133 let res = Timestamp::new(1, TimeUnit::Second)
1134 .sub_duration(Duration::from_secs(1))
1135 .unwrap();
1136 assert_eq!(0, res.value);
1137 assert_eq!(TimeUnit::Second, res.unit);
1138
1139 let res = Timestamp::new(0, TimeUnit::Second)
1140 .sub_duration(Duration::from_secs(1))
1141 .unwrap();
1142 assert_eq!(-1, res.value);
1143 assert_eq!(TimeUnit::Second, res.unit);
1144
1145 let res = Timestamp::new(1, TimeUnit::Second)
1146 .sub_duration(Duration::from_millis(1))
1147 .unwrap();
1148 assert_eq!(1, res.value);
1149 assert_eq!(TimeUnit::Second, res.unit);
1150 }
1151
1152 #[test]
1153 fn test_timestamp_add() {
1154 let res = Timestamp::new(1, TimeUnit::Second)
1155 .add_duration(Duration::from_secs(1))
1156 .unwrap();
1157 assert_eq!(2, res.value);
1158 assert_eq!(TimeUnit::Second, res.unit);
1159
1160 let res = Timestamp::new(0, TimeUnit::Second)
1161 .add_duration(Duration::from_secs(1))
1162 .unwrap();
1163 assert_eq!(1, res.value);
1164 assert_eq!(TimeUnit::Second, res.unit);
1165
1166 let res = Timestamp::new(1, TimeUnit::Second)
1167 .add_duration(Duration::from_millis(1))
1168 .unwrap();
1169 assert_eq!(1, res.value);
1170 assert_eq!(TimeUnit::Second, res.unit);
1171
1172 let res = Timestamp::new(100, TimeUnit::Second)
1173 .add_duration(Duration::from_millis(1000))
1174 .unwrap();
1175 assert_eq!(101, res.value);
1176 assert_eq!(TimeUnit::Second, res.unit);
1177 }
1178
1179 #[test]
1181 fn test_parse_in_timezone() {
1182 std::env::set_var("TZ", "Asia/Shanghai");
1183 assert_eq!(
1184 Timestamp::new(28800, TimeUnit::Second),
1185 Timestamp::from_str_utc("1970-01-01 08:00:00.000").unwrap()
1186 );
1187
1188 assert_eq!(
1189 Timestamp::new(28800, TimeUnit::Second),
1190 Timestamp::from_str_utc("1970-01-01 08:00:00").unwrap()
1191 );
1192
1193 assert_eq!(
1194 Timestamp::new(28800, TimeUnit::Second),
1195 Timestamp::from_str_utc(" 1970-01-01 08:00:00 ").unwrap()
1196 );
1197 }
1198
1199 #[test]
1200 fn test_to_local_string() {
1201 set_default_timezone(Some("Asia/Shanghai")).unwrap();
1202
1203 assert_eq!(
1204 "1970-01-01 08:00:00.000000001",
1205 Timestamp::new(1, TimeUnit::Nanosecond).to_local_string()
1206 );
1207
1208 assert_eq!(
1209 "1970-01-01 08:00:00.001",
1210 Timestamp::new(1, TimeUnit::Millisecond).to_local_string()
1211 );
1212
1213 assert_eq!(
1214 "1970-01-01 08:00:01",
1215 Timestamp::new(1, TimeUnit::Second).to_local_string()
1216 );
1217 }
1218
1219 #[test]
1220 fn test_subtract_timestamp() {
1221 assert_eq!(
1222 chrono::Duration::try_milliseconds(42),
1223 Timestamp::new_millisecond(100).sub(&Timestamp::new_millisecond(58))
1224 );
1225
1226 assert_eq!(
1227 chrono::Duration::try_milliseconds(-42),
1228 Timestamp::new_millisecond(58).sub(&Timestamp::new_millisecond(100))
1229 );
1230 }
1231
1232 #[test]
1233 fn test_to_timezone_aware_string() {
1234 set_default_timezone(Some("Asia/Shanghai")).unwrap();
1235 std::env::set_var("TZ", "Asia/Shanghai");
1236 assert_eq!(
1237 "1970-01-01 08:00:00.001",
1238 Timestamp::new(1, TimeUnit::Millisecond)
1239 .to_timezone_aware_string(Some(&Timezone::from_tz_string("SYSTEM").unwrap()))
1240 );
1241 assert_eq!(
1242 "1970-01-01 08:00:00.001",
1243 Timestamp::new(1, TimeUnit::Millisecond)
1244 .to_timezone_aware_string(Some(&Timezone::from_tz_string("SYSTEM").unwrap()))
1245 );
1246 assert_eq!(
1247 "1970-01-01 08:00:00.001",
1248 Timestamp::new(1, TimeUnit::Millisecond)
1249 .to_timezone_aware_string(Some(&Timezone::from_tz_string("+08:00").unwrap()))
1250 );
1251 assert_eq!(
1252 "1970-01-01 07:00:00.001",
1253 Timestamp::new(1, TimeUnit::Millisecond)
1254 .to_timezone_aware_string(Some(&Timezone::from_tz_string("+07:00").unwrap()))
1255 );
1256 assert_eq!(
1257 "1969-12-31 23:00:00.001",
1258 Timestamp::new(1, TimeUnit::Millisecond)
1259 .to_timezone_aware_string(Some(&Timezone::from_tz_string("-01:00").unwrap()))
1260 );
1261 assert_eq!(
1262 "1970-01-01 08:00:00.001",
1263 Timestamp::new(1, TimeUnit::Millisecond).to_timezone_aware_string(Some(
1264 &Timezone::from_tz_string("Asia/Shanghai").unwrap()
1265 ))
1266 );
1267 assert_eq!(
1268 "1970-01-01 00:00:00.001",
1269 Timestamp::new(1, TimeUnit::Millisecond)
1270 .to_timezone_aware_string(Some(&Timezone::from_tz_string("UTC").unwrap()))
1271 );
1272 assert_eq!(
1273 "1970-01-01 01:00:00.001",
1274 Timestamp::new(1, TimeUnit::Millisecond).to_timezone_aware_string(Some(
1275 &Timezone::from_tz_string("Europe/Berlin").unwrap()
1276 ))
1277 );
1278 assert_eq!(
1279 "1970-01-01 03:00:00.001",
1280 Timestamp::new(1, TimeUnit::Millisecond).to_timezone_aware_string(Some(
1281 &Timezone::from_tz_string("Europe/Moscow").unwrap()
1282 ))
1283 );
1284 }
1285
1286 #[test]
1287 fn test_as_formatted_string() {
1288 let ts = Timestamp::new(1, TimeUnit::Millisecond);
1289
1290 assert_eq!(
1291 "1970-01-01",
1292 ts.as_formatted_string("%Y-%m-%d", None).unwrap()
1293 );
1294 assert_eq!(
1295 "1970-01-01 00:00:00",
1296 ts.as_formatted_string("%Y-%m-%d %H:%M:%S", None).unwrap()
1297 );
1298 assert_eq!(
1299 "1970-01-01T00:00:00:001",
1300 ts.as_formatted_string("%Y-%m-%dT%H:%M:%S:%3f", None)
1301 .unwrap()
1302 );
1303 assert_eq!(
1304 "1970-01-01T08:00:00:001",
1305 ts.as_formatted_string(
1306 "%Y-%m-%dT%H:%M:%S:%3f",
1307 Some(&Timezone::from_tz_string("Asia/Shanghai").unwrap())
1308 )
1309 .unwrap()
1310 );
1311 }
1312
1313 #[test]
1314 fn test_from_arrow_time_unit() {
1315 assert_eq!(TimeUnit::Second, TimeUnit::from(ArrowTimeUnit::Second));
1316 assert_eq!(
1317 TimeUnit::Millisecond,
1318 TimeUnit::from(ArrowTimeUnit::Millisecond)
1319 );
1320 assert_eq!(
1321 TimeUnit::Microsecond,
1322 TimeUnit::from(ArrowTimeUnit::Microsecond)
1323 );
1324 assert_eq!(
1325 TimeUnit::Nanosecond,
1326 TimeUnit::from(ArrowTimeUnit::Nanosecond)
1327 );
1328 }
1329
1330 fn check_conversion(ts: Timestamp, valid: bool) {
1331 let Some(t2) = ts.to_chrono_datetime() else {
1332 if valid {
1333 panic!("Cannot convert {:?} to Chrono NaiveDateTime", ts);
1334 }
1335 return;
1336 };
1337 let Some(t3) = Timestamp::from_chrono_datetime(t2) else {
1338 if valid {
1339 panic!("Cannot convert Chrono NaiveDateTime {:?} to Timestamp", t2);
1340 }
1341 return;
1342 };
1343
1344 assert_eq!(t3, ts);
1345 }
1346
1347 #[test]
1348 fn test_from_naive_date_time() {
1349 let naive_date_time_min = NaiveDateTime::MIN.and_utc();
1350 let naive_date_time_max = NaiveDateTime::MAX.and_utc();
1351
1352 let min_sec = Timestamp::new_second(naive_date_time_min.timestamp());
1353 let max_sec = Timestamp::new_second(naive_date_time_max.timestamp());
1354 check_conversion(min_sec, true);
1355 check_conversion(Timestamp::new_second(min_sec.value - 1), false);
1356 check_conversion(max_sec, true);
1357 check_conversion(Timestamp::new_second(max_sec.value + 1), false);
1358
1359 let min_millis = Timestamp::new_millisecond(naive_date_time_min.timestamp_millis());
1360 let max_millis = Timestamp::new_millisecond(naive_date_time_max.timestamp_millis());
1361 check_conversion(min_millis, true);
1362 check_conversion(Timestamp::new_millisecond(min_millis.value - 1), false);
1363 check_conversion(max_millis, true);
1364 check_conversion(Timestamp::new_millisecond(max_millis.value + 1), false);
1365
1366 let min_micros = Timestamp::new_microsecond(naive_date_time_min.timestamp_micros());
1367 let max_micros = Timestamp::new_microsecond(naive_date_time_max.timestamp_micros());
1368 check_conversion(min_micros, true);
1369 check_conversion(Timestamp::new_microsecond(min_micros.value - 1), false);
1370 check_conversion(max_micros, true);
1371 check_conversion(Timestamp::new_microsecond(max_micros.value + 1), false);
1372
1373 let min_nanos = Timestamp::new_nanosecond(-9223372036854775000);
1375 let max_nanos = Timestamp::new_nanosecond(i64::MAX);
1376 check_conversion(min_nanos, true);
1377 check_conversion(Timestamp::new_nanosecond(min_nanos.value - 1), false);
1378 check_conversion(max_nanos, true);
1379 }
1380
1381 #[test]
1382 fn test_parse_timestamp_range() {
1383 let datetime_min = NaiveDateTime::MIN.format("%Y-%m-%d %H:%M:%SZ").to_string();
1384 assert_eq!("-262143-01-01 00:00:00Z", datetime_min);
1385 let datetime_max = NaiveDateTime::MAX.format("%Y-%m-%d %H:%M:%SZ").to_string();
1386 assert_eq!("+262142-12-31 23:59:59Z", datetime_max);
1387
1388 let valid_strings = vec![
1389 "-262143-01-01 00:00:00Z",
1390 "+262142-12-31 23:59:59Z",
1391 "+262142-12-31 23:59:59.999Z",
1392 "+262142-12-31 23:59:59.999999Z",
1393 "1677-09-21 00:12:43.145224192Z",
1394 "2262-04-11 23:47:16.854775807Z",
1395 "+100000-01-01 00:00:01.5Z",
1396 ];
1397
1398 for s in valid_strings {
1399 Timestamp::from_str_utc(s).unwrap();
1400 }
1401 }
1402
1403 #[test]
1404 fn test_min_nanos_roundtrip() {
1405 let (sec, nsec) = Timestamp::MIN_NANOSECOND.split();
1406 let ts = Timestamp::from_splits(sec, nsec).unwrap();
1407 assert_eq!(Timestamp::MIN_NANOSECOND, ts);
1408 }
1409
1410 #[test]
1411 fn test_timestamp_bound_format() {
1412 assert_eq!(
1413 "1677-09-21 00:12:43.145224192",
1414 Timestamp::MIN_NANOSECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1415 );
1416 assert_eq!(
1417 "2262-04-11 23:47:16.854775807",
1418 Timestamp::MAX_NANOSECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1419 );
1420 assert_eq!(
1421 "-262143-01-01 00:00:00",
1422 Timestamp::MIN_MICROSECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1423 );
1424 assert_eq!(
1425 "+262142-12-31 23:59:59.999999",
1426 Timestamp::MAX_MICROSECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1427 );
1428 assert_eq!(
1429 "-262143-01-01 00:00:00",
1430 Timestamp::MIN_MILLISECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1431 );
1432 assert_eq!(
1433 "+262142-12-31 23:59:59.999",
1434 Timestamp::MAX_MILLISECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1435 );
1436 assert_eq!(
1437 "-262143-01-01 00:00:00",
1438 Timestamp::MIN_SECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1439 );
1440 assert_eq!(
1441 "+262142-12-31 23:59:59",
1442 Timestamp::MAX_SECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1443 );
1444 }
1445
1446 #[test]
1447 fn test_debug_timestamp() {
1448 assert_eq!(
1449 "1000::Second",
1450 format!("{:?}", Timestamp::new(1000, TimeUnit::Second))
1451 );
1452 assert_eq!(
1453 "1001::Millisecond",
1454 format!("{:?}", Timestamp::new(1001, TimeUnit::Millisecond))
1455 );
1456 assert_eq!(
1457 "1002::Microsecond",
1458 format!("{:?}", Timestamp::new(1002, TimeUnit::Microsecond))
1459 );
1460 assert_eq!(
1461 "1003::Nanosecond",
1462 format!("{:?}", Timestamp::new(1003, TimeUnit::Nanosecond))
1463 );
1464 }
1465}