Skip to main content

bullet_exchange_interface/
time.rs

1use crate::define_simple_type;
2use crate::error::{ArithmeticError, ArithmeticOperation};
3
4// Stores microseconds since Unix Epoch.
5define_simple_type!(UnixTimestampMicros(i64));
6
7pub const MICROSECONDS_PER_HOUR: i64 = 3_600_000_000;
8pub const ONE_HOUR: UnixTimestampMicros = UnixTimestampMicros(MICROSECONDS_PER_HOUR);
9
10impl UnixTimestampMicros {
11    pub const ZERO: Self = Self(0);
12    pub fn from_secs(secs: i64) -> Result<Self, ArithmeticError> {
13        let micros = secs.checked_mul(1_000_000).ok_or(ArithmeticError::IntegerFailed {
14            operation: ArithmeticOperation::Multiplication,
15            left: secs as i128,
16            right: 1_000_000,
17        })?;
18        Ok(Self(micros))
19    }
20
21    pub fn from_secs_u32(secs: u32) -> Self {
22        #[allow(clippy::arithmetic_side_effects)]
23        Self((secs as i64) * 1_000_000)
24    }
25
26    pub fn from_micros(micros: i64) -> Self {
27        Self(micros)
28    }
29
30    pub fn from_millis(millis: i64) -> Result<Self, ArithmeticError> {
31        millis.checked_mul(1000).map(Self).ok_or(ArithmeticError::IntegerFailed {
32            operation: ArithmeticOperation::Multiplication,
33            left: millis as i128,
34            right: 1000,
35        })
36    }
37    pub fn from_nanos(nanos: u128) -> Result<Self, ArithmeticError> {
38        (nanos / 1000).try_into().map(Self).map_err(|_| ArithmeticError::IntegerFailed {
39            operation: ArithmeticOperation::Division,
40            left: nanos as i128,
41            right: 1000,
42        })
43    }
44
45    pub fn as_secs(&self) -> i64 {
46        self.0 / 1_000_000
47    }
48
49    pub fn as_micros(&self) -> i64 {
50        self.0
51    }
52
53    pub fn as_hour(&self) -> i64 {
54        self.0 / MICROSECONDS_PER_HOUR
55    }
56
57    pub fn checked_add_secs(&self, other: i64) -> Result<Self, ArithmeticError> {
58        self.checked_add(Self::from_secs(other)?)
59    }
60    pub fn checked_add(&self, other: UnixTimestampMicros) -> Result<Self, ArithmeticError> {
61        self.0.checked_add(other.0).map(Self).ok_or(ArithmeticError::IntegerFailed {
62            operation: ArithmeticOperation::Addition,
63            left: self.0 as i128,
64            right: other.0 as i128,
65        })
66    }
67
68    /// Returns the microseconds elapsed. Or zero on errors.
69    pub fn elapsed_micros(self, other: UnixTimestampMicros) -> i64 {
70        self.0.checked_sub(other.0).unwrap_or(0).max(0)
71    }
72
73    /// Returns the seconds elapsed. Or zero on errors.
74    pub fn elapsed_secs(self, other: UnixTimestampMicros) -> u64 {
75        let delta = self.as_secs().checked_sub(other.as_secs()).unwrap_or(0).max(0);
76        // Safe to cast to u64 as it will be 0 or larger
77        delta as u64
78    }
79}