use crate::Dt;
pub struct LeapSecond {
pub ntp_timestamp: i64,
pub leap_seconds_after: i64,
pub utc_sec: i64,
pub tai_sec: i64,
}
pub const LEAP_SECS: &[LeapSecond] = &[
LeapSecond {
ntp_timestamp: 2272060800,
leap_seconds_after: 10,
utc_sec: -883656000,
tai_sec: -883655991, }, LeapSecond {
ntp_timestamp: 2287785600,
leap_seconds_after: 11,
utc_sec: -867931200,
tai_sec: -867931190, }, LeapSecond {
ntp_timestamp: 2303683200,
leap_seconds_after: 12,
utc_sec: -852033600,
tai_sec: -852033589, }, LeapSecond {
ntp_timestamp: 2335219200,
leap_seconds_after: 13,
utc_sec: -820497600,
tai_sec: -820497588, }, LeapSecond {
ntp_timestamp: 2366755200,
leap_seconds_after: 14,
utc_sec: -788961600,
tai_sec: -788961587, }, LeapSecond {
ntp_timestamp: 2398291200,
leap_seconds_after: 15,
utc_sec: -757425600,
tai_sec: -757425586, }, LeapSecond {
ntp_timestamp: 2429913600,
leap_seconds_after: 16,
utc_sec: -725803200,
tai_sec: -725803185, }, LeapSecond {
ntp_timestamp: 2461449600,
leap_seconds_after: 17,
utc_sec: -694267200,
tai_sec: -694267184, }, LeapSecond {
ntp_timestamp: 2492985600,
leap_seconds_after: 18,
utc_sec: -662731200,
tai_sec: -662731183, }, LeapSecond {
ntp_timestamp: 2524521600,
leap_seconds_after: 19,
utc_sec: -631195200,
tai_sec: -631195182, }, LeapSecond {
ntp_timestamp: 2571782400,
leap_seconds_after: 20,
utc_sec: -583934400,
tai_sec: -583934381, }, LeapSecond {
ntp_timestamp: 2603318400,
leap_seconds_after: 21,
utc_sec: -552398400,
tai_sec: -552398380, }, LeapSecond {
ntp_timestamp: 2634854400,
leap_seconds_after: 22,
utc_sec: -520862400,
tai_sec: -520862379, }, LeapSecond {
ntp_timestamp: 2698012800,
leap_seconds_after: 23,
utc_sec: -457704000,
tai_sec: -457703978, }, LeapSecond {
ntp_timestamp: 2776982400,
leap_seconds_after: 24,
utc_sec: -378734400,
tai_sec: -378734377, }, LeapSecond {
ntp_timestamp: 2840140800,
leap_seconds_after: 25,
utc_sec: -315576000,
tai_sec: -315575976, }, LeapSecond {
ntp_timestamp: 2871676800,
leap_seconds_after: 26,
utc_sec: -284040000,
tai_sec: -284039975, }, LeapSecond {
ntp_timestamp: 2918937600,
leap_seconds_after: 27,
utc_sec: -236779200,
tai_sec: -236779174, }, LeapSecond {
ntp_timestamp: 2950473600,
leap_seconds_after: 28,
utc_sec: -205243200,
tai_sec: -205243173, }, LeapSecond {
ntp_timestamp: 2982009600,
leap_seconds_after: 29,
utc_sec: -173707200,
tai_sec: -173707172, }, LeapSecond {
ntp_timestamp: 3029443200,
leap_seconds_after: 30,
utc_sec: -126273600,
tai_sec: -126273571, }, LeapSecond {
ntp_timestamp: 3076704000,
leap_seconds_after: 31,
utc_sec: -79012800,
tai_sec: -79012770, }, LeapSecond {
ntp_timestamp: 3124137600,
leap_seconds_after: 32,
utc_sec: -31579200,
tai_sec: -31579169, }, LeapSecond {
ntp_timestamp: 3345062400,
leap_seconds_after: 33,
utc_sec: 189345600,
tai_sec: 189345632, }, LeapSecond {
ntp_timestamp: 3439756800,
leap_seconds_after: 34,
utc_sec: 284040000,
tai_sec: 284040033, }, LeapSecond {
ntp_timestamp: 3550089600,
leap_seconds_after: 35,
utc_sec: 394372800,
tai_sec: 394372834, }, LeapSecond {
ntp_timestamp: 3644697600,
leap_seconds_after: 36,
utc_sec: 488980800,
tai_sec: 488980835, }, LeapSecond {
ntp_timestamp: 3692217600,
leap_seconds_after: 37,
utc_sec: 536500800,
tai_sec: 536500836, }, ];
#[derive(Copy, Clone, Debug)]
pub struct LeapInfo {
pub offset: i64,
pub leaps_inserted: i64,
pub is_leap_second: bool,
}
impl Dt {
#[inline]
pub const fn leap_seconds(&self, from_civil: bool) -> LeapInfo {
get_leap_seconds(self, from_civil)
}
#[inline]
pub const fn leap_seconds_using(&self, from_civil: bool, table: &[LeapSecond]) -> LeapInfo {
get_leap_seconds_with_table(self, from_civil, table)
}
}
#[inline]
pub const fn get_leap_seconds(dt: &Dt, from_civil: bool) -> LeapInfo {
get_leap_seconds_with_table(dt, from_civil, LEAP_SECS)
}
pub const fn get_leap_seconds_with_table(
dt: &Dt,
from_civil: bool,
table: &[LeapSecond],
) -> LeapInfo {
let len = table.len();
if len == 0 {
return LeapInfo {
offset: 0,
leaps_inserted: 0,
is_leap_second: false,
};
}
let target = dt.sec();
let mut low = 0usize;
let mut high = len;
while low < high {
let mid = low + (high - low) / 2;
let entry_sec = if from_civil {
table[mid].utc_sec
} else {
table[mid].tai_sec
};
if entry_sec <= target {
low = mid + 1;
} else {
high = mid;
}
}
if low == 0 {
return LeapInfo {
offset: 0,
leaps_inserted: 0,
is_leap_second: false,
};
}
let idx = low - 1;
let entry = &table[idx];
let entry_sec = if from_civil {
entry.utc_sec
} else {
entry.tai_sec
};
let is_leap = target == entry_sec;
LeapInfo {
offset: entry.leap_seconds_after,
leaps_inserted: (idx + 1) as i64,
is_leap_second: is_leap,
}
}