js-on-sx: Date.prototype.toISOString proper YMDhms format + Type/RangeError gates
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s

This commit is contained in:
2026-05-10 07:39:40 +00:00
parent fb8bb9f105
commit 5bb65d8315
2 changed files with 131 additions and 4 deletions

View File

@@ -1193,12 +1193,137 @@
js-date-iso
(fn
(d)
(cond
((or (not (dict? d)) (not (contains? (keys d) "__js_is_date__")))
(raise (js-new-call TypeError (js-args "this is not a Date object"))))
(else
(let
((ms-raw (get d "__date_value__")))
(let
((ms (if (= (type-of ms-raw) "rational") (exact->inexact ms-raw) ms-raw)))
(cond
((or (= ms nil) (js-undefined? ms))
(raise (js-new-call RangeError (js-args "Invalid time value"))))
((not (number? ms))
(raise (js-new-call RangeError (js-args "Invalid time value"))))
((js-number-is-nan ms)
(raise (js-new-call RangeError (js-args "Invalid time value"))))
((or (> ms 8640000000000000) (< ms -8640000000000000))
(raise (js-new-call RangeError (js-args "Invalid time value"))))
(else (js-date-iso-format ms)))))))))
(define
js-date-iso-format
(fn
(ms)
(let
((ms (get d "__date_value__")))
((day-ms 86400000) (sec-ms 1000) (min-ms 60000) (hr-ms 3600000))
(let
((year
(+ 1970 (js-math-trunc (/ ms 31557600000)))))
(str (js-date-year-pad year) "-01-01T00:00:00.000Z")))))
((days (floor (/ ms day-ms)))
(time-of-day
(let ((m (modulo (js-num-to-int ms) day-ms)))
(if (< m 0) (+ m day-ms) m))))
(let
((hh (js-math-trunc (/ time-of-day hr-ms)))
(mm (js-math-trunc (/ (modulo time-of-day hr-ms) min-ms)))
(ss (js-math-trunc (/ (modulo time-of-day min-ms) sec-ms)))
(msec (modulo time-of-day sec-ms))
(ymd (js-date-days-to-ymd days)))
(let
((y (nth ymd 0)) (mo (nth ymd 1)) (d (nth ymd 2)))
(str
(js-date-iso-year y)
"-"
(js-pad2 mo)
"-"
(js-pad2 d)
"T"
(js-pad2 hh)
":"
(js-pad2 mm)
":"
(js-pad2 ss)
"."
(js-pad3 msec)
"Z")))))))
(define
js-date-iso-year
(fn
(y)
(cond
((or (< y 0) (> y 9999))
(let
((sign (if (< y 0) "-" "+"))
(ay (if (< y 0) (- 0 y) y)))
(str sign (js-date-year-6 ay))))
((< y 10) (str "000" (js-to-string y)))
((< y 100) (str "00" (js-to-string y)))
((< y 1000) (str "0" (js-to-string y)))
(else (js-to-string y)))))
(define
js-date-year-6
(fn
(y)
(cond
((< y 10) (str "00000" (js-to-string y)))
((< y 100) (str "0000" (js-to-string y)))
((< y 1000) (str "000" (js-to-string y)))
((< y 10000) (str "00" (js-to-string y)))
((< y 100000) (str "0" (js-to-string y)))
(else (js-to-string y)))))
(define js-pad2 (fn (n) (if (< n 10) (str "0" (js-to-string n)) (js-to-string n))))
(define
js-pad3
(fn
(n)
(cond
((< n 10) (str "00" (js-to-string n)))
((< n 100) (str "0" (js-to-string n)))
(else (js-to-string n)))))
(define
js-date-days-to-ymd
(fn
(days-since-epoch)
(let
((d (+ days-since-epoch 719468)))
(let
((era (if (>= d 0) (js-math-trunc (/ d 146097)) (js-math-trunc (/ (- d 146096) 146097)))))
(let
((doe (- d (* era 146097))))
(let
((yoe
(js-math-trunc
(/
(-
(+
(- doe (js-math-trunc (/ doe 1460)))
(js-math-trunc (/ doe 36524)))
(js-math-trunc (/ doe 146096)))
365))))
(let
((y (+ yoe (* era 400)))
(doy
(-
doe
(+
(* yoe 365)
(-
(js-math-trunc (/ yoe 4))
(js-math-trunc (/ yoe 100)))))))
(let
((mp (js-math-trunc (/ (+ (* 5 doy) 2) 153))))
(let
((day (- (+ doy 1) (js-math-trunc (/ (+ (* 153 mp) 2) 5))))
(month (if (< mp 10) (+ mp 3) (- mp 9))))
(list
(if (<= month 2) (+ y 1) y)
month
day))))))))))
(define
js-date-year-pad