Как распечатать время как #inst

Легко читать литерал даты:

(read-string "#inst \"2012\"")
        ;;; ⇒ #inst "2012-01-01T00:00:00.000-00:00"

Как я могу вывести дату как литерал #inst...?

Это не работает:

(pr-str (clj-time.core/now))
        ;;; ⇒ "#<DateTime 2013-07-09T17:26:30.058Z>"

(read-string (pr-str (clj-time.core/now)))
        ;;; ⇒ <err>
        ;;;   RuntimeException Unreadable form  clojure.lang.Util.runtimeException (Util.java:219)

Ответы

Ответ 1

Когда вы читаете в литерале #inst, по умолчанию создается экземпляр java.util.Date. У них есть метод, определенный для print-method (мультиметод, отвечающий за печатные представления объектов) в пространстве имен clojure.instant (соответствующий фрагмент источника 1.5.1 здесь).

clj-time использует тип DateTime от Joda-Time, у которого нет настраиваемого метода print-method. Это имеет смысл, так как наличие a print-method, которое создает представление, которое не обращается вбок, редко бывает желательным. Для того, чтобы он прошел в оба конца, вам придется использовать нестандартный читатель #inst. Для этого, если вы читаете данные edn, вы можете использовать clojure.edn/read (или read-string), передавая соответствующий читатель, как описано в его документации:

(require '[clojure.edn :as edn])

(edn/read {:readers {'inst your-inst-reader}} rdr)

При использовании clj-времени your-inst-reader будет чем-то вроде #(clj-time.format/parse some-formatter %). Затем вы можете предоставить соответствующее определение print-method, следуя примеру clojure.instant. (Или вы можете просто указать определение print-method и помнить, что вы не получите идеального округления, clj-time обеспечивает очень удобные функции принуждения - см. Ниже - так что это может быть нормально.)

В качестве альтернативы вы можете печатать и читать экземпляры java.util.Date и преобразовывать их в и из DateTime s; существуют функции для этого в clj-time.coerce.