surrealdb/sql/
duration.rs1use crate::sql::datetime::Datetime;
2use crate::sql::strand::Strand;
3use crate::syn;
4use revision::revisioned;
5use serde::{Deserialize, Serialize};
6use std::fmt;
7use std::iter::Sum;
8use std::ops;
9use std::ops::Deref;
10use std::str::FromStr;
11use std::time;
12
13pub(crate) static SECONDS_PER_YEAR: u64 = 365 * SECONDS_PER_DAY;
14pub(crate) static SECONDS_PER_WEEK: u64 = 7 * SECONDS_PER_DAY;
15pub(crate) static SECONDS_PER_DAY: u64 = 24 * SECONDS_PER_HOUR;
16pub(crate) static SECONDS_PER_HOUR: u64 = 60 * SECONDS_PER_MINUTE;
17pub(crate) static SECONDS_PER_MINUTE: u64 = 60;
18pub(crate) static NANOSECONDS_PER_MILLISECOND: u32 = 1000000;
19pub(crate) static NANOSECONDS_PER_MICROSECOND: u32 = 1000;
20
21pub(crate) const TOKEN: &str = "$surrealdb::private::sql::Duration";
22
23#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
24#[serde(rename = "$surrealdb::private::sql::Duration")]
25#[revisioned(revision = 1)]
26pub struct Duration(pub time::Duration);
27
28impl From<time::Duration> for Duration {
29 fn from(v: time::Duration) -> Self {
30 Self(v)
31 }
32}
33
34impl From<Duration> for time::Duration {
35 fn from(s: Duration) -> Self {
36 s.0
37 }
38}
39
40impl FromStr for Duration {
41 type Err = ();
42 fn from_str(s: &str) -> Result<Self, Self::Err> {
43 Self::try_from(s)
44 }
45}
46
47impl TryFrom<String> for Duration {
48 type Error = ();
49 fn try_from(v: String) -> Result<Self, Self::Error> {
50 Self::try_from(v.as_str())
51 }
52}
53
54impl TryFrom<Strand> for Duration {
55 type Error = ();
56 fn try_from(v: Strand) -> Result<Self, Self::Error> {
57 Self::try_from(v.as_str())
58 }
59}
60
61impl TryFrom<&str> for Duration {
62 type Error = ();
63 fn try_from(v: &str) -> Result<Self, Self::Error> {
64 match syn::duration(v) {
65 Ok(v) => Ok(v),
66 _ => Err(()),
67 }
68 }
69}
70
71impl Deref for Duration {
72 type Target = time::Duration;
73 fn deref(&self) -> &Self::Target {
74 &self.0
75 }
76}
77
78impl Duration {
79 pub fn to_raw(&self) -> String {
81 self.to_string()
82 }
83 pub fn nanos(&self) -> u128 {
85 self.0.as_nanos()
86 }
87 pub fn micros(&self) -> u128 {
89 self.0.as_micros()
90 }
91 pub fn millis(&self) -> u128 {
93 self.0.as_millis()
94 }
95 pub fn secs(&self) -> u64 {
97 self.0.as_secs()
98 }
99 pub fn mins(&self) -> u64 {
101 self.0.as_secs() / SECONDS_PER_MINUTE
102 }
103 pub fn hours(&self) -> u64 {
105 self.0.as_secs() / SECONDS_PER_HOUR
106 }
107 pub fn days(&self) -> u64 {
109 self.0.as_secs() / SECONDS_PER_DAY
110 }
111 pub fn weeks(&self) -> u64 {
113 self.0.as_secs() / SECONDS_PER_WEEK
114 }
115 pub fn years(&self) -> u64 {
117 self.0.as_secs() / SECONDS_PER_YEAR
118 }
119 pub fn from_nanos(nanos: u64) -> Duration {
121 time::Duration::from_nanos(nanos).into()
122 }
123 pub fn from_micros(micros: u64) -> Duration {
125 time::Duration::from_micros(micros).into()
126 }
127 pub fn from_millis(millis: u64) -> Duration {
129 time::Duration::from_millis(millis).into()
130 }
131 pub fn from_secs(secs: u64) -> Duration {
133 time::Duration::from_secs(secs).into()
134 }
135 pub fn from_mins(mins: u64) -> Duration {
137 time::Duration::from_secs(mins * SECONDS_PER_MINUTE).into()
138 }
139 pub fn from_hours(hours: u64) -> Duration {
141 time::Duration::from_secs(hours * SECONDS_PER_HOUR).into()
142 }
143 pub fn from_days(days: u64) -> Duration {
145 time::Duration::from_secs(days * SECONDS_PER_DAY).into()
146 }
147 pub fn from_weeks(days: u64) -> Duration {
149 time::Duration::from_secs(days * SECONDS_PER_WEEK).into()
150 }
151}
152
153impl fmt::Display for Duration {
154 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
155 let secs = self.0.as_secs();
157 let nano = self.0.subsec_nanos();
158 if secs == 0 && nano == 0 {
160 return write!(f, "0ns");
161 }
162 let year = secs / SECONDS_PER_YEAR;
164 let secs = secs % SECONDS_PER_YEAR;
165 let week = secs / SECONDS_PER_WEEK;
167 let secs = secs % SECONDS_PER_WEEK;
168 let days = secs / SECONDS_PER_DAY;
170 let secs = secs % SECONDS_PER_DAY;
171 let hour = secs / SECONDS_PER_HOUR;
173 let secs = secs % SECONDS_PER_HOUR;
174 let mins = secs / SECONDS_PER_MINUTE;
176 let secs = secs % SECONDS_PER_MINUTE;
177 let msec = nano / NANOSECONDS_PER_MILLISECOND;
179 let nano = nano % NANOSECONDS_PER_MILLISECOND;
180 let usec = nano / NANOSECONDS_PER_MICROSECOND;
182 let nano = nano % NANOSECONDS_PER_MICROSECOND;
183 if year > 0 {
185 write!(f, "{year}y")?;
186 }
187 if week > 0 {
188 write!(f, "{week}w")?;
189 }
190 if days > 0 {
191 write!(f, "{days}d")?;
192 }
193 if hour > 0 {
194 write!(f, "{hour}h")?;
195 }
196 if mins > 0 {
197 write!(f, "{mins}m")?;
198 }
199 if secs > 0 {
200 write!(f, "{secs}s")?;
201 }
202 if msec > 0 {
203 write!(f, "{msec}ms")?;
204 }
205 if usec > 0 {
206 write!(f, "{usec}µs")?;
207 }
208 if nano > 0 {
209 write!(f, "{nano}ns")?;
210 }
211 Ok(())
212 }
213}
214
215impl ops::Add for Duration {
216 type Output = Self;
217 fn add(self, other: Self) -> Self {
218 match self.0.checked_add(other.0) {
219 Some(v) => Duration::from(v),
220 None => Duration::from(time::Duration::MAX),
221 }
222 }
223}
224
225impl<'a, 'b> ops::Add<&'b Duration> for &'a Duration {
226 type Output = Duration;
227 fn add(self, other: &'b Duration) -> Duration {
228 match self.0.checked_add(other.0) {
229 Some(v) => Duration::from(v),
230 None => Duration::from(time::Duration::MAX),
231 }
232 }
233}
234
235impl ops::Sub for Duration {
236 type Output = Self;
237 fn sub(self, other: Self) -> Self {
238 match self.0.checked_sub(other.0) {
239 Some(v) => Duration::from(v),
240 None => Duration::default(),
241 }
242 }
243}
244
245impl<'a, 'b> ops::Sub<&'b Duration> for &'a Duration {
246 type Output = Duration;
247 fn sub(self, other: &'b Duration) -> Duration {
248 match self.0.checked_sub(other.0) {
249 Some(v) => Duration::from(v),
250 None => Duration::default(),
251 }
252 }
253}
254
255impl ops::Add<Datetime> for Duration {
256 type Output = Datetime;
257 fn add(self, other: Datetime) -> Datetime {
258 match chrono::Duration::from_std(self.0) {
259 Ok(d) => Datetime::from(other.0 + d),
260 Err(_) => Datetime::default(),
261 }
262 }
263}
264
265impl ops::Sub<Datetime> for Duration {
266 type Output = Datetime;
267 fn sub(self, other: Datetime) -> Datetime {
268 match chrono::Duration::from_std(self.0) {
269 Ok(d) => Datetime::from(other.0 - d),
270 Err(_) => Datetime::default(),
271 }
272 }
273}
274
275impl Sum<Self> for Duration {
276 fn sum<I>(iter: I) -> Duration
277 where
278 I: Iterator<Item = Self>,
279 {
280 iter.fold(Duration::default(), |a, b| a + b)
281 }
282}
283
284impl<'a> Sum<&'a Self> for Duration {
285 fn sum<I>(iter: I) -> Duration
286 where
287 I: Iterator<Item = &'a Self>,
288 {
289 iter.fold(Duration::default(), |a, b| &a + b)
290 }
291}