From 59eea64985d3d0b41e0860b13378ad22ecd0158b Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Mon, 6 Oct 2025 22:02:55 +0100 Subject: [PATCH] add tai64 module to anoia --- pkgs/anoia/Makefile | 4 +-- pkgs/anoia/tai64.fnl | 78 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 pkgs/anoia/tai64.fnl diff --git a/pkgs/anoia/Makefile b/pkgs/anoia/Makefile index 2d202d6..cce0946 100644 --- a/pkgs/anoia/Makefile +++ b/pkgs/anoia/Makefile @@ -1,9 +1,9 @@ servicedir:=$(shell mktemp -d) outputdir:=$(servicedir)/.outputs -default: fs.lua init.lua nl.lua svc.lua process.lua net/constants.lua +default: fs.lua init.lua nl.lua svc.lua process.lua net/constants.lua tai64.lua -CHECK=fs.fnl init.fnl svc.fnl process.fnl +CHECK=fs.fnl init.fnl svc.fnl process.fnl tai64.fnl check: ln -s . anoia diff --git a/pkgs/anoia/tai64.fnl b/pkgs/anoia/tai64.fnl new file mode 100644 index 0000000..d19153a --- /dev/null +++ b/pkgs/anoia/tai64.fnl @@ -0,0 +1,78 @@ +(local { : base64 : assoc } (require :anoia)) +(import-macros { : expect= : define-tests } :anoia.assert) + +(local + leap-seconds-list + (let [tbl + [ + ;; https://data.iana.org/time-zones/data/leap-seconds.list + ;; comments are the _start_ of the day where the second was + ;; added at the end of the previous day + [2272060800 10] ; 1 jan 1972 ; baseline, not a leap second + [2287785600 11] ; 1 jul 1972 + [2303683200 12] ; 1 jan 1973 + [2335219200 13] ; 1 jan 1974 + [2366755200 14] ; 1 Jan 1975 + [2398291200 15] ; 1 Jan 1976 + [2429913600 16] ; 1 Jan 1977 + [2461449600 17] ; 1 Jan 1978 + [2492985600 18] ; 1 Jan 1979 + [2524521600 19] ; 1 Jan 1980 + [2571782400 20] ; 1 Jul 1981 + [2603318400 21] ; 1 Jul 1982 + [2634854400 22] ; 1 Jul 1983 + [2698012800 23] ; 1 Jul 1985 + [2776982400 24] ; 1 Jan 1988 + [2840140800 25] ; 1 Jan 1990 + [2871676800 26] ; 1 Jan 1991 + [2918937600 27] ; 1 Jul 1992 + [2950473600 28] ; 1 Jul 1993 + [2982009600 29] ; 1 Jul 1994 + [3029443200 30] ; 1 Jan 1996 + [3076704000 31] ; 1 Jul 1997 + [3124137600 32] ; 1 Jan 1999 + [3345062400 33] ; 1 Jan 2006 + [3439756800 34] ; 1 Jan 2009 + [3550089600 35] ; 1 Jul 2012 + [3644697600 36] ; 1 Jul 2015 + [3692217600 37] ; 1 Jan 2017 + ]] + (icollect [_ [ts dtai] (ipairs tbl)] + [(+ (- ts 2208988800) dtai) dtai]))) + +(fn leap-seconds [timestamp] + (accumulate [secs 10 + _ [epoch leap-seconds] (ipairs leap-seconds-list) + &until (> epoch timestamp)] + leap-seconds)) + +(define-tests :leap-seconds + (expect= (leap-seconds 104694412) 12) + (expect= (leap-seconds 23) 10) + (expect= (leap-seconds (+ 3692217600 60)) 37) + (expect= (leap-seconds (+ 10 773020829)) 29) + (expect= (leap-seconds 362793520) 19)) + +(fn from-timestamp [str] + (if (= (string.sub str 1 1) "@") + (let [s (tonumber (string.sub str 2 17) 16) + two_62 (lshift 1 62) + sec (if (>= s two_62) + (- s two_62) + (- two_62 s)) + nano (tonumber (string.sub str 18 25) 16)] + {:s sec :n nano}) + nil)) + +(fn to-utc [tai] + (+ (- tai.s (leap-seconds tai.s)) (/ tai.n 1e9))) + +(define-tests + (expect= + (from-timestamp "@4000000068e2f0d3257dc09b") + {:s 1759703251 :n 628998299}) + + (expect= (to-utc (from-timestamp "@4000000068e2f0d3257dc09b")) + 1759703214.628998299)) + +{ : from-timestamp : to-utc }