java.time DST + data readers: make tick pass fully
Shaking out tick's api and alpha.interval suites (api 353->359, interval
0->103 passing) cleared a set of general gaps:
- Named-zone DST. Zones resolved to a fixed representative offset, so
America/New_York in August read -05:00 not -04:00. Add US/EU DST rules
(compact transition-date math) and make instant<->zoned, the zone rules'
getOffset, and the zoned equality arm DST-aware.
- Nanosecond zoned/offset times. Instant is nanos but atZone/atOffset/
toInstant/withZoneSameInstant and Instant/parse went through epoch-ms,
truncating sub-ms. Route them through nanos.
- Locale month/day names. A formatter dropped its Locale; carry it and add
French names so MMM under Locale/FRENCH renders "mai".
- Callable records. A defrecord implementing clojure.lang.IFn (tick's
GeneralRelation) is now invokable: jolt-invoke dispatches to its inline
invoke method. Also give collections the Iterable host tag so a protocol
extended to Iterable matches vectors/seqs.
- Imported class short names. (:import [java.time ZonedDateTime]) then
(. ZonedDateTime parse s) resolved to nil; an otherwise-unresolved bare
Capitalized name that's a registered host class now resolves as a class.
- Data readers. A project's data_readers.{clj,cljc} is loaded into
*data-readers* (reader namespaces required eagerly); registered #tag
literals in source rewrite to (reader-fn 'form). clojure.core/read-string
now applies #inst/#uuid/#"regex" and *data-readers* like Clojure.
- Duration/between accepts zoned/offset date-times.
All runtime shims, no re-mint. docs/libraries.md: tick full pass + aero.
This commit is contained in:
parent
8d7d03bfbc
commit
7b1ec9a1d3
8 changed files with 354 additions and 43 deletions
|
|
@ -560,8 +560,42 @@
|
|||
(define (rdr-carry-meta src dst)
|
||||
(let ((m (jolt-meta src))) (if (jolt-nil? m) dst (jolt-with-meta dst m))))
|
||||
|
||||
;; tag keyword (:#time/date) -> its *data-readers* reader fn, or #f. The fn's
|
||||
;; namespace must already be loaded (the loader requires them when a project's
|
||||
;; data_readers.{clj,cljc} registers a tag).
|
||||
(define (rdr-data-reader-fn tag)
|
||||
(and (keyword? tag)
|
||||
(let ((nm (keyword-t-name tag)))
|
||||
(and (> (string-length nm) 0) (char=? (string-ref nm 0) #\#)
|
||||
(let* ((bare (substring nm 1 (string-length nm)))
|
||||
(slash (let loop ((i 0))
|
||||
(cond ((>= i (string-length bare)) #f)
|
||||
((char=? (string-ref bare i) #\/) i)
|
||||
(else (loop (+ i 1))))))
|
||||
(sym (if slash
|
||||
(jolt-symbol (substring bare 0 slash) (substring bare (+ slash 1) (string-length bare)))
|
||||
(jolt-symbol #f bare)))
|
||||
(dr (var-deref "clojure.core" "*data-readers*"))
|
||||
(v (and (pmap? dr) (jolt-get dr sym))))
|
||||
(and v (not (jolt-nil? v)) (symbol-t? v) (not (jolt-nil? (symbol-t-ns v)))
|
||||
(guard (e (#t #f))
|
||||
(let ((fn (var-deref (symbol-t-ns v) (symbol-t-name v))))
|
||||
(and (procedure? fn) fn)))))))))
|
||||
;; read-string / read data seam: construct the value for a #tag literal. #inst,
|
||||
;; #uuid and #"regex" are built in; any other tag is applied from *data-readers*.
|
||||
;; An unregistered tag stays a tagged FORM (lenient — clojure.edn raises instead).
|
||||
(define (rdr-construct-tag tag inner)
|
||||
(cond
|
||||
((eq? tag (keyword #f "#inst")) (jolt-inst-from-string inner))
|
||||
((eq? tag (keyword #f "#uuid")) (jolt-uuid-from-string inner))
|
||||
((eq? tag (keyword #f "regex")) (jolt-re-pattern inner))
|
||||
(else (let ((fn (rdr-data-reader-fn tag)))
|
||||
(if fn (jolt-invoke fn inner) (rdr-make-tagged tag inner))))))
|
||||
|
||||
(define (rdr-form->data x)
|
||||
(cond
|
||||
((and (pmap? x) (eq? (jolt-get x rdr-kw-jolt-type) rdr-kw-jolt-tagged))
|
||||
(rdr-construct-tag (jolt-get x rdr-kw-tag) (rdr-form->data (jolt-get x rdr-kw-form))))
|
||||
((rdr-set-form? x)
|
||||
(let ((items (jolt-get x rdr-kw-value)))
|
||||
(rdr-carry-meta x
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue