1use std::fmt::Display;
16
17use common_time::timestamp::TimeUnit;
18
19use crate::Error;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub enum Precision {
25 Nanosecond,
26 Microsecond,
27 Millisecond,
28 Second,
29 Minute,
30 Hour,
31}
32
33impl Precision {
34 pub fn to_nanos(&self, amount: i64) -> Option<i64> {
35 match self {
36 Precision::Nanosecond => Some(amount),
37 Precision::Microsecond => amount.checked_mul(1_000),
38 Precision::Millisecond => amount.checked_mul(1_000_000),
39 Precision::Second => amount.checked_mul(1_000_000_000),
40 Precision::Minute => amount
41 .checked_mul(60)
42 .and_then(|a| a.checked_mul(1_000_000_000)),
43 Precision::Hour => amount
44 .checked_mul(3600)
45 .and_then(|a| a.checked_mul(1_000_000_000)),
46 }
47 }
48
49 pub fn to_millis(&self, amount: i64) -> Option<i64> {
50 match self {
51 Precision::Nanosecond => amount.checked_div(1_000_000),
52 Precision::Microsecond => amount.checked_div(1_000),
53 Precision::Millisecond => Some(amount),
54 Precision::Second => amount.checked_mul(1_000),
55 Precision::Minute => amount.checked_mul(60_000),
56 Precision::Hour => amount.checked_mul(3_600_000),
57 }
58 }
59}
60
61impl Display for Precision {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 match self {
64 Precision::Nanosecond => write!(f, "Precision::Nanosecond"),
65 Precision::Microsecond => write!(f, "Precision::Microsecond"),
66 Precision::Millisecond => write!(f, "Precision::Millisecond"),
67 Precision::Second => write!(f, "Precision::Second"),
68 Precision::Minute => write!(f, "Precision::Minute"),
69 Precision::Hour => write!(f, "Precision::Hour"),
70 }
71 }
72}
73
74impl TryFrom<Precision> for TimeUnit {
75 type Error = Error;
76
77 fn try_from(precision: Precision) -> Result<Self, Self::Error> {
78 Ok(match precision {
79 Precision::Second => TimeUnit::Second,
80 Precision::Millisecond => TimeUnit::Millisecond,
81 Precision::Microsecond => TimeUnit::Microsecond,
82 Precision::Nanosecond => TimeUnit::Nanosecond,
83 _ => {
84 return Err(Error::NotSupported {
85 feat: format!("convert {precision} into TimeUnit"),
86 })
87 }
88 })
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use crate::precision::Precision;
95
96 #[test]
97 fn test_to_nanos() {
98 assert_eq!(Precision::Nanosecond.to_nanos(1).unwrap(), 1);
99 assert_eq!(Precision::Microsecond.to_nanos(1).unwrap(), 1_000);
100 assert_eq!(Precision::Millisecond.to_nanos(1).unwrap(), 1_000_000);
101 assert_eq!(Precision::Second.to_nanos(1).unwrap(), 1_000_000_000);
102 assert_eq!(Precision::Minute.to_nanos(1).unwrap(), 60 * 1_000_000_000);
103 assert_eq!(
104 Precision::Hour.to_nanos(1).unwrap(),
105 60 * 60 * 1_000_000_000
106 );
107 }
108
109 #[test]
110 fn test_to_millis() {
111 assert_eq!(Precision::Nanosecond.to_millis(1_000_000).unwrap(), 1);
112 assert_eq!(Precision::Microsecond.to_millis(1_000).unwrap(), 1);
113 assert_eq!(Precision::Millisecond.to_millis(1).unwrap(), 1);
114 assert_eq!(Precision::Second.to_millis(1).unwrap(), 1_000);
115 assert_eq!(Precision::Minute.to_millis(1).unwrap(), 60 * 1_000);
116 assert_eq!(Precision::Hour.to_millis(1).unwrap(), 60 * 60 * 1_000);
117 }
118
119 #[test]
120 fn test_to_nanos_basic() {
121 assert_eq!(Precision::Second.to_nanos(1), Some(1_000_000_000));
122 assert_eq!(Precision::Minute.to_nanos(1), Some(60 * 1_000_000_000));
123 }
124
125 #[test]
126 fn test_to_millis_basic() {
127 assert_eq!(Precision::Second.to_millis(1), Some(1_000));
128 assert_eq!(Precision::Minute.to_millis(1), Some(60_000));
129 }
130
131 #[test]
132 fn test_to_nanos_overflow() {
133 assert_eq!(Precision::Hour.to_nanos(i64::MAX / 100), None);
134 }
135
136 #[test]
137 fn test_zero_input() {
138 assert_eq!(Precision::Second.to_nanos(0), Some(0));
139 assert_eq!(Precision::Minute.to_millis(0), Some(0));
140 }
141}