1use crate::duration::Duration;
2use crate::instant::Instant;
3
4pub enum Epoch {
6 JulianPeriod,
11
12 JulianCalendar,
20
21 GregorianCalendar,
25
26 Spreadsheet,
32
33 J1900_0,
37
38 Ntp,
43
44 Unix,
48
49 TimeStandard,
54
55 Y1977,
58
59 J1991_25,
63
64 Y2k,
68
69 J2000_0,
74
75 J2100_0,
79
80 J2200_0,
84}
85
86impl Epoch {
87 #[must_use]
89 pub const fn as_instant(&self) -> Instant {
90 match *self {
91 Self::JulianPeriod => Instant(Duration {
93 secs: -211_087_684_832,
94 attos: -184_000_000_000_000_000,
95 }),
96 Self::JulianCalendar => Instant(Duration {
97 secs: -62_356_694_432,
98 attos: -184_000_000_000_000_000,
99 }),
100 Self::GregorianCalendar => Instant(Duration {
101 secs: -62_356_521_632,
102 attos: -184_000_000_000_000_000,
103 }),
104 Self::Spreadsheet => Instant(Duration {
105 secs: -2_430_086_391,
106 attos: -0,
107 }),
108 Self::J1900_0 => Instant(Duration {
109 secs: -2_429_956_832,
110 attos: -184_000_000_000_000_000,
111 }),
112 Self::Ntp => Instant(Duration {
113 secs: -2_429_913_591,
114 attos: -0,
115 }),
116 Self::Unix => Instant(Duration {
117 secs: -220_924_791,
118 attos: -0,
119 }),
120 Self::TimeStandard => Instant(Duration { secs: 0, attos: 0 }),
121 Self::Y1977 => Instant(Duration { secs: 16, attos: 0 }),
122 Self::J1991_25 => Instant(Duration {
123 secs: 449_674_167,
124 attos: 816_000_000_000_000_000,
125 }),
126 Self::Y2k => Instant(Duration {
127 secs: 725_760_032,
128 attos: 0,
129 }),
130 Self::J2000_0 => Instant(Duration {
131 secs: 725_803_167,
132 attos: 816_000_000_000_000_000,
133 }),
134 Self::J2100_0 => Instant(Duration {
135 secs: 3_881_563_167,
136 attos: 816_000_000_000_000_000,
137 }),
138 Self::J2200_0 => Instant(Duration {
139 secs: 7_037_323_167,
140 attos: 816_000_000_000_000_000,
141 }),
142 }
143 }
144}
145
146#[cfg(test)]
147mod test {
148 use super::Epoch;
149 use crate::calendar::{Gregorian, Julian};
150 use crate::date_time::DateTime;
151 use crate::instant::Instant;
152 use crate::standard::{Tai, Tt, Utc};
153
154 macro_rules! epoch_check {
155 ($epoch:expr, $cal:ty, $std:ty, $def:expr) => {
156 let instant = $epoch.as_instant();
157 let dt: DateTime<$cal, $std> = From::from(instant);
158 assert_eq!(dt, $def);
159 let check: Instant = From::from(dt);
160 assert_eq!(instant, check);
161 };
162 }
163
164 #[test]
165 fn check_epochs_and_conversion() {
166 epoch_check!(
167 Epoch::JulianPeriod,
168 Julian,
169 Tt,
170 DateTime::<Julian, Tt>::new_bc(4713, 1, 1, 12, 0, 0, 0).unwrap()
171 );
172 epoch_check!(
173 Epoch::JulianCalendar,
174 Julian,
175 Tt,
176 DateTime::<Julian, Tt>::new(1, 1, 1, 0, 0, 0, 0).unwrap()
177 );
178 epoch_check!(
179 Epoch::GregorianCalendar,
180 Gregorian,
181 Tt,
182 DateTime::<Gregorian, Tt>::new(1, 1, 1, 0, 0, 0, 0).unwrap()
183 );
184 epoch_check!(
185 Epoch::Spreadsheet,
186 Gregorian,
187 Utc,
188 DateTime::<Gregorian, Utc>::new(1899, 12, 30, 0, 0, 0, 0).unwrap()
189 );
190 epoch_check!(
191 Epoch::J1900_0,
192 Gregorian,
193 Tt,
194 DateTime::<Gregorian, Tt>::new(1899, 12, 31, 12, 0, 0, 0).unwrap()
195 );
196 epoch_check!(
197 Epoch::Ntp,
198 Gregorian,
199 Utc,
200 DateTime::<Gregorian, Utc>::new(1900, 1, 1, 0, 0, 0, 0).unwrap()
201 );
202 epoch_check!(
203 Epoch::Unix,
204 Gregorian,
205 Utc,
206 DateTime::<Gregorian, Utc>::new(1970, 1, 1, 0, 0, 0, 0).unwrap()
207 );
208 epoch_check!(
209 Epoch::TimeStandard,
210 Gregorian,
211 Tai,
212 DateTime::<Gregorian, Tai>::new(1977, 1, 1, 0, 0, 0, 0).unwrap()
213 );
214 epoch_check!(
215 Epoch::Y1977,
216 Gregorian,
217 Utc,
218 DateTime::<Gregorian, Utc>::new(1977, 1, 1, 0, 0, 0, 0).unwrap()
219 );
220 epoch_check!(
221 Epoch::J1991_25,
222 Gregorian,
223 Tt,
224 DateTime::<Gregorian, Tt>::new(1991, 4, 2, 13, 30, 0, 0).unwrap()
225 );
226 epoch_check!(
227 Epoch::Y2k,
228 Gregorian,
229 Utc,
230 DateTime::<Gregorian, Utc>::new(2000, 1, 1, 0, 0, 0, 0).unwrap()
231 );
232 epoch_check!(
233 Epoch::J2000_0,
234 Gregorian,
235 Tt,
236 DateTime::<Gregorian, Tt>::new(2000, 1, 1, 12, 0, 0, 0).unwrap()
237 );
238 epoch_check!(
239 Epoch::J2100_0,
240 Gregorian,
241 Tt,
242 DateTime::<Gregorian, Tt>::new(2100, 1, 1, 12, 0, 0, 0).unwrap()
243 );
244 epoch_check!(
245 Epoch::J2200_0,
246 Gregorian,
247 Tt,
248 DateTime::<Gregorian, Tt>::new(2200, 1, 2, 12, 0, 0, 0).unwrap()
249 );
250 }
251
252 #[test]
253 fn test_instant_julian_day_formatted() {
254 assert_eq!(
255 Epoch::JulianPeriod.as_instant().as_julian_day_formatted(),
256 "JD 0"
257 );
258 assert_eq!(
259 Epoch::JulianCalendar.as_instant().as_julian_day_formatted(),
260 "JD 1721423.5"
261 );
262 assert_eq!(
263 Epoch::GregorianCalendar
264 .as_instant()
265 .as_julian_day_formatted(),
266 "JD 1721425.5"
267 );
268 assert_eq!(
269 Epoch::Spreadsheet.as_instant().as_julian_day_formatted(),
270 "JD 2415018.5004766666666667"
271 );
272 assert_eq!(
273 Epoch::J1900_0.as_instant().as_julian_day_formatted(),
274 "JD 2415020"
275 );
276 assert_eq!(
277 Epoch::Ntp.as_instant().as_julian_day_formatted(),
278 "JD 2415020.5004766666666667"
279 );
280 assert_eq!(
281 Epoch::Unix.as_instant().as_julian_day_formatted(),
282 "JD 2440587.5004766666666667"
283 );
284 assert_eq!(
285 Epoch::TimeStandard.as_instant().as_julian_day_formatted(),
286 "JD 2443144.5003725"
287 );
288 assert_eq!(
289 Epoch::J1991_25.as_instant().as_julian_day_formatted(),
290 "JD 2448349.0625"
291 );
292 assert_eq!(
293 Epoch::Y2k.as_instant().as_julian_day_formatted(),
294 "JD 2451544.5007428703703704"
295 );
296 assert_eq!(
297 Epoch::J2000_0.as_instant().as_julian_day_formatted(),
298 "JD 2451545"
299 );
300 assert_eq!(
301 Epoch::J2100_0.as_instant().as_julian_day_formatted(),
302 "JD 2488070"
303 );
304 assert_eq!(
305 Epoch::J2200_0.as_instant().as_julian_day_formatted(),
306 "JD 2524595"
307 );
308 }
309}