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:
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
//