saa_common/types/
ts.rs

1use core::fmt;
2use saa_schema::saa_str_struct;
3use super::uints::Uint64;
4
5#[saa_str_struct]
6pub struct Timestamp(Uint64);
7
8impl Timestamp {
9    /// Creates a timestamp from nanoseconds since epoch
10    pub const fn from_nanos(nanos_since_epoch: u64) -> Self {
11        Timestamp(Uint64::new(nanos_since_epoch))
12    }
13
14    /// Creates a timestamp from seconds since epoch
15    pub const fn from_seconds(seconds_since_epoch: u64) -> Self {
16        Timestamp(Uint64::new(seconds_since_epoch * 1_000_000_000))
17    }
18
19    /// Adds the given amount of days to the timestamp and
20    /// returns the result. The original value remains unchanged.
21    ///
22    /// Panics if the result exceeds the value range of [`Timestamp`].
23    #[must_use = "this returns the result of the operation, without modifying the original"]
24    #[inline]
25    pub const fn plus_days(&self, addition: u64) -> Timestamp {
26        self.plus_hours(addition * 24)
27    }
28
29    /// Adds the given amount of hours to the timestamp and
30    /// returns the result. The original value remains unchanged.
31    ///
32    /// Panics if the result exceeds the value range of [`Timestamp`].
33    #[must_use = "this returns the result of the operation, without modifying the original"]
34    #[inline]
35    pub const fn plus_hours(&self, addition: u64) -> Timestamp {
36        self.plus_minutes(addition * 60)
37    }
38
39    /// Adds the given amount of minutes to the timestamp and
40    /// returns the result. The original value remains unchanged.
41    ///
42    /// Panics if the result exceeds the value range of [`Timestamp`].
43    #[must_use = "this returns the result of the operation, without modifying the original"]
44    #[inline]
45    pub const fn plus_minutes(&self, addition: u64) -> Timestamp {
46        self.plus_seconds(addition * 60)
47    }
48
49    /// Adds the given amount of seconds to the timestamp and
50    /// returns the result. The original value remains unchanged.
51    ///
52    /// Panics if the result exceeds the value range of [`Timestamp`].
53    #[must_use = "this returns the result of the operation, without modifying the original"]
54    #[inline]
55    pub const fn plus_seconds(&self, addition: u64) -> Timestamp {
56        self.plus_nanos(addition * 1_000_000_000)
57    }
58
59    /// Adds the given amount of nanoseconds to the timestamp and
60    /// returns the result. The original value remains unchanged.
61    ///
62    /// Panics if the result exceeds the value range of [`Timestamp`].
63    #[must_use = "this returns the result of the operation, without modifying the original"]
64    // no #[inline] here as this could be shared with all the callers
65    pub const fn plus_nanos(&self, addition: u64) -> Timestamp {
66        let nanos = self.0.strict_add(Uint64::new(addition));
67        Timestamp(nanos)
68    }
69
70    /// Subtracts the given amount of days from the timestamp and
71    /// returns the result. The original value remains unchanged.
72    ///
73    /// Panics if the result is not >= 0. I.e. times before epoch cannot be represented.
74    #[must_use = "this returns the result of the operation, without modifying the original"]
75    #[inline]
76    pub const fn minus_days(&self, subtrahend: u64) -> Timestamp {
77        self.minus_hours(subtrahend * 24)
78    }
79
80    /// Subtracts the given amount of hours from the timestamp and
81    /// returns the result. The original value remains unchanged.
82    ///
83    /// Panics if the result is not >= 0. I.e. times before epoch cannot be represented.
84    #[must_use = "this returns the result of the operation, without modifying the original"]
85    #[inline]
86    pub const fn minus_hours(&self, subtrahend: u64) -> Timestamp {
87        self.minus_minutes(subtrahend * 60)
88    }
89
90    /// Subtracts the given amount of minutes from the timestamp and
91    /// returns the result. The original value remains unchanged.
92    ///
93    /// Panics if the result is not >= 0. I.e. times before epoch cannot be represented.
94    #[must_use = "this returns the result of the operation, without modifying the original"]
95    #[inline]
96    pub const fn minus_minutes(&self, subtrahend: u64) -> Timestamp {
97        self.minus_seconds(subtrahend * 60)
98    }
99
100    /// Subtracts the given amount of seconds from the timestamp and
101    /// returns the result. The original value remains unchanged.
102    ///
103    /// Panics if the result is not >= 0. I.e. times before epoch cannot be represented.
104    #[must_use = "this returns the result of the operation, without modifying the original"]
105    #[inline]
106    pub const fn minus_seconds(&self, subtrahend: u64) -> Timestamp {
107        self.minus_nanos(subtrahend * 1_000_000_000)
108    }
109
110    /// Subtracts the given amount of nanoseconds from the timestamp and
111    /// returns the result. The original value remains unchanged.
112    ///
113    /// Panics if the result is not >= 0. I.e. times before epoch cannot be represented.
114    #[must_use = "this returns the result of the operation, without modifying the original"]
115    // no #[inline] here as this could be shared with all the callers
116    pub const fn minus_nanos(&self, subtrahend: u64) -> Timestamp {
117        Timestamp(self.0.strict_sub(Uint64::new(subtrahend)))
118    }
119
120    /// Returns nanoseconds since epoch
121    #[inline]
122    pub fn nanos(&self) -> u64 {
123        self.0.u64()
124    }
125
126    /// Returns seconds since epoch (truncate nanoseconds)
127    #[inline]
128    pub fn seconds(&self) -> u64 {
129        self.0.u64() / 1_000_000_000
130    }
131
132    /// Returns nanoseconds since the last whole second (the remainder truncated
133    /// by `seconds()`)
134    #[inline]
135    pub fn subsec_nanos(&self) -> u64 {
136        self.0.u64() % 1_000_000_000
137    }
138}
139
140impl fmt::Display for Timestamp {
141    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
142        let whole = self.seconds();
143        let fractional = self.subsec_nanos();
144        write!(f, "{whole}.{fractional:09}")
145    }
146}