scsys_core/time/
timestamp.rs

1/*
2    Appellation: timestamp <module>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5use crate::time::{Now, RawTimestamp};
6
7/// [`Timestamp`] is a generic implementation of a type that represents some point in time.
8///
9/// ## Usage
10///
11/// ### Examples
12///
13/// #### _Example #1_ Using the [`now`](Timestamp::now) method to get the current timestamp
14///
15/// ```rust
16/// #[cfg(feature = "std")]
17/// let ts = scsys_core::Timestamp::<u64>::now();
18/// ```
19///
20/// ## Features
21///
22/// The timestamps implementation dynamically reflects the extensive feature-gating of the
23/// crate. Listed below are the features that customize the behavior of the [`Timestamp`] type:
24///
25/// - `serde`: Enables serialization and deserialization of the [`Timestamp`] type.
26///
27/// - `chrono`: Enables support for `chrono` timestamps, uses [`i64`] for the [Now] impl
28/// - `std`: Enables the use of system time for the default implementation of:
29///   - `Timestamp<u64>`: for seconds
30///   - `Timestamp<u128>`: for milliseconds
31///
32#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
33#[cfg_attr(
34    feature = "serde",
35    derive(serde::Deserialize, serde::Serialize),
36    serde(transparent)
37)]
38#[repr(transparent)]
39pub struct Timestamp<T = u64>(pub T);
40
41impl<T> Timestamp<T>
42where
43    T: RawTimestamp,
44{
45    /// create a new instance of [`Timestamp`] with the given value.
46    pub fn new(ts: T) -> Self {
47        Self(ts)
48    }
49    /// a convenience method to create a new [`Timestamp`] instance with the current time.
50    pub fn now() -> Self
51    where
52        Self: Now<Output = Self>,
53    {
54        <Self as Now>::now()
55    }
56    /// Get an immutable reference to the current timestamp.
57    pub const fn get(&self) -> &T {
58        &self.0
59    }
60    /// Get a mutable reference to the current timestamp.
61    pub const fn get_mut(&mut self) -> &mut T {
62        &mut self.0
63    }
64    /// consumes the current instance and returns the inner value.
65    #[inline]
66    pub fn value(self) -> T {
67        self.0
68    }
69    /// [`replace`](core::mem::replace) the current value with a new one and return the old one
70    pub const fn replace(&mut self, value: T) -> T {
71        core::mem::replace(self.get_mut(), value)
72    }
73    /// update the current value and return a mutable reference to the current instance.
74    #[inline]
75    pub fn set(&mut self, ts: T) -> &mut Self {
76        *self.get_mut() = ts;
77        self
78    }
79    /// [`swap`](core::mem::swap) the current value with another and return a mutable reference to self
80    pub const fn swap(&mut self, ts: &mut T) {
81        core::mem::swap(self.get_mut(), ts)
82    }
83    /// [`take`](core::mem::take) the current value and return it, leaving the logical
84    /// [`default`](Default::default) in its place.
85    #[inline]
86    pub fn take(&mut self) -> T
87    where
88        T: Default,
89    {
90        core::mem::take(self.get_mut())
91    }
92    /// consumes the current instance to create another with the given value
93    #[inline]
94    pub fn with<U: RawTimestamp>(self, ts: U) -> Timestamp<U> {
95        Timestamp(ts)
96    }
97    /// applies a function onto the current value and returns a new instance with the result
98    pub fn map<U, F>(self, f: F) -> Timestamp<U>
99    where
100        F: FnOnce(T) -> U,
101        U: RawTimestamp,
102    {
103        Timestamp(f(self.value()))
104    }
105    /// returns a new instance of the [`Timestamp`] with the current value updated using the given function
106    pub fn map_inplace<F>(&mut self, f: F) -> &mut Self
107    where
108        F: FnOnce(&mut T),
109    {
110        f(self.get_mut());
111        self
112    }
113    /// updates the timestamp to reflect _now_ and return the previous timestamp
114    pub fn update(&mut self) -> T
115    where
116        T: Now<Output = T>,
117    {
118        let now = T::now();
119        // replace the current value with the new one
120        self.replace(now)
121    }
122    /// returns a new instance of the [`Timestamp`] containing an immutable reference to the
123    /// inner value.
124    pub const fn view(&self) -> Timestamp<&T> {
125        Timestamp(self.get())
126    }
127    /// returns a new instance of the [`Timestamp`] containing a mutable reference to the inner
128    /// value.
129    pub const fn view_mut(&mut self) -> Timestamp<&mut T> {
130        Timestamp(self.get_mut())
131    }
132}
133#[allow(deprecated)]
134impl<T> Timestamp<T>
135where
136    T: RawTimestamp,
137{
138    #[deprecated(since = "0.2.8", note = "use `Timestamp::get` instead")]
139    pub fn as_ref(&self) -> &T {
140        self.get()
141    }
142    #[deprecated(since = "0.2.8", note = "use `Timestamp::get_mut` instead")]
143    pub fn as_mut(&mut self) -> &mut T {
144        self.get_mut()
145    }
146    #[deprecated(since = "0.2.8", note = "use `Timestamp::value` instead")]
147    pub fn into_inner(self) -> T {
148        self.0
149    }
150}
151
152impl<T> Default for Timestamp<T>
153where
154    Self: Now<Output = Self>,
155    T: RawTimestamp,
156{
157    fn default() -> Self {
158        Self::now()
159    }
160}
161
162#[cfg(feature = "std")]
163impl Now for Timestamp<u64> {
164    type Output = Self;
165
166    fn now() -> Self::Output {
167        Self::new(super::systime().as_secs())
168    }
169}
170
171#[cfg(feature = "std")]
172impl Now for Timestamp<u128> {
173    type Output = Self;
174
175    fn now() -> Self::Output {
176        Self::new(super::systime().as_millis())
177    }
178}
179
180#[cfg(feature = "chrono")]
181impl Now for Timestamp<i64> {
182    type Output = Self;
183
184    fn now() -> Self::Output {
185        Self::new(chrono::Local::now().timestamp())
186    }
187}
188
189impl<T: RawTimestamp> AsRef<T> for Timestamp<T> {
190    fn as_ref(&self) -> &T {
191        self.get()
192    }
193}
194
195impl<T: RawTimestamp> AsMut<T> for Timestamp<T> {
196    fn as_mut(&mut self) -> &mut T {
197        self.get_mut()
198    }
199}
200
201impl<T: RawTimestamp> core::borrow::Borrow<T> for Timestamp<T> {
202    fn borrow(&self) -> &T {
203        self.get()
204    }
205}
206
207impl<T: RawTimestamp> core::borrow::BorrowMut<T> for Timestamp<T> {
208    fn borrow_mut(&mut self) -> &mut T {
209        self.get_mut()
210    }
211}
212
213impl<T: RawTimestamp> core::ops::Deref for Timestamp<T> {
214    type Target = T;
215
216    fn deref(&self) -> &Self::Target {
217        self.get()
218    }
219}
220
221impl<T: RawTimestamp> core::ops::DerefMut for Timestamp<T> {
222    fn deref_mut(&mut self) -> &mut Self::Target {
223        self.get_mut()
224    }
225}
226
227crate::fmt_wrapper! {
228    Timestamp<T>(
229        Binary,
230        Octal,
231        LowerHex,
232        UpperHex,
233        Display,
234        Debug,
235        LowerExp,
236        UpperExp,
237        Pointer,
238    )
239}
240
241impl From<core::time::Duration> for Timestamp<u64> {
242    fn from(dur: core::time::Duration) -> Self {
243        Self(dur.as_secs())
244    }
245}
246
247impl From<core::time::Duration> for Timestamp<u128> {
248    fn from(dur: core::time::Duration) -> Self {
249        Self(dur.as_millis())
250    }
251}
252
253impl From<Timestamp<u64>> for core::time::Duration {
254    fn from(ts: Timestamp<u64>) -> Self {
255        Self::from_secs(*ts)
256    }
257}
258
259impl From<Timestamp<u128>> for core::time::Duration {
260    fn from(ts: Timestamp<u128>) -> Self {
261        Self::from_millis(*ts as u64)
262    }
263}
264
265#[cfg(feature = "chrono")]
266impl<Tz> From<chrono::DateTime<Tz>> for Timestamp<i64>
267where
268    Tz: chrono::TimeZone,
269{
270    fn from(ts: chrono::DateTime<Tz>) -> Self {
271        Self(ts.timestamp())
272    }
273}