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 into_inner(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.into_inner()))
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
134#[doc(hidden)]
135#[allow(deprecated)]
136impl<T> Timestamp<T>
137where
138    T: RawTimestamp,
139{
140    #[deprecated(
141        since = "0.2.8",
142        note = "use `get` instead; this will be removed in the next major release"
143    )]
144    pub fn as_ref(&self) -> &T {
145        self.get()
146    }
147    #[deprecated(
148        since = "0.2.8",
149        note = "use `get_mut` instead; this will be removed in the next major release"
150    )]
151    pub fn as_mut(&mut self) -> &mut T {
152        self.get_mut()
153    }
154    #[deprecated(
155        since = "0.3.1",
156        note = "use `into_innter` instead; this will be removed in the next major release"
157    )]
158    pub fn value(self) -> T {
159        self.0
160    }
161}
162
163impl<T> Default for Timestamp<T>
164where
165    Self: Now<Output = Self>,
166    T: RawTimestamp,
167{
168    fn default() -> Self {
169        Self::now()
170    }
171}
172
173#[cfg(feature = "std")]
174impl Now for Timestamp<u64> {
175    type Output = Self;
176
177    fn now() -> Self::Output {
178        Self::new(super::systime().as_secs())
179    }
180}
181
182#[cfg(feature = "std")]
183impl Now for Timestamp<u128> {
184    type Output = Self;
185
186    fn now() -> Self::Output {
187        Self::new(super::systime().as_millis())
188    }
189}
190
191#[cfg(feature = "chrono")]
192impl Now for Timestamp<i64> {
193    type Output = Self;
194
195    fn now() -> Self::Output {
196        Self::new(chrono::Local::now().timestamp())
197    }
198}