datomic

Ask questions on the official Q&A site at https://ask.datomic.com!
nando 2020-10-03T00:06:23.190Z

(t/instant? (.toInstant #inst "2020-09-26T23:08:27.619-00:00")) => true (t/instant? (t/instant #inst "2020-09-26T23:08:27.619-00:00")) => true

nando 2020-10-03T00:23:34.190200Z

This works: (t/format "<http://yyyy.MM|yyyy.MM>.dd" (t/zoned-date-time 2015 9 28)) => "2015.09.28" but I can't find a way to convert a datomic db.type/instant to a zoned-date-time.

nando 2020-10-03T00:36:37.190400Z

There must be a more straightforward way to format datomic datetime values.

seancorfield 2020-10-03T04:45:06.190600Z

@nando

user=&gt; (t/format "dd/MM/yyyy" (t/zoned-date-time #inst "2020-09-26T23:08:27.619-00:00" (t/zone-id "UTC")))
"26/09/2020"
user=&gt; 

seancorfield 2020-10-03T04:45:27.190800Z

(or whatever TZ you need there)

seancorfield 2020-10-03T04:51:42.191Z

Although if you're dealing with #inst which I believe are just regular java.util.Date objects, this should work (without clojure.java-time at all):

user=&gt; (let [f (java.text.SimpleDateFormat. "dd/MM/yyyy")]
         (.format f #inst "2020-09-26T23:08:27.619-00:00"))
"26/09/2020"
user=&gt; 

seancorfield 2020-10-03T04:53:11.191200Z

Yup, Datomic docs say it's just a java.util.Date:

:db.type/instant	instant in time	java.util.Date	#inst "2017-09-16T11:43:32.450-00:00"

nando 2020-10-03T10:51:36.191400Z

@seancorfield Thanks very much! I've confirmed that both approaches work as expected with an #inst returned from datomic.

nando 2020-10-03T11:37:18.191600Z

I've learned a lot here, both by dipping my toes into the clojure.java-time and tick libraries, and getting a more practical sense of how java interop works through your example.

favila 2020-10-03T12:33:27.192100Z

@nando I meant something like this (sorry, was on a phone earlier):

(let [d #inst"2020-10-03T12:18:02.445-00:00"
      f (-&gt; (java.time.format.DateTimeFormatter/ofPattern "dd/MM/yyyy")
            (.withZone (java.time.ZoneId/systemDefault)))]
  (.format f (.toInstant d)))

favila 2020-10-03T12:33:50.192300Z

I avoid java.text.SimpleDateFormat because it’s the “old” way and it’s not thread-safe

favila 2020-10-03T12:35:28.192500Z

I think what sean posted is nearly the equivalent, except he coerces to a zoned date time instead of specifying the zone in the formatter

favila 2020-10-03T12:35:46.192700Z

but I’m not familiar with clojure.java-time, I just use java.time directly

nando 2020-10-03T13:30:48.192900Z

@favila I see what you originally meant evaluating

(let [d #inst"2020-10-03T12:18:02.445-00:00"
                       f (-&gt; (java.time.format.DateTimeFormatter/ofPattern "dd/MM/yyyy")
                             (.withZone (java.time.ZoneId/systemDefault)))]
                   (.format f d))

nando 2020-10-03T13:32:13.193100Z

The same error is produced without the date being wrapped in a .toInstant call.

nando 2020-10-03T13:40:30.193300Z

In what type of use case would the fact that SimpleDateFormat is not thread safe produce an unexpected result, particularly in the context of a web application?

favila 2020-10-03T14:19:52.194500Z

Def the format object and then use it in functions running in my tools threads

favila 2020-10-03T14:20:12.195Z

*multiple

favila 2020-10-03T14:24:04.197700Z

There are a few strata of Java date systems

favila 2020-10-03T14:25:50.200100Z

The oldest is Java.util.date objects. The newest is Java.time.*, which represents instants as Java.time.Instant objects instead.

favila 2020-10-03T14:26:16.200800Z

There are some in between that aren’t worth learning anymore

seancorfield 2020-10-03T17:55:04.201Z

Yup, going via Java Time is definitely the safest route and the best set of APIs to learn. At work, over the past decade we've gone from java.util.Date to date-clj (date arithmetic for that old Date type), to clj-time (wrapping Joda Time), to Java Time (with clojure.java-time in some parts of the code and plain interop in a lot of places). Converting java.util.Date to java.time.Instant and doing everything in Java Time is a bit painful/verbose, but you can write utility functions for stuff you need frequently to hide that interop/verbosity.