Could data.json support dates?
Cheshire provides default formatting for dates out of the box. data.json does not, and just throws an exception.
java.util.Date can easily be converted and formatted that way, but you also need to be careful about java.sql.Date – which Cheshire supports out of the box – but which cannot be directly converted to a java.time.Instant – throwing UnsupportedOperationException because SQL DATEs have no time component.
Our solution at work was to go to a LocalDate and then .atStartOfDay with (java.time.ZoneId/systemDefault) to get to something you can format as an instant.
Do nothing, let the consumer implement a :value-fn which does the transformation.
Teach data.json how to handle dates
Doing nothing is the easiest case for the maintainers of data.json, but does put a burden on all consumers, and it might be assumed that writing dates is a normal use case when writing json.
Teach data.json to handle dates
Seemingly both simple and easy, but javas date and time handling has evolved over time. As outlined below, there are some corner cases to be considered. There are also problems in providing useful defaults, but still letting the user override these as she pleases.
The proposed solution basically follows what outlined in the original issue:
Base everything off java.time.Instant
Convert java.sql.Date to java.time.Instant by using a default-sql-date->instant-fn which goes via a LocalDate and its .atStartOfDay
Add :date-formatter which accepts a DateTimeFormatter , with a default of DateTimeFormatter/ISO_INSTANT
Add :sql-date-converter, an option to override default-sql-date->instant-fn
Nice that the new time formatter stuff properly handles java.sql.Timestamp nanos now.
The data.json test suite passes here in California and I ran our full test suite at work using the patched data.json and with our :value-fn changed to identity (it otherwise handles both dates and UUIDs). The place where we provide a custom formatter required the formatter to be wrapped in .withZone (with either UTC or the system default – tested with both). I did not test with java.sql.Timestamp.
I think the docs need to be clear about which date/time types are supported out of the box and what TZ is used for any conversions. An example of a TZ-sensitive formatter should also be provided, demonstrating the need for .withZone such as:
The patch looks good from my p.o.v.
I’d really appreciate it if you had a thorough look through this patch (and maybe took it for a spin). Especially the tests, since even though I’ve tried to write them TZ-agnostic, I might just not have succeeded in that.