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
503fn naive_datetime_to_timestamp(
506 s: &str,
507 datetime: NaiveDateTime,
508 timezone: Option<&Timezone>,
509) -> crate::error::Result<Timestamp> {
510 let Some(timezone) = timezone else {
511 return Timestamp::from_chrono_datetime(Utc.from_utc_datetime(&datetime).naive_utc())
512 .context(ParseTimestampSnafu { raw: s });
513 };
514
515 match datetime_to_utc(&datetime, timezone) {
516 LocalResult::None => ParseTimestampSnafu { raw: s }.fail(),
517 LocalResult::Single(utc) | LocalResult::Ambiguous(utc, _) => {
518 Timestamp::from_chrono_datetime(utc).context(ParseTimestampSnafu { raw: s })
519 }
520 }
521}
522
523impl From<i64> for Timestamp {
524 fn from(v: i64) -> Self {
525 Self {
526 value: v,
527 unit: TimeUnit::Millisecond,
528 }
529 }
530}
531
532impl From<Timestamp> for i64 {
533 fn from(t: Timestamp) -> Self {
534 t.value
535 }
536}
537
538impl From<Timestamp> for serde_json::Value {
539 fn from(d: Timestamp) -> Self {
540 serde_json::Value::String(d.to_iso8601_string())
541 }
542}
543
544impl fmt::Debug for Timestamp {
545 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
546 write!(f, "{}::{}", self.value, self.unit)
547 }
548}
549
550#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
551pub enum TimeUnit {
552 Second,
553 #[default]
554 Millisecond,
555 Microsecond,
556 Nanosecond,
557}
558
559impl From<&ArrowTimeUnit> for TimeUnit {
560 fn from(unit: &ArrowTimeUnit) -> Self {
561 match unit {
562 ArrowTimeUnit::Second => Self::Second,
563 ArrowTimeUnit::Millisecond => Self::Millisecond,
564 ArrowTimeUnit::Microsecond => Self::Microsecond,
565 ArrowTimeUnit::Nanosecond => Self::Nanosecond,
566 }
567 }
568}
569
570impl From<ArrowTimeUnit> for TimeUnit {
571 fn from(unit: ArrowTimeUnit) -> Self {
572 (&unit).into()
573 }
574}
575
576impl Display for TimeUnit {
577 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
578 match self {
579 TimeUnit::Second => {
580 write!(f, "Second")
581 }
582 TimeUnit::Millisecond => {
583 write!(f, "Millisecond")
584 }
585 TimeUnit::Microsecond => {
586 write!(f, "Microsecond")
587 }
588 TimeUnit::Nanosecond => {
589 write!(f, "Nanosecond")
590 }
591 }
592 }
593}
594
595impl TimeUnit {
596 pub fn factor(&self) -> u32 {
597 match self {
598 TimeUnit::Second => 1_000_000_000,
599 TimeUnit::Millisecond => 1_000_000,
600 TimeUnit::Microsecond => 1_000,
601 TimeUnit::Nanosecond => 1,
602 }
603 }
604
605 pub(crate) fn short_name(&self) -> &'static str {
606 match self {
607 TimeUnit::Second => "s",
608 TimeUnit::Millisecond => "ms",
609 TimeUnit::Microsecond => "us",
610 TimeUnit::Nanosecond => "ns",
611 }
612 }
613
614 pub fn as_arrow_time_unit(&self) -> ArrowTimeUnit {
615 match self {
616 Self::Second => ArrowTimeUnit::Second,
617 Self::Millisecond => ArrowTimeUnit::Millisecond,
618 Self::Microsecond => ArrowTimeUnit::Microsecond,
619 Self::Nanosecond => ArrowTimeUnit::Nanosecond,
620 }
621 }
622}
623
624impl PartialOrd for Timestamp {
625 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
626 Some(self.cmp(other))
627 }
628}
629
630impl Ord for Timestamp {
634 fn cmp(&self, other: &Self) -> Ordering {
635 if self.unit == other.unit {
637 return self.value.cmp(&other.value);
638 }
639
640 let (s_sec, s_nsec) = self.split();
641 let (o_sec, o_nsec) = other.split();
642 match s_sec.cmp(&o_sec) {
643 Ordering::Less => Ordering::Less,
644 Ordering::Greater => Ordering::Greater,
645 Ordering::Equal => s_nsec.cmp(&o_nsec),
646 }
647 }
648}
649
650impl PartialEq for Timestamp {
651 fn eq(&self, other: &Self) -> bool {
652 self.cmp(other) == Ordering::Equal
653 }
654}
655
656impl Eq for Timestamp {}
657
658impl Hash for Timestamp {
659 fn hash<H: Hasher>(&self, state: &mut H) {
660 let (sec, nsec) = self.split();
661 state.write_i64(sec);
662 state.write_u32(nsec);
663 }
664}
665
666#[cfg(test)]
667mod tests {
668 use std::collections::hash_map::DefaultHasher;
669
670 use chrono_tz::Tz;
671 use rand::Rng;
672 use serde_json::Value;
673
674 use super::*;
675 use crate::timezone::set_default_timezone;
676
677 #[test]
678 pub fn test_time_unit() {
679 assert_eq!(
680 TimeUnit::Millisecond.factor() * 1000,
681 TimeUnit::Second.factor()
682 );
683 assert_eq!(
684 TimeUnit::Microsecond.factor() * 1000000,
685 TimeUnit::Second.factor()
686 );
687 assert_eq!(
688 TimeUnit::Nanosecond.factor() * 1000000000,
689 TimeUnit::Second.factor()
690 );
691 }
692
693 #[test]
694 pub fn test_timestamp() {
695 let t = Timestamp::new(1, TimeUnit::Millisecond);
696 assert_eq!(TimeUnit::Millisecond, t.unit());
697 assert_eq!(1, t.value());
698 assert_eq!(Timestamp::new(1000, TimeUnit::Microsecond), t);
699 assert!(t > Timestamp::new(999, TimeUnit::Microsecond));
700 }
701
702 #[test]
703 fn test_timestamp_antisymmetry() {
704 let t1 = Timestamp::new(1, TimeUnit::Second);
705 let t2 = Timestamp::new(1000, TimeUnit::Millisecond);
706 assert!(t1 >= t2);
707 assert!(t2 >= t1);
708 assert_eq!(Ordering::Equal, t1.cmp(&t2));
709 }
710
711 fn gen_random_ts() -> Timestamp {
712 let units = [
713 TimeUnit::Second,
714 TimeUnit::Millisecond,
715 TimeUnit::Microsecond,
716 TimeUnit::Nanosecond,
717 ];
718 let mut rng = rand::rng();
719 let unit_idx: usize = rng.random_range(0..4);
720 let unit = units[unit_idx];
721 let value: i64 = rng.random();
722 Timestamp::new(value, unit)
723 }
724
725 #[test]
726 fn test_add_sub_interval() {
727 let ts = Timestamp::new(1000, TimeUnit::Millisecond);
728
729 let interval = IntervalDayTime::new(1, 200);
730
731 let new_ts = ts.add_day_time(interval).unwrap();
732 assert_eq!(new_ts.unit(), TimeUnit::Millisecond);
733 assert_eq!(new_ts.value(), 1000 + 3600 * 24 * 1000 + 200);
734
735 assert_eq!(ts, new_ts.sub_day_time(interval).unwrap());
736 }
737
738 #[test]
739 fn test_timestamp_reflexivity() {
740 for _ in 0..1000 {
741 let ts = gen_random_ts();
742 assert!(ts >= ts, "ts: {ts:?}");
743 }
744 }
745
746 fn gen_ts_le(threshold: &Timestamp) -> Timestamp {
748 let mut rng = rand::rng();
749 let timestamp = rng.random_range(i64::MIN..=threshold.value);
750 Timestamp::new(timestamp, threshold.unit)
751 }
752
753 #[test]
754 fn test_timestamp_transitivity() {
755 let t0 = Timestamp::new_millisecond(100);
756 let t1 = gen_ts_le(&t0);
757 let t2 = gen_ts_le(&t1);
758 assert!(t0 >= t1, "t0: {t0:?}, t1: {t1:?}");
759 assert!(t1 >= t2, "t1: {t1:?}, t2: {t2:?}");
760 assert!(t0 >= t2, "t0: {t0:?}, t2: {t2:?}");
761
762 let t0 = Timestamp::new_millisecond(-100);
763 let t1 = gen_ts_le(&t0); let t2 = gen_ts_le(&t1); assert!(t0 >= t1, "t0: {t0:?}, t1: {t1:?}");
766 assert!(t1 >= t2, "t1: {t1:?}, t2: {t2:?}");
767 assert!(t0 >= t2, "t0: {t0:?}, t2: {t2:?}"); }
769
770 #[test]
771 fn test_antisymmetry() {
772 let t0 = Timestamp::new(1, TimeUnit::Second);
773 let t1 = Timestamp::new(1000, TimeUnit::Millisecond);
774 assert!(t0 >= t1, "t0: {t0:?}, t1: {t1:?}");
775 assert!(t1 >= t0, "t0: {t0:?}, t1: {t1:?}");
776 assert_eq!(t1, t0, "t0: {t0:?}, t1: {t1:?}");
777 }
778
779 #[test]
780 fn test_strong_connectivity() {
781 let mut values = Vec::with_capacity(1000);
782 for _ in 0..1000 {
783 values.push(gen_random_ts());
784 }
785
786 for l in &values {
787 for r in &values {
788 assert!(l >= r || l <= r, "l: {l:?}, r: {r:?}");
789 }
790 }
791 }
792
793 #[test]
794 fn test_cmp_timestamp() {
795 let t1 = Timestamp::new(0, TimeUnit::Millisecond);
796 let t2 = Timestamp::new(0, TimeUnit::Second);
797 assert_eq!(t2, t1);
798
799 let t1 = Timestamp::new(1, TimeUnit::Millisecond);
800 let t2 = Timestamp::new(-1, TimeUnit::Second);
801 assert!(t1 > t2);
802
803 let t1 = Timestamp::new(i64::MAX / 1000 * 1000, TimeUnit::Millisecond);
804 let t2 = Timestamp::new(i64::MAX / 1000, TimeUnit::Second);
805 assert_eq!(t2, t1);
806
807 let t1 = Timestamp::new(i64::MAX, TimeUnit::Millisecond);
808 let t2 = Timestamp::new(i64::MAX / 1000 + 1, TimeUnit::Second);
809 assert!(t2 > t1);
810
811 let t1 = Timestamp::new(i64::MAX, TimeUnit::Millisecond);
812 let t2 = Timestamp::new(i64::MAX / 1000, TimeUnit::Second);
813 assert!(t2 < t1);
814
815 let t1 = Timestamp::new(10_010_001, TimeUnit::Millisecond);
816 let t2 = Timestamp::new(100, TimeUnit::Second);
817 assert!(t1 > t2);
818
819 let t1 = Timestamp::new(-100 * 10_001, TimeUnit::Millisecond);
820 let t2 = Timestamp::new(-100, TimeUnit::Second);
821 assert!(t2 > t1);
822
823 let t1 = Timestamp::new(i64::MIN, TimeUnit::Millisecond);
824 let t2 = Timestamp::new(i64::MIN / 1000 - 1, TimeUnit::Second);
825 assert!(t1 > t2);
826
827 let t1 = Timestamp::new(i64::MIN, TimeUnit::Millisecond);
828 let t2 = Timestamp::new(i64::MIN + 1, TimeUnit::Millisecond);
829 assert!(t2 > t1);
830
831 let t1 = Timestamp::new(i64::MAX, TimeUnit::Millisecond);
832 let t2 = Timestamp::new(i64::MIN, TimeUnit::Second);
833 assert!(t1 > t2);
834
835 let t1 = Timestamp::new(0, TimeUnit::Nanosecond);
836 let t2 = Timestamp::new(i64::MIN, TimeUnit::Second);
837 assert!(t1 > t2);
838 }
839
840 fn check_hash_eq(t1: Timestamp, t2: Timestamp) {
841 let mut hasher = DefaultHasher::new();
842 t1.hash(&mut hasher);
843 let t1_hash = hasher.finish();
844
845 let mut hasher = DefaultHasher::new();
846 t2.hash(&mut hasher);
847 let t2_hash = hasher.finish();
848 assert_eq!(t2_hash, t1_hash);
849 }
850
851 #[test]
852 fn test_hash() {
853 check_hash_eq(
854 Timestamp::new(0, TimeUnit::Millisecond),
855 Timestamp::new(0, TimeUnit::Second),
856 );
857 check_hash_eq(
858 Timestamp::new(1000, TimeUnit::Millisecond),
859 Timestamp::new(1, TimeUnit::Second),
860 );
861 check_hash_eq(
862 Timestamp::new(1_000_000, TimeUnit::Microsecond),
863 Timestamp::new(1, TimeUnit::Second),
864 );
865 check_hash_eq(
866 Timestamp::new(1_000_000_000, TimeUnit::Nanosecond),
867 Timestamp::new(1, TimeUnit::Second),
868 );
869 }
870
871 #[test]
872 pub fn test_from_i64() {
873 let t: Timestamp = 42.into();
874 assert_eq!(42, t.value());
875 assert_eq!(TimeUnit::Millisecond, t.unit());
876 }
877
878 fn check_from_str(s: &str, expect: &str) {
881 let ts = Timestamp::from_str_utc(s).unwrap();
882 let time = ts.to_chrono_datetime().unwrap();
883 assert_eq!(expect, time.to_string());
884 }
885
886 #[test]
887 fn test_from_str() {
888 check_from_str("2020-09-08 13:42:29Z", "2020-09-08 13:42:29");
890 check_from_str("2020-09-08T13:42:29+08:00", "2020-09-08 05:42:29");
891
892 check_from_str("2020-09-08 13:42:29", "2020-09-08 13:42:29");
893
894 check_from_str("2020-09-08 13:42:29.042Z", "2020-09-08 13:42:29.042");
895 check_from_str("2020-09-08 13:42:29.042+08:00", "2020-09-08 05:42:29.042");
896
897 check_from_str(
898 "2020-09-08T13:42:29.0042+08:00",
899 "2020-09-08 05:42:29.004200",
900 );
901 }
902
903 #[test]
904 fn test_to_iso8601_string() {
905 set_default_timezone(Some("Asia/Shanghai")).unwrap();
906 let datetime_str = "2020-09-08 13:42:29.042+0000";
907 let ts = Timestamp::from_str_utc(datetime_str).unwrap();
908 assert_eq!("2020-09-08 21:42:29.042+0800", ts.to_iso8601_string());
909
910 let ts_millis = 1668070237000;
911 let ts = Timestamp::new_millisecond(ts_millis);
912 assert_eq!("2022-11-10 16:50:37+0800", ts.to_iso8601_string());
913
914 let ts_millis = -1000;
915 let ts = Timestamp::new_millisecond(ts_millis);
916 assert_eq!("1970-01-01 07:59:59+0800", ts.to_iso8601_string());
917
918 let ts_millis = -1;
919 let ts = Timestamp::new_millisecond(ts_millis);
920 assert_eq!("1970-01-01 07:59:59.999+0800", ts.to_iso8601_string());
921
922 let ts_millis = -1001;
923 let ts = Timestamp::new_millisecond(ts_millis);
924 assert_eq!("1970-01-01 07:59:58.999+0800", ts.to_iso8601_string());
925 }
926
927 #[test]
928 fn test_serialize_to_json_value() {
929 set_default_timezone(Some("Asia/Shanghai")).unwrap();
930 assert_eq!(
931 "1970-01-01 08:00:01+0800",
932 match serde_json::Value::from(Timestamp::new(1, TimeUnit::Second)) {
933 Value::String(s) => s,
934 _ => unreachable!(),
935 }
936 );
937
938 assert_eq!(
939 "1970-01-01 08:00:00.001+0800",
940 match serde_json::Value::from(Timestamp::new(1, TimeUnit::Millisecond)) {
941 Value::String(s) => s,
942 _ => unreachable!(),
943 }
944 );
945
946 assert_eq!(
947 "1970-01-01 08:00:00.000001+0800",
948 match serde_json::Value::from(Timestamp::new(1, TimeUnit::Microsecond)) {
949 Value::String(s) => s,
950 _ => unreachable!(),
951 }
952 );
953
954 assert_eq!(
955 "1970-01-01 08:00:00.000000001+0800",
956 match serde_json::Value::from(Timestamp::new(1, TimeUnit::Nanosecond)) {
957 Value::String(s) => s,
958 _ => unreachable!(),
959 }
960 );
961 }
962
963 #[test]
964 fn test_convert_timestamp() {
965 let ts = Timestamp::new(1, TimeUnit::Second);
966 assert_eq!(
967 Timestamp::new(1000, TimeUnit::Millisecond),
968 ts.convert_to(TimeUnit::Millisecond).unwrap()
969 );
970 assert_eq!(
971 Timestamp::new(1_000_000, TimeUnit::Microsecond),
972 ts.convert_to(TimeUnit::Microsecond).unwrap()
973 );
974 assert_eq!(
975 Timestamp::new(1_000_000_000, TimeUnit::Nanosecond),
976 ts.convert_to(TimeUnit::Nanosecond).unwrap()
977 );
978
979 let ts = Timestamp::new(1_000_100_100, TimeUnit::Nanosecond);
980 assert_eq!(
981 Timestamp::new(1_000_100, TimeUnit::Microsecond),
982 ts.convert_to(TimeUnit::Microsecond).unwrap()
983 );
984 assert_eq!(
985 Timestamp::new(1000, TimeUnit::Millisecond),
986 ts.convert_to(TimeUnit::Millisecond).unwrap()
987 );
988 assert_eq!(
989 Timestamp::new(1, TimeUnit::Second),
990 ts.convert_to(TimeUnit::Second).unwrap()
991 );
992
993 let ts = Timestamp::new(1_000_100_100, TimeUnit::Nanosecond);
994 assert_eq!(ts, ts.convert_to(TimeUnit::Nanosecond).unwrap());
995 let ts = Timestamp::new(1_000_100_100, TimeUnit::Microsecond);
996 assert_eq!(ts, ts.convert_to(TimeUnit::Microsecond).unwrap());
997 let ts = Timestamp::new(1_000_100_100, TimeUnit::Millisecond);
998 assert_eq!(ts, ts.convert_to(TimeUnit::Millisecond).unwrap());
999 let ts = Timestamp::new(1_000_100_100, TimeUnit::Second);
1000 assert_eq!(ts, ts.convert_to(TimeUnit::Second).unwrap());
1001
1002 assert_eq!(
1004 Timestamp::new(-9223372036854776, TimeUnit::Second),
1005 Timestamp::new(i64::MIN, TimeUnit::Millisecond)
1006 .convert_to(TimeUnit::Second)
1007 .unwrap()
1008 );
1009
1010 assert!(Timestamp::new(i64::MAX, TimeUnit::Second)
1011 .convert_to(TimeUnit::Millisecond)
1012 .is_none());
1013 }
1014
1015 #[test]
1016 fn test_split() {
1017 assert_eq!((0, 0), Timestamp::new(0, TimeUnit::Second).split());
1018 assert_eq!((1, 0), Timestamp::new(1, TimeUnit::Second).split());
1019 assert_eq!(
1020 (0, 1_000_000),
1021 Timestamp::new(1, TimeUnit::Millisecond).split()
1022 );
1023
1024 assert_eq!((0, 1_000), Timestamp::new(1, TimeUnit::Microsecond).split());
1025 assert_eq!((0, 1), Timestamp::new(1, TimeUnit::Nanosecond).split());
1026
1027 assert_eq!(
1028 (1, 1_000_000),
1029 Timestamp::new(1001, TimeUnit::Millisecond).split()
1030 );
1031
1032 assert_eq!(
1033 (-2, 999_000_000),
1034 Timestamp::new(-1001, TimeUnit::Millisecond).split()
1035 );
1036
1037 let (sec, nsec) = Timestamp::new(i64::MIN, TimeUnit::Nanosecond).split();
1039 assert_eq!(
1040 i64::MIN as i128,
1041 sec as i128 * (TimeUnit::Second.factor() / TimeUnit::Nanosecond.factor()) as i128
1042 + nsec as i128
1043 );
1044
1045 assert_eq!(
1046 (i64::MAX, 0),
1047 Timestamp::new(i64::MAX, TimeUnit::Second).split()
1048 );
1049 }
1050
1051 #[test]
1052 fn test_convert_to_ceil() {
1053 assert_eq!(
1054 Timestamp::new(1, TimeUnit::Second),
1055 Timestamp::new(1000, TimeUnit::Millisecond)
1056 .convert_to_ceil(TimeUnit::Second)
1057 .unwrap()
1058 );
1059
1060 assert_eq!(
1063 Timestamp::new(1, TimeUnit::Second),
1064 Timestamp::new(1001, TimeUnit::Millisecond)
1065 .convert_to(TimeUnit::Second)
1066 .unwrap()
1067 );
1068 assert_eq!(
1069 Timestamp::new(2, TimeUnit::Second),
1070 Timestamp::new(1001, TimeUnit::Millisecond)
1071 .convert_to_ceil(TimeUnit::Second)
1072 .unwrap()
1073 );
1074
1075 assert_eq!(
1076 Timestamp::new(-1, TimeUnit::Second),
1077 Timestamp::new(-1, TimeUnit::Millisecond)
1078 .convert_to(TimeUnit::Second)
1079 .unwrap()
1080 );
1081 assert_eq!(
1082 Timestamp::new(0, TimeUnit::Second),
1083 Timestamp::new(-1, TimeUnit::Millisecond)
1084 .convert_to_ceil(TimeUnit::Second)
1085 .unwrap()
1086 );
1087
1088 assert_eq!(
1091 Timestamp::new(-1, TimeUnit::Second).convert_to(TimeUnit::Millisecond),
1092 Timestamp::new(-1, TimeUnit::Second).convert_to_ceil(TimeUnit::Millisecond)
1093 );
1094 assert_eq!(
1095 Timestamp::new(1000, TimeUnit::Second).convert_to(TimeUnit::Millisecond),
1096 Timestamp::new(1000, TimeUnit::Second).convert_to_ceil(TimeUnit::Millisecond)
1097 );
1098 assert_eq!(
1099 Timestamp::new(1, TimeUnit::Second).convert_to(TimeUnit::Millisecond),
1100 Timestamp::new(1, TimeUnit::Second).convert_to_ceil(TimeUnit::Millisecond)
1101 );
1102 }
1103
1104 #[test]
1105 fn test_split_overflow() {
1106 let _ = Timestamp::new(i64::MAX, TimeUnit::Second).split();
1107 let _ = Timestamp::new(i64::MIN, TimeUnit::Second).split();
1108 let _ = Timestamp::new(i64::MAX, TimeUnit::Millisecond).split();
1109 let _ = Timestamp::new(i64::MIN, TimeUnit::Millisecond).split();
1110 let _ = Timestamp::new(i64::MAX, TimeUnit::Microsecond).split();
1111 let _ = Timestamp::new(i64::MIN, TimeUnit::Microsecond).split();
1112 let _ = Timestamp::new(i64::MAX, TimeUnit::Nanosecond).split();
1113 let _ = Timestamp::new(i64::MIN, TimeUnit::Nanosecond).split();
1114 let (sec, nsec) = Timestamp::new(i64::MIN, TimeUnit::Nanosecond).split();
1115 let time = DateTime::from_timestamp(sec, nsec).unwrap().naive_utc();
1116 assert_eq!(sec, time.and_utc().timestamp());
1117 assert_eq!(nsec, time.and_utc().timestamp_subsec_nanos());
1118 }
1119
1120 #[test]
1121 fn test_timestamp_sub() {
1122 let res = Timestamp::new(1, TimeUnit::Second)
1123 .sub_duration(Duration::from_secs(1))
1124 .unwrap();
1125 assert_eq!(0, res.value);
1126 assert_eq!(TimeUnit::Second, res.unit);
1127
1128 let res = Timestamp::new(0, TimeUnit::Second)
1129 .sub_duration(Duration::from_secs(1))
1130 .unwrap();
1131 assert_eq!(-1, res.value);
1132 assert_eq!(TimeUnit::Second, res.unit);
1133
1134 let res = Timestamp::new(1, TimeUnit::Second)
1135 .sub_duration(Duration::from_millis(1))
1136 .unwrap();
1137 assert_eq!(1, res.value);
1138 assert_eq!(TimeUnit::Second, res.unit);
1139 }
1140
1141 #[test]
1142 fn test_timestamp_add() {
1143 let res = Timestamp::new(1, TimeUnit::Second)
1144 .add_duration(Duration::from_secs(1))
1145 .unwrap();
1146 assert_eq!(2, res.value);
1147 assert_eq!(TimeUnit::Second, res.unit);
1148
1149 let res = Timestamp::new(0, TimeUnit::Second)
1150 .add_duration(Duration::from_secs(1))
1151 .unwrap();
1152 assert_eq!(1, res.value);
1153 assert_eq!(TimeUnit::Second, res.unit);
1154
1155 let res = Timestamp::new(1, TimeUnit::Second)
1156 .add_duration(Duration::from_millis(1))
1157 .unwrap();
1158 assert_eq!(1, res.value);
1159 assert_eq!(TimeUnit::Second, res.unit);
1160
1161 let res = Timestamp::new(100, TimeUnit::Second)
1162 .add_duration(Duration::from_millis(1000))
1163 .unwrap();
1164 assert_eq!(101, res.value);
1165 assert_eq!(TimeUnit::Second, res.unit);
1166 }
1167
1168 #[test]
1170 fn test_parse_in_timezone() {
1171 std::env::set_var("TZ", "Asia/Shanghai");
1172 assert_eq!(
1173 Timestamp::new(28800, TimeUnit::Second),
1174 Timestamp::from_str_utc("1970-01-01 08:00:00.000").unwrap()
1175 );
1176
1177 assert_eq!(
1178 Timestamp::new(28800, TimeUnit::Second),
1179 Timestamp::from_str_utc("1970-01-01 08:00:00").unwrap()
1180 );
1181
1182 assert_eq!(
1183 Timestamp::new(28800, TimeUnit::Second),
1184 Timestamp::from_str_utc(" 1970-01-01 08:00:00 ").unwrap()
1185 );
1186 }
1187
1188 #[test]
1189 fn test_to_local_string() {
1190 set_default_timezone(Some("Asia/Shanghai")).unwrap();
1191
1192 assert_eq!(
1193 "1970-01-01 08:00:00.000000001",
1194 Timestamp::new(1, TimeUnit::Nanosecond).to_local_string()
1195 );
1196
1197 assert_eq!(
1198 "1970-01-01 08:00:00.001",
1199 Timestamp::new(1, TimeUnit::Millisecond).to_local_string()
1200 );
1201
1202 assert_eq!(
1203 "1970-01-01 08:00:01",
1204 Timestamp::new(1, TimeUnit::Second).to_local_string()
1205 );
1206 }
1207
1208 #[test]
1209 fn test_subtract_timestamp() {
1210 assert_eq!(
1211 chrono::Duration::try_milliseconds(42),
1212 Timestamp::new_millisecond(100).sub(&Timestamp::new_millisecond(58))
1213 );
1214
1215 assert_eq!(
1216 chrono::Duration::try_milliseconds(-42),
1217 Timestamp::new_millisecond(58).sub(&Timestamp::new_millisecond(100))
1218 );
1219 }
1220
1221 #[test]
1222 fn test_to_timezone_aware_string() {
1223 set_default_timezone(Some("Asia/Shanghai")).unwrap();
1224 std::env::set_var("TZ", "Asia/Shanghai");
1225 assert_eq!(
1226 "1970-01-01 08:00:00.001",
1227 Timestamp::new(1, TimeUnit::Millisecond)
1228 .to_timezone_aware_string(Some(&Timezone::from_tz_string("SYSTEM").unwrap()))
1229 );
1230 assert_eq!(
1231 "1970-01-01 08:00:00.001",
1232 Timestamp::new(1, TimeUnit::Millisecond)
1233 .to_timezone_aware_string(Some(&Timezone::from_tz_string("SYSTEM").unwrap()))
1234 );
1235 assert_eq!(
1236 "1970-01-01 08:00:00.001",
1237 Timestamp::new(1, TimeUnit::Millisecond)
1238 .to_timezone_aware_string(Some(&Timezone::from_tz_string("+08:00").unwrap()))
1239 );
1240 assert_eq!(
1241 "1970-01-01 07:00:00.001",
1242 Timestamp::new(1, TimeUnit::Millisecond)
1243 .to_timezone_aware_string(Some(&Timezone::from_tz_string("+07:00").unwrap()))
1244 );
1245 assert_eq!(
1246 "1969-12-31 23:00:00.001",
1247 Timestamp::new(1, TimeUnit::Millisecond)
1248 .to_timezone_aware_string(Some(&Timezone::from_tz_string("-01:00").unwrap()))
1249 );
1250 assert_eq!(
1251 "1970-01-01 08:00:00.001",
1252 Timestamp::new(1, TimeUnit::Millisecond).to_timezone_aware_string(Some(
1253 &Timezone::from_tz_string("Asia/Shanghai").unwrap()
1254 ))
1255 );
1256 assert_eq!(
1257 "1970-01-01 00:00:00.001",
1258 Timestamp::new(1, TimeUnit::Millisecond)
1259 .to_timezone_aware_string(Some(&Timezone::from_tz_string("UTC").unwrap()))
1260 );
1261 assert_eq!(
1262 "1970-01-01 01:00:00.001",
1263 Timestamp::new(1, TimeUnit::Millisecond).to_timezone_aware_string(Some(
1264 &Timezone::from_tz_string("Europe/Berlin").unwrap()
1265 ))
1266 );
1267 assert_eq!(
1268 "1970-01-01 03:00:00.001",
1269 Timestamp::new(1, TimeUnit::Millisecond).to_timezone_aware_string(Some(
1270 &Timezone::from_tz_string("Europe/Moscow").unwrap()
1271 ))
1272 );
1273 }
1274
1275 #[test]
1276 fn test_as_formatted_string() {
1277 let ts = Timestamp::new(1, TimeUnit::Millisecond);
1278
1279 assert_eq!(
1280 "1970-01-01",
1281 ts.as_formatted_string("%Y-%m-%d", None).unwrap()
1282 );
1283 assert_eq!(
1284 "1970-01-01 00:00:00",
1285 ts.as_formatted_string("%Y-%m-%d %H:%M:%S", None).unwrap()
1286 );
1287 assert_eq!(
1288 "1970-01-01T00:00:00:001",
1289 ts.as_formatted_string("%Y-%m-%dT%H:%M:%S:%3f", None)
1290 .unwrap()
1291 );
1292 assert_eq!(
1293 "1970-01-01T08:00:00:001",
1294 ts.as_formatted_string(
1295 "%Y-%m-%dT%H:%M:%S:%3f",
1296 Some(&Timezone::from_tz_string("Asia/Shanghai").unwrap())
1297 )
1298 .unwrap()
1299 );
1300 }
1301
1302 #[test]
1303 fn test_from_arrow_time_unit() {
1304 assert_eq!(TimeUnit::Second, TimeUnit::from(ArrowTimeUnit::Second));
1305 assert_eq!(
1306 TimeUnit::Millisecond,
1307 TimeUnit::from(ArrowTimeUnit::Millisecond)
1308 );
1309 assert_eq!(
1310 TimeUnit::Microsecond,
1311 TimeUnit::from(ArrowTimeUnit::Microsecond)
1312 );
1313 assert_eq!(
1314 TimeUnit::Nanosecond,
1315 TimeUnit::from(ArrowTimeUnit::Nanosecond)
1316 );
1317 }
1318
1319 fn check_conversion(ts: Timestamp, valid: bool) {
1320 let Some(t2) = ts.to_chrono_datetime() else {
1321 if valid {
1322 panic!("Cannot convert {:?} to Chrono NaiveDateTime", ts);
1323 }
1324 return;
1325 };
1326 let Some(t3) = Timestamp::from_chrono_datetime(t2) else {
1327 if valid {
1328 panic!("Cannot convert Chrono NaiveDateTime {:?} to Timestamp", t2);
1329 }
1330 return;
1331 };
1332
1333 assert_eq!(t3, ts);
1334 }
1335
1336 #[test]
1337 fn test_from_naive_date_time() {
1338 let naive_date_time_min = NaiveDateTime::MIN.and_utc();
1339 let naive_date_time_max = NaiveDateTime::MAX.and_utc();
1340
1341 let min_sec = Timestamp::new_second(naive_date_time_min.timestamp());
1342 let max_sec = Timestamp::new_second(naive_date_time_max.timestamp());
1343 check_conversion(min_sec, true);
1344 check_conversion(Timestamp::new_second(min_sec.value - 1), false);
1345 check_conversion(max_sec, true);
1346 check_conversion(Timestamp::new_second(max_sec.value + 1), false);
1347
1348 let min_millis = Timestamp::new_millisecond(naive_date_time_min.timestamp_millis());
1349 let max_millis = Timestamp::new_millisecond(naive_date_time_max.timestamp_millis());
1350 check_conversion(min_millis, true);
1351 check_conversion(Timestamp::new_millisecond(min_millis.value - 1), false);
1352 check_conversion(max_millis, true);
1353 check_conversion(Timestamp::new_millisecond(max_millis.value + 1), false);
1354
1355 let min_micros = Timestamp::new_microsecond(naive_date_time_min.timestamp_micros());
1356 let max_micros = Timestamp::new_microsecond(naive_date_time_max.timestamp_micros());
1357 check_conversion(min_micros, true);
1358 check_conversion(Timestamp::new_microsecond(min_micros.value - 1), false);
1359 check_conversion(max_micros, true);
1360 check_conversion(Timestamp::new_microsecond(max_micros.value + 1), false);
1361
1362 let min_nanos = Timestamp::new_nanosecond(-9223372036854775000);
1364 let max_nanos = Timestamp::new_nanosecond(i64::MAX);
1365 check_conversion(min_nanos, true);
1366 check_conversion(Timestamp::new_nanosecond(min_nanos.value - 1), false);
1367 check_conversion(max_nanos, true);
1368 }
1369
1370 #[test]
1371 fn test_parse_timestamp_range() {
1372 let datetime_min = NaiveDateTime::MIN.format("%Y-%m-%d %H:%M:%SZ").to_string();
1373 assert_eq!("-262143-01-01 00:00:00Z", datetime_min);
1374 let datetime_max = NaiveDateTime::MAX.format("%Y-%m-%d %H:%M:%SZ").to_string();
1375 assert_eq!("+262142-12-31 23:59:59Z", datetime_max);
1376
1377 let valid_strings = vec![
1378 "-262143-01-01 00:00:00Z",
1379 "+262142-12-31 23:59:59Z",
1380 "+262142-12-31 23:59:59.999Z",
1381 "+262142-12-31 23:59:59.999999Z",
1382 "1677-09-21 00:12:43.145224192Z",
1383 "2262-04-11 23:47:16.854775807Z",
1384 "+100000-01-01 00:00:01.5Z",
1385 ];
1386
1387 for s in valid_strings {
1388 Timestamp::from_str_utc(s).unwrap();
1389 }
1390 }
1391
1392 #[test]
1393 fn test_min_nanos_roundtrip() {
1394 let (sec, nsec) = Timestamp::MIN_NANOSECOND.split();
1395 let ts = Timestamp::from_splits(sec, nsec).unwrap();
1396 assert_eq!(Timestamp::MIN_NANOSECOND, ts);
1397 }
1398
1399 #[test]
1400 fn test_timestamp_bound_format() {
1401 assert_eq!(
1402 "1677-09-21 00:12:43.145224192",
1403 Timestamp::MIN_NANOSECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1404 );
1405 assert_eq!(
1406 "2262-04-11 23:47:16.854775807",
1407 Timestamp::MAX_NANOSECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1408 );
1409 assert_eq!(
1410 "-262143-01-01 00:00:00",
1411 Timestamp::MIN_MICROSECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1412 );
1413 assert_eq!(
1414 "+262142-12-31 23:59:59.999999",
1415 Timestamp::MAX_MICROSECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1416 );
1417 assert_eq!(
1418 "-262143-01-01 00:00:00",
1419 Timestamp::MIN_MILLISECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1420 );
1421 assert_eq!(
1422 "+262142-12-31 23:59:59.999",
1423 Timestamp::MAX_MILLISECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1424 );
1425 assert_eq!(
1426 "-262143-01-01 00:00:00",
1427 Timestamp::MIN_SECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1428 );
1429 assert_eq!(
1430 "+262142-12-31 23:59:59",
1431 Timestamp::MAX_SECOND.to_timezone_aware_string(Some(&Timezone::Named(Tz::UTC)))
1432 );
1433 }
1434
1435 #[test]
1436 fn test_debug_timestamp() {
1437 assert_eq!(
1438 "1000::Second",
1439 format!("{:?}", Timestamp::new(1000, TimeUnit::Second))
1440 );
1441 assert_eq!(
1442 "1001::Millisecond",
1443 format!("{:?}", Timestamp::new(1001, TimeUnit::Millisecond))
1444 );
1445 assert_eq!(
1446 "1002::Microsecond",
1447 format!("{:?}", Timestamp::new(1002, TimeUnit::Microsecond))
1448 );
1449 assert_eq!(
1450 "1003::Nanosecond",
1451 format!("{:?}", Timestamp::new(1003, TimeUnit::Nanosecond))
1452 );
1453 }
1454}