Java.time

I just made a transparent solution - using Richelieu advices - for using java.time.Instant in transactions and receiving them in pull results.

See my original post about it here:

For convenience, I will repeat the code here too:

(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))
  )

It returns {:timestamp #time/instant"2021-05-27T05:54:00.260Z"}.

1 Like