Skip to main content

midnight_base_crypto/
time.rs

1// This file is part of midnight-ledger.
2// Copyright (C) 2025 Midnight Foundation
3// SPDX-License-Identifier: Apache-2.0
4// Licensed under the Apache License, Version 2.0 (the "License");
5// You may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7// http://www.apache.org/licenses/LICENSE-2.0
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14//! Representation of time and duration
15use crate::fab::Aligned;
16use crate::fab::Alignment;
17use crate::fab::Value;
18use crate::fab::ValueAtom;
19use serialize::{Deserializable, Serializable, Tagged, tag_enforcement_test};
20use std::ops::Add;
21use std::ops::AddAssign;
22use std::ops::Sub;
23
24#[derive(
25    Clone,
26    Copy,
27    Debug,
28    PartialEq,
29    Eq,
30    PartialOrd,
31    Ord,
32    Hash,
33    Default,
34    Serializable,
35    serde::Serialize,
36    serde::Deserialize,
37)]
38#[tag = "timestamp"]
39/// Time since Unix Epoch
40pub struct Timestamp(u64);
41tag_enforcement_test!(Timestamp);
42
43impl Timestamp {
44    /// The maximum representable time.
45    pub const MAX: Timestamp = Timestamp(u64::MAX);
46
47    /// Creates a timestamp `s` seconds after the start of Unix Epoch
48    pub const fn from_secs(s: u64) -> Self {
49        Timestamp(s)
50    }
51
52    /// Gets the number of seconds since the start of Unix Epoch from the `Timestamp`
53    pub fn to_secs(self) -> u64 {
54        self.0
55    }
56}
57
58impl rand::distributions::Distribution<Timestamp> for rand::distributions::Standard {
59    fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Timestamp {
60        Timestamp(rng.r#gen())
61    }
62}
63
64impl Aligned for Timestamp {
65    fn alignment() -> Alignment {
66        u64::alignment()
67    }
68}
69
70impl From<Timestamp> for ValueAtom {
71    fn from(timestamp: Timestamp) -> ValueAtom {
72        ValueAtom::from(timestamp.0).normalize()
73    }
74}
75
76impl From<Timestamp> for Value {
77    fn from(val: Timestamp) -> Value {
78        Value(vec![val.into()])
79    }
80}
81
82impl Sub<Self> for Timestamp {
83    type Output = Duration;
84
85    fn sub(self, rhs: Self) -> Self::Output {
86        Duration(self.0 as i128 - rhs.0 as i128)
87    }
88}
89
90impl AddAssign<Duration> for Timestamp {
91    fn add_assign(&mut self, rhs: Duration) {
92        *self = *self + rhs;
93    }
94}
95
96impl Add<Duration> for Timestamp {
97    type Output = Timestamp;
98
99    fn add(self, rhs: Duration) -> Self::Output {
100        if rhs.0 >= 0 {
101            let result = self.0.saturating_add(rhs.0 as u64);
102            Timestamp(result)
103        } else {
104            let abs_duration: u64 = rhs
105                .0
106                .checked_abs()
107                .and_then(|val| u64::try_from(val).ok())
108                .unwrap_or(u64::MAX);
109            Timestamp(self.0.saturating_sub(abs_duration))
110        }
111    }
112}
113
114impl Sub<Duration> for Timestamp {
115    type Output = Timestamp;
116
117    fn sub(self, rhs: Duration) -> Self::Output {
118        if rhs.0 >= 0 {
119            let result = self.0.saturating_sub(rhs.0 as u64);
120            Timestamp(result)
121        } else {
122            let abs_duration: u64 = rhs
123                .0
124                .checked_abs()
125                .and_then(|val| u64::try_from(val).ok())
126                .unwrap_or(u64::MAX);
127            Timestamp(self.0.saturating_add(abs_duration))
128        }
129    }
130}
131
132#[derive(
133    Clone,
134    Copy,
135    Debug,
136    PartialEq,
137    Eq,
138    PartialOrd,
139    Ord,
140    Serializable,
141    Hash,
142    Default,
143    serde::Serialize,
144    serde::Deserialize,
145)]
146#[serde(transparent)]
147#[tag = "duration"]
148/// Some duration of time in seconds
149pub struct Duration(i128);
150tag_enforcement_test!(Duration);
151
152impl Duration {
153    /// Gets the `Duration` from a number of seconds
154    pub const fn from_secs(s: i128) -> Self {
155        Duration(s)
156    }
157
158    /// Gets the `Duration` from a number of hours
159    pub const fn from_hours(h: i128) -> Self {
160        Duration::from_secs(h * 60 * 60)
161    }
162
163    /// Returns the duration's raw value in seconds.
164    pub fn as_seconds(self) -> i128 {
165        self.0
166    }
167}
168
169impl Add<Duration> for Duration {
170    type Output = Self;
171
172    fn add(self, rhs: Self) -> Self::Output {
173        Duration(self.0.saturating_add(rhs.0))
174    }
175}
176
177impl Sub<Self> for Duration {
178    type Output = Self;
179
180    fn sub(self, rhs: Self) -> Self::Output {
181        Duration(self.0.saturating_sub(rhs.0))
182    }
183}