Coverage Report

Created: 2026-05-16 06:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/sofars-0.6.1/src/cal/jdcalf.rs
Line
Count
Source
1
use crate::cal::jd2cal;
2
3
/// Julian Date to Gregorian Calendar, expressed in a form convenient
4
/// for formatting messages: rounded to a specified precision.
5
///
6
/// This function is part of the International Astronomical Union's
7
/// SOFA (Standards of Fundamental Astronomy) software collection.
8
///
9
/// Status: support function.
10
///
11
/// # Given:
12
/// * `ndp`: number of decimal places of days in fraction
13
/// * `dj1`, `dj2`: dj1+dj2 = Julian Date (Note 1)
14
///
15
/// # Returned:
16
/// * `(iy, im, id, iymdf_3)`: year, month, day, fraction in Gregorian calendar
17
///
18
/// # Returned (function value):
19
/// * `Result`:
20
///     * `Ok(status)`:
21
///         * `0` = OK
22
///         * `1` = ndp not 0-9 (interpreted as 0)
23
///     * `Err(status)`:
24
///         * `-1` = date out of range
25
///
26
/// # Notes:
27
/// 1) The Julian Date is apportioned in any convenient way between
28
///    the arguments dj1 and dj2. For example, JD=2450123.7 could
29
///    be expressed in any of these ways, among others:
30
///
31
///            dj1            dj2
32
///
33
///        2450123.7           0.0       (JD method)
34
///        2451545.0       -1421.3       (J2000 method)
35
///        2400000.5       50123.2       (MJD method)
36
///        2450123.5           0.2       (date & time method)
37
///
38
/// 2) In early eras the conversion is from the "Proleptic Gregorian
39
///    Calendar"; no account is taken of the date(s) of adoption of
40
///    the Gregorian Calendar, nor is the AD/BC numbering convention
41
///    observed.
42
///
43
/// 3) See also the function iauJd2cal.
44
///
45
/// 4) The number of decimal places ndp should be 4 or less if internal
46
///    overflows are to be avoided on platforms which use 16-bit
47
///    integers.
48
///
49
/// # Reference:
50
/// Explanatory Supplement to the Astronomical Almanac,
51
/// P. Kenneth Seidelmann (ed), University Science Books (1992),
52
/// Section 12.92 (p604).
53
0
pub fn jdcalf(ndp: i32, dj1: f64, dj2: f64) -> Result<(i32, i32, i32, i32, i32), i32> {
54
    let j;
55
    let denom;
56
57
    /* Denominator of fraction (e.g. 100 for 2 decimal places). */
58
0
    if (ndp >= 0) && (ndp <= 9) {
59
0
        j = 0;
60
0
        denom = 10.0f64.powi(ndp);
61
0
    } else {
62
0
        j = 1;
63
0
        denom = 1.0;
64
0
    }
65
66
    /* Copy the date, big then small. */
67
0
    let (mut d1, d2) = if dj1.abs() >= dj2.abs() {
68
0
        (dj1, dj2)
69
    } else {
70
0
        (dj2, dj1)
71
    };
72
73
    /* Realign to midnight (without rounding error). */
74
0
    d1 -= 0.5;
75
76
    /* Separate day and fraction (as precisely as possible). */
77
0
    let mut d = dnint(d1);
78
0
    let f1 = d1 - d;
79
0
    let mut djd = d;
80
0
    d = dnint(d2);
81
0
    let f2 = d2 - d;
82
0
    djd += d;
83
0
    d = dnint(f1 + f2);
84
0
    let mut f = (f1 - d) + f2;
85
0
    if f < 0.0 {
86
0
        f += 1.0;
87
0
        d -= 1.0;
88
0
    }
89
0
    djd += d;
90
91
    /* Round the total fraction to the specified number of places. */
92
0
    let rf = dnint(f * denom) / denom;
93
94
    /* Re-align to noon. */
95
0
    djd += 0.5;
96
97
    /* Convert to Gregorian calendar. */
98
0
    match jd2cal(djd, rf) {
99
0
        Ok((iy, im, id, f_out)) => {
100
0
            let iymdf_3 = dnint(f_out * denom) as i32;
101
0
            Ok((iy, im, id, iymdf_3, j))
102
        }
103
0
        Err(js) => Err(js),
104
    }
105
0
}
106
107
/* dnint(A) - round to nearest whole number (double) */
108
0
fn dnint(a: f64) -> f64 {
109
0
    if a.abs() < 0.5 {
110
0
        0.0
111
0
    } else if a < 0.0 {
112
0
        (a - 0.5).ceil()
113
    } else {
114
0
        (a + 0.5).floor()
115
    }
116
0
}