Since the java.time
package is well-designed and built-in to Java 8+ and it’s quite convenient to work with, via juxt/tick, I really wanted to use it with Datomic transparently.
Here is my 1st, seemingly successful attempt, which advises the d/pull
and d/transact
functions, using the Richelieu library:
(ns xxx.datomic.client
"Conveniences for working with the `datomic.client.api`."
(:require
[datomic.client.api :as d]
[richelieu.core :refer :all]
[tick.alpha.api :as t]
[clojure.walk :as walk]))
(defn- maybe-instant->inst [i] (if (t/instant? i) (t/inst i) i))
(defadvice ^:private transact-instants [transact conn arg-map]
(transact conn
(update arg-map :tx-data
(partial walk/postwalk maybe-instant->inst))))
(defonce _transact-instants (advise-var #'d/transact #'transact-instants))
(defn- maybe-inst->instant [i] (if (inst? i) (t/instant i) i))
(defadvice ^:private pull-instants
([pull db arg-map]
(->> (pull db arg-map)
(walk/postwalk maybe-inst->instant)))
([pull db selector eid]
(->> (pull db selector eid)
(walk/postwalk maybe-inst->instant))))
(defonce _pull-instants (advise-var #'d/pull #'pull-instants))
Here is an example of a java.time.Instant
roundtrip to a Datomic DB:
(comment
(let [client (d/client {:server-type :dev-local
:storage-dir :mem
:system "tick"})
db-ref {:db-name "demo"}
_ (d/create-database client db-ref)
conn (d/connect client db-ref)]
(->> [[{:db/ident :timestamp
:db/valueType :db.type/instant
:db/cardinality :db.cardinality/one}]
[{:db/ident :t1
:timestamp (t/now)}]]
(reduce (fn [c tx] (d/transact c {:tx-data tx}) c) conn))
(d/pull (d/db conn) [:timestamp] :t1))
)
Please share your thoughts and opinions!
(I’ve seen the GitHub - magnars/java-time-dte: Datomic type extensions for java.time classes library, but that was made for Datomic On-Prem and relied on the internals of Datomic.)