Coverage Report

Created: 2026-10-28 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}