/rust/registry/src/index.crates.io-1949cf8c6b5b557f/sofars-0.6.2/src/ts/utctai.rs
Line | Count | Source |
1 | | use crate::cal::{cal2jd, jd2cal}; |
2 | | use crate::consts::DAYSEC; |
3 | | /// - - - - - - - - - - |
4 | | /// i a u U t c t a i |
5 | | /// - - - - - - - - - - |
6 | | /// |
7 | | /// Time scale transformation: Coordinated Universal Time, UTC, to |
8 | | /// International Atomic Time, TAI. |
9 | | /// |
10 | | /// This function is part of the International Astronomical Union's |
11 | | /// SOFA (Standards of Fundamental Astronomy) software collection. |
12 | | /// |
13 | | /// Status: canonical. |
14 | | /// |
15 | | /// Given: |
16 | | /// utc1,utc2 double UTC as a 2-part quasi Julian Date (Notes 1-4) |
17 | | /// |
18 | | /// Returned: |
19 | | /// tai1,tai2 double TAI as a 2-part Julian Date (Note 5) |
20 | | /// |
21 | | /// Returned (function value): |
22 | | /// int status: +1 = dubious year (Note 3) |
23 | | /// 0 = OK |
24 | | /// -1 = unacceptable date |
25 | | /// |
26 | | /// Notes: |
27 | | /// |
28 | | /// 1) utc1+utc2 is quasi Julian Date (see Note 2), apportioned in any |
29 | | /// convenient way between the two arguments, for example where utc1 |
30 | | /// is the Julian Day Number and utc2 is the fraction of a day. |
31 | | /// |
32 | | /// 2) JD cannot unambiguously represent UTC during a leap second unless |
33 | | /// special measures are taken. The convention in the present |
34 | | /// function is that the JD day represents UTC days whether the |
35 | | /// length is 86399, 86400 or 86401 SI seconds. In the 1960-1972 era |
36 | | /// there were smaller jumps (in either direction) each time the |
37 | | /// linear UTC(TAI) expression was changed, and these "mini-leaps" |
38 | | /// are also included in the SOFA convention. |
39 | | /// |
40 | | /// 3) The warning status "dubious year" flags UTCs that predate the |
41 | | /// introduction of the time scale or that are too far in the future |
42 | | /// to be trusted. See iauDat for further details. |
43 | | /// |
44 | | /// 4) The function iauDtf2d converts from calendar date and time of day |
45 | | /// into 2-part Julian Date, and in the case of UTC implements the |
46 | | /// leap-second-ambiguity convention described above. |
47 | | /// |
48 | | /// 5) The returned TAI1,TAI2 are such that their sum is the TAI Julian |
49 | | /// Date. |
50 | | /// |
51 | | /// Called: |
52 | | /// iauJd2cal JD to Gregorian calendar |
53 | | /// iauDat delta(AT) = TAI-UTC |
54 | | /// iauCal2jd Gregorian calendar to JD |
55 | | /// |
56 | | /// References: |
57 | | /// |
58 | | /// McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003), |
59 | | /// IERS Technical Note No. 32, BKG (2004) |
60 | | /// |
61 | | /// Explanatory Supplement to the Astronomical Almanac, |
62 | | /// P. Kenneth Seidelmann (ed), University Science Books (1992) |
63 | | /// |
64 | | /// This revision: 2021 May 11 |
65 | | /// |
66 | | /// SOFA release 2023-10-11 |
67 | | /// |
68 | | /// Copyright (C) 2023 IAU SOFA Board. See notes at end. |
69 | 0 | pub fn utctai(utc1: f64, utc2: f64) -> Result<(f64, f64), i32> { |
70 | | let (iy, im, id, iyt, imt, idt): (i32, i32, i32, i32, i32, i32); |
71 | | let (u1, u2, mut fd, dat0, dat12, dat24, dlod, dleap, z1, z2): ( |
72 | | f64, |
73 | | f64, |
74 | | f64, |
75 | | f64, |
76 | | f64, |
77 | | f64, |
78 | | f64, |
79 | | f64, |
80 | | f64, |
81 | | f64, |
82 | | ); |
83 | | |
84 | | // Put the two parts of the UTC into big-first order. |
85 | 0 | let big1: bool = utc1.abs() >= utc2.abs(); |
86 | 0 | if big1 { |
87 | 0 | u1 = utc1; |
88 | 0 | u2 = utc2; |
89 | 0 | } else { |
90 | 0 | u1 = utc2; |
91 | 0 | u2 = utc1; |
92 | 0 | } |
93 | | |
94 | | // Get TAI-UTC at 0h today. |
95 | 0 | match jd2cal(u1, u2) { |
96 | 0 | Ok((y, m, d, f)) => { |
97 | 0 | iy = y; |
98 | 0 | im = m; |
99 | 0 | id = d; |
100 | 0 | fd = f; |
101 | 0 | } |
102 | 0 | Err(j) => return Err(j), |
103 | | } |
104 | | { |
105 | 0 | let d = super::dat(iy, im, id, 0.0)?; |
106 | 0 | dat0 = d |
107 | | } |
108 | | |
109 | | // Get TAI-UTC at 12h today (to detect drift). |
110 | | { |
111 | 0 | let d = super::dat(iy, im, id, 0.5)?; |
112 | 0 | dat12 = d |
113 | | } |
114 | | |
115 | | // Get TAI-UTC at 0h tomorrow (to detect jumps). |
116 | 0 | let j = jd2cal(u1 + 1.5, u2 - fd); |
117 | 0 | match j { |
118 | 0 | Err(j) => return Err(j), |
119 | 0 | Ok((y, m, d, _)) => { |
120 | 0 | iyt = y; |
121 | 0 | imt = m; |
122 | 0 | idt = d; |
123 | 0 | } |
124 | | } |
125 | | |
126 | | { |
127 | 0 | let d = super::dat(iyt, imt, idt, 0.0)?; |
128 | 0 | dat24 = d |
129 | | } |
130 | | |
131 | | // Separate TAI-UTC change into per-day (DLOD) and any jump (DLEAP). |
132 | 0 | dlod = 2.0 * (dat12 - dat0); |
133 | 0 | dleap = dat24 - (dat0 + dlod); |
134 | | |
135 | | // Remove any scaling applied to spread leap into preceding day. |
136 | 0 | fd *= (DAYSEC + dleap) / DAYSEC; |
137 | | |
138 | | // Scale from (pre-1972) UTC seconds to SI seconds. |
139 | 0 | fd *= (DAYSEC + dlod) / DAYSEC; |
140 | | |
141 | | // Today's calendar date to 2-part JD. |
142 | 0 | match cal2jd(iy, im, id) { |
143 | 0 | Err(j) => return Err(j), |
144 | 0 | Ok((d1, d2)) => { |
145 | 0 | z1 = d1; |
146 | 0 | z2 = d2; |
147 | 0 | } |
148 | | }; |
149 | | |
150 | | // Assemble the TAI result, preserving the UTC split and order. |
151 | 0 | let mut res2 = z1 - u1; |
152 | 0 | res2 += z2; |
153 | 0 | res2 += fd + dat0 / DAYSEC; |
154 | 0 | if big1 { Ok((u1, res2)) } else { Ok((res2, u1)) } |
155 | 0 | } |