1use crate::G14_safe::eraDatini_safe;
7use crate::G19_safe::eraJd2cal_safe;
8use crate::G8_safe::eraCal2jd_safe;
9use crate::H1_safe::{eraLEAPSECOND, ERFA_DAYSEC, ERFA_DINT, ERFA_DNINT};
10
11pub type ErfaResult<T> = Result<T, ()>;
12
13pub fn eraD2tf_safe(ndp: i32, days: f64) -> ErfaResult<(char, [i32; 4])> {
16 let sign = if days >= 0.0 { '+' } else { '-' };
17
18 let mut a = ERFA_DAYSEC * days.abs();
19
20 if ndp < 0 {
21 let mut nrs = 1;
22 for n in 1..=-ndp {
23 nrs *= if n == 2 || n == 4 { 6 } else { 10 };
24 }
25 let rs = nrs as f64;
26 let w = a / rs;
27 a = rs * ERFA_DNINT(w);
28 }
29
30 let mut nrs = 1;
31 for _ in 1..=ndp.max(0) {
32 nrs *= 10;
33 }
34 let rs = nrs as f64;
35 let rm = rs * 60.0;
36 let rh = rm * 60.0;
37
38 a = ERFA_DNINT(rs * a);
39
40 let ah = ERFA_DINT(a / rh);
41 a -= ah * rh;
42 let am = ERFA_DINT(a / rm);
43 a -= am * rm;
44 let as_ = ERFA_DINT(a / rs);
45 let af = a - as_ * rs;
46
47 let ihmsf = [ah as i32, am as i32, as_ as i32, af as i32];
48 Ok((sign, ihmsf))
49}
50
51pub fn eraD2dtf_safe(
54 scale: &str,
55 ndp: i32,
56 d1: f64,
57 d2: f64,
58) -> ErfaResult<((i32, i32, i32), [i32; 4], i32)> {
59 let ((iy0, im0, id0), mut fd, j_cal) = eraJd2cal_safe(d1, d2)?;
60 if j_cal != 0 {
61 return Err(());
62 }
63 let (mut iy1, mut im1, mut id1) = (iy0, im0, id0);
64
65 let mut js = 0;
66 let mut leap = false;
67
68 if scale == "UTC" {
69 let (dat0, j0) = eraDat_safe(iy1, im1, id1, 0.0)?;
70 if j0 < 0 {
71 return Err(());
72 }
73 if j0 > 0 {
74 js = j0;
75 }
76
77 let (dat12, j12) = eraDat_safe(iy1, im1, id1, 0.5)?;
78 if j12 < 0 {
79 return Err(());
80 }
81 if j12 > 0 && js == 0 {
82 js = j12;
83 }
84
85 let ((iy2, im2, id2), _w, j_next) = eraJd2cal_safe(d1 + 1.5, d2 - fd)?;
86 if j_next != 0 {
87 return Err(());
88 }
89 let (dat24, j24) = eraDat_safe(iy2, im2, id2, 0.0)?;
90 if j24 < 0 {
91 return Err(());
92 }
93 if j24 > 0 && js == 0 {
94 js = j24;
95 }
96
97 let dleap = dat24 - (2.0 * dat12 - dat0);
98 leap = dleap.abs() > 0.5;
99 if leap {
100 fd += fd * dleap / ERFA_DAYSEC;
101 }
102 }
103
104 let (_s, mut ihmsf1) = eraD2tf_safe(ndp, fd)?;
105
106 if ihmsf1[0] > 23 {
107 let ((iy2, im2, id2), _w, j_next) = eraJd2cal_safe(d1 + 1.5, d2 - fd)?;
108 if j_next != 0 {
109 return Err(());
110 }
111
112 if !leap {
113 iy1 = iy2;
114 im1 = im2;
115 id1 = id2;
116 ihmsf1 = [0, 0, 0, 0];
117 } else {
118 if ihmsf1[2] > 0 {
119 iy1 = iy2;
120 im1 = im2;
121 id1 = id2;
122 ihmsf1 = [0, 0, 0, 0];
123 } else {
124 ihmsf1[0] = 23;
125 ihmsf1[1] = 59;
126 ihmsf1[2] = 60;
127 }
128 if ndp < 0 && ihmsf1[2] == 60 {
129 iy1 = iy2;
130 im1 = im2;
131 id1 = id2;
132 ihmsf1 = [0, 0, 0, 0];
133 }
134 }
135 }
136
137 Ok(((iy1, im1, id1), ihmsf1, js))
138}
139
140pub fn eraDat_safe(iy: i32, im: i32, id: i32, fd: f64) -> ErfaResult<(f64, i32)> {
143 const IYV: i32 = 2023;
144
145 const DRIFT: &[[f64; 2]] = &[
146 [37300.0, 0.0012960],
147 [37300.0, 0.0012960],
148 [37300.0, 0.0012960],
149 [37665.0, 0.0011232],
150 [37665.0, 0.0011232],
151 [38761.0, 0.0012960],
152 [38761.0, 0.0012960],
153 [38761.0, 0.0012960],
154 [38761.0, 0.0012960],
155 [38761.0, 0.0012960],
156 [38761.0, 0.0012960],
157 [38761.0, 0.0012960],
158 [39126.0, 0.0025920],
159 [39126.0, 0.0025920],
160 ];
161 const NERA1: usize = DRIFT.len();
162
163 const CHANGES_BUILTIN: &[eraLEAPSECOND] = &[
164 eraLEAPSECOND {
165 iyear: 1960,
166 month: 1,
167 delat: 1.4178180,
168 },
169 eraLEAPSECOND {
170 iyear: 1961,
171 month: 1,
172 delat: 1.4228180,
173 },
174 eraLEAPSECOND {
175 iyear: 1961,
176 month: 8,
177 delat: 1.3728180,
178 },
179 eraLEAPSECOND {
180 iyear: 1962,
181 month: 1,
182 delat: 1.8458580,
183 },
184 eraLEAPSECOND {
185 iyear: 1963,
186 month: 11,
187 delat: 1.9458580,
188 },
189 eraLEAPSECOND {
190 iyear: 1964,
191 month: 1,
192 delat: 3.2401300,
193 },
194 eraLEAPSECOND {
195 iyear: 1964,
196 month: 4,
197 delat: 3.3401300,
198 },
199 eraLEAPSECOND {
200 iyear: 1964,
201 month: 9,
202 delat: 3.4401300,
203 },
204 eraLEAPSECOND {
205 iyear: 1965,
206 month: 1,
207 delat: 3.5401300,
208 },
209 eraLEAPSECOND {
210 iyear: 1965,
211 month: 3,
212 delat: 3.6401300,
213 },
214 eraLEAPSECOND {
215 iyear: 1965,
216 month: 7,
217 delat: 3.7401300,
218 },
219 eraLEAPSECOND {
220 iyear: 1965,
221 month: 9,
222 delat: 3.8401300,
223 },
224 eraLEAPSECOND {
225 iyear: 1966,
226 month: 1,
227 delat: 4.3131700,
228 },
229 eraLEAPSECOND {
230 iyear: 1968,
231 month: 2,
232 delat: 4.2131700,
233 },
234 eraLEAPSECOND {
235 iyear: 1972,
236 month: 1,
237 delat: 10.0,
238 },
239 eraLEAPSECOND {
240 iyear: 1972,
241 month: 7,
242 delat: 11.0,
243 },
244 eraLEAPSECOND {
245 iyear: 1973,
246 month: 1,
247 delat: 12.0,
248 },
249 eraLEAPSECOND {
250 iyear: 1974,
251 month: 1,
252 delat: 13.0,
253 },
254 eraLEAPSECOND {
255 iyear: 1975,
256 month: 1,
257 delat: 14.0,
258 },
259 eraLEAPSECOND {
260 iyear: 1976,
261 month: 1,
262 delat: 15.0,
263 },
264 eraLEAPSECOND {
265 iyear: 1977,
266 month: 1,
267 delat: 16.0,
268 },
269 eraLEAPSECOND {
270 iyear: 1978,
271 month: 1,
272 delat: 17.0,
273 },
274 eraLEAPSECOND {
275 iyear: 1979,
276 month: 1,
277 delat: 18.0,
278 },
279 eraLEAPSECOND {
280 iyear: 1980,
281 month: 1,
282 delat: 19.0,
283 },
284 eraLEAPSECOND {
285 iyear: 1981,
286 month: 7,
287 delat: 20.0,
288 },
289 eraLEAPSECOND {
290 iyear: 1982,
291 month: 7,
292 delat: 21.0,
293 },
294 eraLEAPSECOND {
295 iyear: 1983,
296 month: 7,
297 delat: 22.0,
298 },
299 eraLEAPSECOND {
300 iyear: 1985,
301 month: 7,
302 delat: 23.0,
303 },
304 eraLEAPSECOND {
305 iyear: 1988,
306 month: 1,
307 delat: 24.0,
308 },
309 eraLEAPSECOND {
310 iyear: 1990,
311 month: 1,
312 delat: 25.0,
313 },
314 eraLEAPSECOND {
315 iyear: 1991,
316 month: 1,
317 delat: 26.0,
318 },
319 eraLEAPSECOND {
320 iyear: 1992,
321 month: 7,
322 delat: 27.0,
323 },
324 eraLEAPSECOND {
325 iyear: 1993,
326 month: 7,
327 delat: 28.0,
328 },
329 eraLEAPSECOND {
330 iyear: 1994,
331 month: 7,
332 delat: 29.0,
333 },
334 eraLEAPSECOND {
335 iyear: 1996,
336 month: 1,
337 delat: 30.0,
338 },
339 eraLEAPSECOND {
340 iyear: 1997,
341 month: 7,
342 delat: 31.0,
343 },
344 eraLEAPSECOND {
345 iyear: 1999,
346 month: 1,
347 delat: 32.0,
348 },
349 eraLEAPSECOND {
350 iyear: 2006,
351 month: 1,
352 delat: 33.0,
353 },
354 eraLEAPSECOND {
355 iyear: 2009,
356 month: 1,
357 delat: 34.0,
358 },
359 eraLEAPSECOND {
360 iyear: 2012,
361 month: 7,
362 delat: 35.0,
363 },
364 eraLEAPSECOND {
365 iyear: 2015,
366 month: 7,
367 delat: 36.0,
368 },
369 eraLEAPSECOND {
370 iyear: 2017,
371 month: 1,
372 delat: 37.0,
373 },
374 ];
375
376 if fd < 0.0 || fd > 1.0 {
377 return Err(());
378 }
379
380 let ((_, djm), jcal) = eraCal2jd_safe(iy, im, id)?;
381 if jcal < 0 {
382 return Err(());
383 }
384
385 let table = eraDatini_safe(CHANGES_BUILTIN)?;
386
387 if iy < table[0].iyear {
388 return Ok((0.0, 1));
389 }
390
391 let mut j = 0;
392 if iy > IYV + 5 {
393 j = 1;
394 }
395
396 let m = 12 * iy + im;
397
398 let mut idx = None;
399 for i in (0..table.len()).rev() {
400 if m >= (12 * table[i].iyear + table[i].month) {
401 idx = Some(i);
402 break;
403 }
404 }
405 let i = match idx {
406 Some(i) => i,
407 None => return Err(()),
408 };
409
410 let mut da = table[i].delat;
411
412 if i < NERA1 {
413 da += (djm + fd - DRIFT[i][0]) * DRIFT[i][1];
414 }
415
416 Ok((da, j))
417}