proto_types/timestamp/
timestamp_impls.rs1use crate::{Duration, Timestamp};
2
3#[cfg(not(feature = "chrono"))]
4impl crate::Timestamp {
5 pub fn format(&self) -> crate::String {
8 use crate::ToString;
9
10 self.to_string()
11 }
12}
13
14#[cfg(feature = "chrono")]
15mod chrono {
16 use chrono::Utc;
17
18 use crate::{String, Timestamp, ToString, timestamp::TimestampError};
19
20 impl Timestamp {
21 pub fn format(&self, string: &str) -> Result<String, TimestampError> {
23 let chrono_timestamp: chrono::DateTime<Utc> = (*self).try_into()?;
24
25 Ok(chrono_timestamp.format(string).to_string())
26 }
27
28 #[inline]
30 pub fn as_datetime_utc(&self) -> Result<chrono::DateTime<Utc>, TimestampError> {
31 (*self).try_into()
32 }
33 }
34}
35
36impl Timestamp {
37 #[must_use]
39 #[inline]
40 pub const fn new(seconds: i64, nanos: i32) -> Self {
41 Self { seconds, nanos }
42 }
43}
44
45#[cfg(all(not(feature = "std"), feature = "chrono-wasm"))]
46impl Timestamp {
47 #[must_use]
49 #[inline]
50 pub fn now() -> Self {
51 ::chrono::Utc::now().into()
52 }
53}
54
55#[cfg(feature = "std")]
56impl Timestamp {
57 #[must_use]
59 #[inline]
60 pub fn now() -> Self {
61 std::time::SystemTime::now().into()
62 }
63}
64
65#[cfg(any(feature = "std", feature = "chrono-wasm"))]
66impl Timestamp {
67 #[must_use]
69 #[inline]
70 pub fn is_within_range_from_now(&self, range: Duration) -> bool {
71 let now = Self::now();
72
73 (now + range) >= *self && (now - range) <= *self
74 }
75
76 #[must_use]
78 #[inline]
79 pub fn is_within_future_range(&self, range: Duration) -> bool {
80 let now = Self::now();
81 let max = now + range;
82
83 *self <= max && *self >= now
84 }
85
86 #[must_use]
88 #[inline]
89 pub fn is_within_past_range(&self, range: Duration) -> bool {
90 let now = Self::now();
91 let min = now - range;
92
93 *self >= min && *self <= now
94 }
95
96 #[must_use]
98 #[inline]
99 pub fn is_future(&self) -> bool {
100 *self > Self::now()
101 }
102
103 #[must_use]
105 #[inline]
106 pub fn is_past(&self) -> bool {
107 *self < Self::now()
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 fn offset_seconds(base: &Timestamp, s: i64) -> Timestamp {
116 Timestamp {
117 seconds: base.seconds + s,
118 nanos: base.nanos,
119 }
120 }
121
122 #[test]
123 fn test_is_future() {
124 let now = Timestamp::now();
125
126 let future_point = offset_seconds(&now, 5);
127 let past_point = offset_seconds(&now, -5);
128
129 assert!(future_point.is_future(), "T + 5s should be in the future");
130 assert!(
131 !past_point.is_future(),
132 "T - 5s should NOT be in the future"
133 );
134 }
135
136 #[test]
137 fn test_is_past() {
138 let now = Timestamp::now();
139
140 let future_point = offset_seconds(&now, 5);
141 let past_point = offset_seconds(&now, -5);
142
143 assert!(past_point.is_past(), "T - 5s should be in the past");
144 assert!(!future_point.is_past(), "T + 5s should NOT be in the past");
145 }
146
147 #[test]
148 fn test_is_within_future_range() {
149 let now = Timestamp::now();
150 let range = Duration::new(10, 0);
151
152 let inside = offset_seconds(&now, 5);
153 assert!(
154 inside.is_within_future_range(range),
155 "5s is within 10s range"
156 );
157
158 let outside_far = offset_seconds(&now, 15);
159 assert!(
160 !outside_far.is_within_future_range(range),
161 "15s is outside 10s range"
162 );
163
164 let outside_past = offset_seconds(&now, -1);
165 assert!(
166 !outside_past.is_within_future_range(range),
167 "Past value is not in future range"
168 );
169 }
170
171 #[test]
172 fn test_is_within_past_range() {
173 let now = Timestamp::now();
174 let range = Duration::new(10, 0);
175
176 let inside = offset_seconds(&now, -5);
177 assert!(
178 inside.is_within_past_range(range),
179 "-5s is within 10s past range"
180 );
181
182 let outside_old = offset_seconds(&now, -15);
183 assert!(
184 !outside_old.is_within_past_range(range),
185 "-15s is too old for 10s range"
186 );
187
188 let outside_future = offset_seconds(&now, 1);
189 assert!(
190 !outside_future.is_within_past_range(range),
191 "Future value is not in past range"
192 );
193 }
194}