Skip to main content

apple_quant_algorithmic/timestamp/
utc_ns.rs

1use std::{
2	ops::{Add, Sub},
3	time::{SystemTime, UNIX_EPOCH},
4};
5
6use apple_quant_core::{TimeDeltaExt, UnwrapOptionExt, UnwrapResultExt};
7
8use chrono::{Duration, NaiveTime};
9
10use chrono_tz::Tz;
11use time::UtcDateTime;
12
13use super::{Timestamp, TimestampType};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16pub struct UtcNs(TimestampType);
17
18impl UtcNs {
19	#[inline]
20	pub(crate) unsafe fn from_utc_date_time(
21		utc_date_time: &UtcDateTime,
22	) -> Self {
23		unsafe {
24			Self::new_unchecked(utc_date_time.unix_timestamp_nanos())
25		}
26	}
27
28	#[inline]
29	pub(crate) fn new_unchecked(
30		utc_ns: TimestampType,
31	) -> Self {
32		Self(utc_ns)
33	}
34
35	#[cfg(feature = "timestamp-u64")]
36	#[inline]
37	pub(super) fn now() -> Self {
38		let now = SystemTime::now()
39			.duration_since(UNIX_EPOCH).unwrap_release_unsafe();
40
41		let now = (now.as_secs() * 1_000_000_000) + (now.subsec_nanos() as u64);
42		Self(now)
43	}
44
45	#[cfg(not(feature = "timestamp-u64"))]
46	#[inline]
47	pub(super) fn now() -> Self {
48		let now = unsafe {
49			SystemTime::now()
50				.duration_since(UNIX_EPOCH).unwrap_unchecked_release()
51		};
52
53		let now = now.as_nanos() as i128;
54		Self(now)
55	}
56
57	#[inline]
58	pub fn as_timestamp_type(
59		&self,
60	) -> &TimestampType {
61		&self.0
62	}
63
64	#[inline]
65	pub fn into_timestamp_type(
66		self,
67	) -> TimestampType {
68		self.0
69	}
70
71	#[inline]
72	pub fn previous_time(
73		&self,
74		tz: Tz,
75		naive_time: &NaiveTime,
76	) -> Self {
77		unimplemented!()
78	}
79
80	#[inline]
81	pub fn as_timestamp(
82		&self,
83	) -> Timestamp {
84		(*self).into()
85	}
86
87	#[inline]
88	pub fn into_timestamp(
89		self,
90	) -> Timestamp {
91		self.into()
92	}
93}
94
95impl From<Timestamp> for UtcNs {
96	fn from(
97		value: Timestamp,
98	) -> Self {
99		value.into_utc_ns()
100	}
101}
102
103impl Add<Duration> for UtcNs {
104	type Output = Self;
105
106	#[cfg(feature = "timestamp-u64")]
107	#[inline]
108	fn add(
109		mut self,
110		rhs: Duration,
111	) -> Self::Output {
112		let duration_ns = (rhs.num_seconds() * 1_000_000_000) as u64 +
113			(rhs.subsec_nanos() as u64);
114
115		self.0 += duration_ns;
116		self
117	}
118
119	#[cfg(not(feature = "timestamp-u64"))]
120	#[inline]
121	fn add(
122		mut self,
123		rhs: Duration,
124	) -> Self::Output {
125		let duration_ns = (rhs.num_seconds() * 1_000_000_000) as i128 +
126			(rhs.subsec_nanos() as i128);
127
128		self.0 += duration_ns;
129		self
130	}
131}
132
133impl Add<&Duration> for UtcNs {
134	type Output = Self;
135
136	#[inline]
137	fn add(
138		self,
139		rhs: &Duration,
140	) -> Self::Output {
141		self + *rhs
142	}
143}
144
145impl Sub<Duration> for UtcNs {
146	type Output = Self;
147
148	#[cfg(feature = "timestamp-u64")]
149	#[inline]
150	fn sub(
151		mut self,
152		rhs: Duration,
153	) -> Self::Output {
154		let duration_ns = (rhs.num_seconds() * 1_000_000_000) as u64 +
155			(rhs.subsec_nanos() as u64);
156
157		self.0 -= duration_ns;
158		self
159	}
160
161	#[cfg(not(feature = "timestamp-u64"))]
162	#[inline]
163	fn sub(
164		mut self,
165		rhs: Duration,
166	) -> Self::Output {
167		let duration_ns = (rhs.num_seconds() * 1_000_000_000) as i128 +
168			(rhs.subsec_nanos() as i128);
169
170		self.0 -= duration_ns;
171		self
172	}
173}
174
175impl Sub<&Duration> for UtcNs {
176	type Output = Self;
177
178	#[inline]
179	fn sub(
180		self,
181		rhs: &Duration,
182	) -> Self::Output {
183		self - *rhs
184	}
185}
186
187impl Sub for UtcNs {
188	type Output = Duration;
189
190	fn sub(
191		self,
192		rhs: Self,
193	) -> Self::Output {
194		let nanoseconds = self.0 - rhs.0;
195
196		unsafe {
197			Duration::nanoseconds_i128(nanoseconds).unwrap_unchecked_release()
198		}
199	}
200}
201
202impl Sub for &UtcNs {
203	type Output = Duration;
204
205	fn sub(
206		self,
207		rhs: Self,
208	) -> Self::Output {
209		*self - *rhs
210	}
211}