templar_primitives/
time.rs

1use crate::strnum::SU64;
2use alloc::fmt;
3#[cfg(feature = "schemars")]
4use alloc::string::String;
5#[cfg(any(feature = "borsh", feature = "schemars"))]
6use alloc::string::ToString;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10#[cfg_attr(feature = "serde", serde(transparent))]
11#[cfg_attr(
12    feature = "borsh",
13    derive(borsh::BorshSerialize, borsh::BorshDeserialize, borsh::BorshSchema)
14)]
15pub struct Nanoseconds(SU64);
16
17#[cfg(feature = "schemars")]
18impl schemars::JsonSchema for Nanoseconds {
19    fn schema_name() -> String {
20        "Nanoseconds".to_string()
21    }
22
23    fn json_schema(_gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
24        let mut schema = schemars::schema::SchemaObject::default();
25        schema.instance_type = Some(schemars::schema::InstanceType::String.into());
26        schema.metadata().description =
27            Some("nanoseconds represented as a decimal string".to_string());
28        schema.into()
29    }
30}
31
32impl Nanoseconds {
33    pub const fn zero() -> Self {
34        Self(SU64::new(0))
35    }
36
37    /// Creates a `Nanoseconds` value from nanoseconds.
38    pub const fn from_ns(value: u64) -> Self {
39        Self(SU64::new(value))
40    }
41
42    /// Creates a `Nanoseconds` value from microseconds.
43    pub const fn from_micros(value: u64) -> Self {
44        Self(SU64::new(value.saturating_mul(1_000)))
45    }
46
47    /// Creates a `Nanoseconds` value from milliseconds.
48    pub const fn from_ms(value: u64) -> Self {
49        Self(SU64::new(value.saturating_mul(1_000_000)))
50    }
51
52    /// Creates a `Nanoseconds` value from seconds.
53    pub const fn from_secs(value: u64) -> Self {
54        Self(SU64::new(value.saturating_mul(1_000_000_000)))
55    }
56
57    /// Returns the value as seconds, truncated.
58    pub const fn as_secs(&self) -> u64 {
59        self.0 .0 / 1_000_000_000
60    }
61
62    /// Returns the value as milliseconds, truncated.
63    pub const fn as_ms(&self) -> u64 {
64        self.0 .0 / 1_000_000
65    }
66
67    /// Returns the value as microseconds, truncated.
68    pub const fn as_micros(&self) -> u64 {
69        self.0 .0 / 1_000
70    }
71
72    /// Returns the value as nanoseconds.
73    pub const fn as_ns(&self) -> u64 {
74        self.0 .0
75    }
76
77    #[must_use]
78    pub const fn saturating_add(self, rhs: Self) -> Self {
79        Self(SU64::new(self.0 .0.saturating_add(rhs.0 .0)))
80    }
81
82    #[must_use]
83    pub const fn saturating_sub(self, rhs: Self) -> Self {
84        Self(SU64::new(self.0 .0.saturating_sub(rhs.0 .0)))
85    }
86}
87
88impl fmt::Display for Nanoseconds {
89    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90        write!(f, "{}ns", self.as_ns())
91    }
92}
93
94#[cfg(feature = "near")]
95mod near {
96    impl super::Nanoseconds {
97        pub fn near_timestamp() -> Self {
98            Self::from_ns(near_sdk::env::block_timestamp())
99        }
100    }
101}
102
103#[cfg(feature = "redstone")]
104mod redstone {
105    impl From<redstone::TimestampMillis> for super::Nanoseconds {
106        fn from(value: redstone::TimestampMillis) -> Self {
107            Self::from_ms(value.as_millis())
108        }
109    }
110
111    impl From<super::Nanoseconds> for redstone::TimestampMillis {
112        fn from(value: super::Nanoseconds) -> Self {
113            Self::from_millis(value.as_ms())
114        }
115    }
116}