1use crate::{
2 ATTOS_PER_FS, ATTOS_PER_MS, ATTOS_PER_NS, ATTOS_PER_PS, ATTOS_PER_SEC, ATTOS_PER_US,
3 ClockDrift, ClockModel, Dt, FS_PER_SEC, MS_PER_SEC, NS_PER_SEC, PS_PER_SEC, Scale,
4 TT_TAI_OFFSET_SPAN, UNIX_EPOCH_TO_J2000_NOON_UTC, US_PER_SEC,
5};
6
7impl Dt {
8 pub const ZERO: Self = Self::new(0, 0);
10
11 pub const J2000_TAI: Self = Self::ZERO.sub(TT_TAI_OFFSET_SPAN);
14
15 pub const J1900_TAI: Self = Self::new(-3_155_760_000, 0);
17
18 pub const GPS_ZERO: Self = Self::new(19, 0);
20 pub const GST_ZERO: Self = Self::new(19, 0);
21 pub const QZSS_ZERO: Self = Self::new(19, 0);
22 pub const BDT_ZERO: Self = Self::new(33, 0);
23
24 pub const UNIX_EPOCH: Self = Self::new(-UNIX_EPOCH_TO_J2000_NOON_UTC, 0);
26
27 pub const GPS_EPOCH: Self = Self::new(-630_763_200 + 19, 0);
29 pub const GALEX_EPOCH: Self = Self::GPS_EPOCH;
30 pub const GALILEO_EPOCH: Self = Self::new(-11_448_000 + 19, 0);
31 pub const BDT_EPOCH: Self = Self::new(189_345_600 + 33, 0);
32
33 #[inline]
36 pub const fn new(sec: i64, attos: u64) -> Self {
37 let mut tp = Self { sec, attos };
38 tp.carry_over();
39 tp
40 }
41
42 #[inline]
48 pub const fn new_custom_clock(self, drift: ClockDrift) -> ClockModel {
49 ClockModel::new(Scale::Custom, self, drift)
50 }
51
52 #[inline]
53 pub const fn from_attos(attos: i128, scale: Scale) -> Self {
54 let sec = (attos / ATTOS_PER_SEC as i128) as i64;
55 let subsec = (attos % ATTOS_PER_SEC as i128) as u64;
56 Self::from(sec, subsec, scale)
57 }
58
59 #[inline]
60 pub const fn from_sec(sec: i64, scale: Scale) -> Self {
61 Self::from(sec, 0, scale)
62 }
63
64 #[inline]
65 pub const fn from_ms(ms: i128, scale: Scale) -> Self {
66 let sec = ms.div_euclid(MS_PER_SEC) as i64;
67 let remaining_ms = ms.rem_euclid(MS_PER_SEC);
68 let subsec = (remaining_ms as u64) * ATTOS_PER_MS;
69 Self::from(sec, subsec, scale)
70 }
71
72 #[inline]
73 pub const fn from_us(us: i128, scale: Scale) -> Self {
74 let sec = us.div_euclid(US_PER_SEC) as i64;
75 let remaining_us = us.rem_euclid(US_PER_SEC);
76 let subsec = (remaining_us as u64) * ATTOS_PER_US;
77 Self::from(sec, subsec, scale)
78 }
79
80 #[inline]
81 pub const fn from_ns(ns: i128, scale: Scale) -> Self {
82 let sec = ns.div_euclid(NS_PER_SEC) as i64;
83 let remaining_ns = ns.rem_euclid(NS_PER_SEC);
84 let subsec = (remaining_ns as u64) * ATTOS_PER_NS;
85 Self::from(sec, subsec, scale)
86 }
87
88 #[inline]
89 pub const fn from_ps(ps: i128, scale: Scale) -> Self {
90 let sec = ps.div_euclid(PS_PER_SEC) as i64;
91 let remaining_ps = ps.rem_euclid(PS_PER_SEC);
92 let subsec = (remaining_ps as u64) * ATTOS_PER_PS;
93 Self::from(sec, subsec, scale)
94 }
95
96 #[inline]
97 pub const fn from_fs(fs: i128, scale: Scale) -> Self {
98 let sec = fs.div_euclid(FS_PER_SEC) as i64;
99 let remaining_fs = fs.rem_euclid(FS_PER_SEC);
100 let subsec = (remaining_fs as u64) * ATTOS_PER_FS;
101 Self::from(sec, subsec, scale)
102 }
103
104 #[inline]
105 pub const fn from_min(m: i64, scale: Scale) -> Self {
106 Self::from(m * 60, 0, scale)
107 }
108
109 #[inline]
110 pub const fn from_hr(h: i64, scale: Scale) -> Self {
111 Self::from(h * 3600, 0, scale)
112 }
113
114 pub const fn from_hms(
117 hr: i64,
118 min: i64,
119 sec: i64,
120 ms: i128,
121 us: i128,
122 ns: i128,
123 scale: Scale,
124 ) -> Self {
125 let total_sec = hr * 3600i64 + min * 60i64 + sec;
126
127 let sub_ns = ms * 1_000_000i128 + us * 1_000i128 + ns;
128
129 if sub_ns == 0 {
130 return Self::from(total_sec, 0, scale);
131 }
132
133 let abs_ns = sub_ns.unsigned_abs();
134 let extra_sec = (abs_ns / 1_000_000_000u128) as i64;
135 let rem_ns = abs_ns % 1_000_000_000u128;
136 let frac = (rem_ns as u64) * ATTOS_PER_NS;
137
138 let (final_sec, final_frac) = if sub_ns >= 0 {
139 (total_sec + extra_sec, frac)
140 } else if frac == 0 {
141 (total_sec - extra_sec, 0)
142 } else {
143 (total_sec - extra_sec - 1, ATTOS_PER_SEC - frac)
144 };
145
146 Self::from(final_sec, final_frac, scale)
147 }
148
149 #[cfg(all(feature = "std", not(all(target_arch = "wasm32", feature = "js"))))]
154 #[inline]
155 pub fn now() -> Self {
156 use crate::TSpan;
157
158 let now = std::time::SystemTime::now();
159 let (secs, nanos) = match now.duration_since(std::time::UNIX_EPOCH) {
160 Ok(dur) => (dur.as_secs() as i64, dur.subsec_nanos() as i64),
161 Err(_) => {
162 let dur = std::time::SystemTime::UNIX_EPOCH
164 .duration_since(now)
165 .unwrap();
166 (-(dur.as_secs() as i64), -(dur.subsec_nanos() as i64))
167 }
168 };
169 crate::Dt::from_epoch(TSpan::new(secs, 0), Dt::UNIX_EPOCH, Scale::UTC)
170 .add(crate::TSpan::from_ns(nanos as i128))
171 }
172
173 #[cfg(all(target_arch = "wasm32", feature = "js"))]
176 #[inline]
177 pub fn now() -> Self {
178 let millis = js_sys::Date::now() as i64;
179 let secs = millis / 1000;
180 let nanos = (millis % 1000) * 1_000_000;
181 crate::Dt::from_epoch(TSpan::new(secs, 0), Dt::UNIX_EPOCH, Scale::UTC)
182 .add(crate::TSpan::from_ns(nanos))
183 }
184}