Welcome! Please see the About page for a little more info on how this works.

0 votes
in data.json by
closed by

See Slack discussion here for the full background: https://clojurians.slack.com/archives/C03S1KBA2/p1723222018579489

Problem statement:

I have a :date-format of "MMMM, dd yyyy HH:mm:ss Z" that I use with Cheshire to turn various types of date/time values into JSON. In particular, java.sql.Timestamp but also others. This works.

I wanted to switch to data.json so I provided :date-formatter with (DateTimeFormatter/ofPattern "MMMM, dd yyyy HH:mm:ss Z") but it threw an exception because data.json internally coerces date/time values to java.time.Instant which doesn't support that pattern.

Several possible solutions I considered:

  • force users to manually convert those types themselves (avoiding that was the whole point of DJSON-41) -- this is essentially "do nothing"
  • provide an option to pre-transform Instant to some other type prior to formatting (which gives the user control over zones/offsets etc)
  • make existing :date-formatter option "smarter" so it can accept a DateTimeFormatter or a user-supplied Instant formatting function
  • change from Instant to some other date/time type internally in a way that is compatible with any formatting that Instant already supports to allow for more variety of DateTimeFormatter patterns
  • ...

I worked around it by using :value-fn but this means a runtime test on every value and manual conversion of date/time values to strings in user code...

  • 1 goes against the whole point of adding date/time formatting support
  • 2 and 3 both add a small runtime overhead (3 would probably be my preference tho')
  • 4 might be tricky to completely support all existing formatting (I don't know) but might be the most seamless "Cheshire compatibility" path
closed with the note: Solved by @cddr on Slack and answer added here for future seekers.

1 Answer

0 votes
by
 
Best answer

Answer provided by @cddr on Slack:

Use .withZone on the DateTimeFormatter itself to provide a timezone, and then the original format works just fine with clojure.data.json:

{:date-formatter (-> (DateTimeFormatter/ofPattern "MMMM, dd yyyy HH:mm:ss Z")
                     (DateTimeFormatter/.withZone ZoneOffset/UTC))}

(or (ZoneId/systemDefault) or similar).

This completely solves the problem, without changes to clojure.data.json.

...