1use std::time::Duration;
2use std::cmp::Ordering;
3use std::hash::{Hash, Hasher};
4
5const TICKS_BETWEEN_EPOCHS: u64 = 621355968000000000;
7
8#[derive(Clone, Copy, Debug)]
15#[repr(transparent)]
16pub struct Date(u64);
17
18impl From<Date> for Duration {
19 fn from(d: Date) -> Self {
20 let micros = d.0 / 10;
22 let remaining_ticks = d.0 - (micros * 10);
23 let nanos = remaining_ticks * 100;
24 Duration::from_micros(micros) + Duration::from_nanos(nanos)
25 }
26}
27
28impl PartialEq for Date {
29 fn eq(&self, other: &Self) -> bool {
30 self.to_ticks() == other.to_ticks()
31 }
32}
33impl Eq for Date {}
34impl PartialOrd for Date {
35 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
36 Some(self.to_ticks().cmp(&other.to_ticks()))
37 }
38}
39impl Ord for Date {
40 fn cmp(&self, other: &Self) -> Ordering {
41 self.to_ticks().cmp(&other.to_ticks())
42 }
43}
44impl Hash for Date {
45 fn hash<H: Hasher>(&self, state: &mut H) {
46 self.to_ticks().hash(state)
47 }
48}
49
50impl Date {
51 #[inline]
52 pub const fn from_ticks(t: u64) -> Self {
53 Self(t)
54 }
55
56 #[inline]
57 pub const fn from_ticks_since_unix_epoch(t: u64) -> Self {
58 Self(t + TICKS_BETWEEN_EPOCHS)
59 }
60
61 #[inline]
62 pub const fn to_ticks(self) -> u64 {
63 self.0 & 0x3fffffffffffffff
65 }
66
67 #[inline]
68 pub const fn to_ticks_since_unix_epoch(self) -> u64 {
69 self.to_ticks() - TICKS_BETWEEN_EPOCHS
70 }
71
72 #[inline]
73 pub const fn from_micros(t: u64) -> Self {
74 Self(t * 10)
75 }
76
77 #[inline]
78 pub const fn from_micros_since_unix_epoch(t: u64) -> Self {
79 Self::from_ticks_since_unix_epoch(t * 10)
80 }
81
82 #[inline]
83 pub const fn to_micros(self) -> u64 {
84 self.to_ticks() / 10
85 }
86
87 #[inline]
88 pub const fn to_micros_since_unix_epoch(self) -> u64 {
89 self.to_ticks_since_unix_epoch() / 10
90 }
91
92 #[inline]
93 pub const fn from_millis(t: u64) -> Self {
94 Date::from_micros(t * 1000)
95 }
96
97 #[inline]
98 pub const fn from_millis_since_unix_epoch(t: u64) -> Self {
99 Date::from_micros_since_unix_epoch(t * 1000)
100 }
101
102 #[inline]
103 pub const fn to_millis(self) -> u64 {
104 self.to_micros() / 1000
105 }
106
107 #[inline]
108 pub const fn to_millis_since_unix_epoch(self) -> u64 {
109 self.to_micros_since_unix_epoch() / 1000
110 }
111
112 #[inline]
113 pub const fn from_secs(t: u64) -> Self {
114 Date::from_millis(t * 1000)
115 }
116
117 #[inline]
118 pub const fn from_secs_since_unix_epoch(t: u64) -> Self {
119 Date::from_millis_since_unix_epoch(t * 1000)
120 }
121
122 #[inline]
123 pub const fn to_secs(self) -> u64 {
124 self.to_millis() / 1000
125 }
126
127 #[inline]
128 pub const fn to_secs_since_unix_epoch(self) -> u64 {
129 self.to_millis_since_unix_epoch() / 1000
130 }
131
132 #[inline]
133 pub fn to_micros_f(self) -> f64 {
134 self.0 as f64 / 10.
135 }
136
137 #[inline]
138 pub fn to_micros_since_unix_epoch_f(self) -> f64 {
139 self.to_ticks_since_unix_epoch() as f64 / 10.
140 }
141
142 #[inline]
143 pub fn to_millis_f(self) -> f64 {
144 self.to_micros_f() / 1000.
145 }
146
147 #[inline]
148 pub fn to_millis_since_unix_epoch_f(self) -> f64 {
149 self.to_micros_since_unix_epoch_f() / 1000.
150 }
151
152 #[inline]
153 pub fn to_secs_f(self) -> f64 {
154 self.to_millis_f() / 1000.
155 }
156
157 #[inline]
158 pub fn to_secs_since_unix_epoch_f(self) -> f64 {
159 self.to_millis_since_unix_epoch_f() / 1000.
160 }
161}