Search code examples
clojurejava-time

Clojure java-time: getting instant with millis


I'm trying to convert a local-date into an instant with millis using java-time, but instant returns a timestamp without millis.

(def UTC (java-time/zone-id "UTC")

(defn local-date-to-instant [local-date] 
  (-> local-date
      (.atStartOfDay UTC)
      java-time/instant))

(local-date-to-instant (java-time/local-date))
=> #object[java.time.Instant 0xdb3a8c7 "2021-05-13T00:00:00Z"]

but

(java-time/instant)
=> #object[java.time.Instant 0x1d1c27c8 "2021-05-13T13:12:31.782Z"]

The service downstream expects a string in this format: yyyy-MM-ddTHH:mm:ss.SSSZ.


Solution

  • Create a DateTimeFormatter that prints an ISO instant with milliseconds (3 fractional digits) even if they are zeroes:

    (ns steffan.overflow
      (:require [java-time :as jt])
      (:import (java.time.format DateTimeFormatterBuilder)))
    
    (def iso-instant-ms-formatter
      (-> (DateTimeFormatterBuilder.) (.appendInstant 3) .toFormatter))
    

    Example of use:

    (def today-inst (jt/truncate-to (jt/instant) :days))
    
    (str today-inst)                                ; => "2021-05-13T00:00:00Z"
    (jt/format iso-instant-ms-formatter today-inst) ; => "2021-05-13T00:00:00.000Z"