hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit f10ac698195c0ba1d73dcb6b84ae9c43944f1abb
parent b71c42164e330b7c6f56f737b002db91eef9900f
Author: Byron Torres <b@torresjrjr.com>
Date:   Thu,  3 Feb 2022 23:29:43 +0000

WIP tai/utc leaps handling

Signed-off-by: Byron Torres <b@torresjrjr.com>

Diffstat:
Mtime/chrono/leapsec.ha | 9++++++++-
Mtime/chrono/timescale.ha | 43++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/time/chrono/leapsec.ha b/time/chrono/leapsec.ha @@ -24,12 +24,18 @@ use strings; // timescales. Therefore, we have decided to take an alternative approach. // The filepath of the leap-seconds.list file +export def SECS_1900_1970: i64 = 2208988800; + +// The filepath of the leap-seconds.list file export def UTC_LEAPSECS_FILE: str = "/usr/share/zoneinfo/leap-seconds.list"; // UTC timestamps and their TAI offsets, sourced from leap-seconds.list let utc_leapsecs: [](i64, i64) = []; -// TODO: BUG: Cannot compile harec2 with this line. +// TODO: Fix, cannot compile harec2 with this line. This code is currenlty +// called where it's needed, as a workaround. Remember to prune this function +// call elsewhere once this @init is fixed. +// //@init fn init_utc_leapsecs() void = init_utc_leapsecs(); fn init_utc_leapsecs() void = { @@ -57,6 +63,7 @@ fn read_leapsecfile(h: io::handle, leapsecs: *[](i64, i64)) (void | io::error) = }; const a = strconv::stoi64(pair[0])!; const b = strconv::stoi64(pair[1])!; + const a = a - SECS_1900_1970; const pair = (a: i64, b: i64); append(utc_leapsecs, pair); }; diff --git a/time/chrono/timescale.ha b/time/chrono/timescale.ha @@ -46,6 +46,15 @@ export const utc: timescale = timescale { }; fn conv_tai_utc(a: time::instant) (time::instant | time::error) = { + init_utc_leapsecs(); + + const idx = lookup_leaps(utc_leapsecs, time::unix(a)); + const ofst = utc_leapsecs[idx].1; + + if (time::unix(a) == utc_leapsecs[idx].0) { + void; + }; + const b = time::instant { sec = a.sec - 37, nsec = a.nsec, @@ -54,13 +63,45 @@ fn conv_tai_utc(a: time::instant) (time::instant | time::error) = { }; fn conv_utc_tai(a: time::instant) (time::instant | time::error) = { + init_utc_leapsecs(); + + const idx = lookup_leaps(utc_leapsecs, time::unix(a)); + const ofst = utc_leapsecs[idx].1; + + if (time::unix(a) == utc_leapsecs[idx].0) { + void; + }; + const b = time::instant { - sec = a.sec + 37, + sec = a.sec + ofst, nsec = a.nsec, }; return b; }; +fn lookup_leaps(list: [](i64, i64), t: i64) size = { + let lo = 0z, hi = len(list); + for (hi - lo > 1) { + const mid = lo + (hi - lo) / 2; + const middle = list[mid].0; + const cmp = time::compare( + time::from_unix(t), + time::from_unix(middle), + ); + switch (cmp) { + case -1 => + hi = mid; + case 0 => + lo = mid; break; + case 1 => + lo = mid; + case => + abort("Unreachable"); + }; + }; + return lo; +}; + // Global Positioning System Time //