Skip to content

JSTEP 5

Michael O'Keeffe edited this page Oct 13, 2020 · 12 revisions

(Back to JSTEP page)


Unify Date/Time handling

(across) formats, defaults across JDK Classic, Joda and Java 8 date/time)

Related implementation issues:

  • to be added -

Author

Tatu Saloranta (@cowtowncoder)

Version history

2020-09-11: added a note about the possibility of adding serializers/deserializers

2020-06-16: adding a few additional notes from bug reports

2020-03-03: first skeletal revision

Background

Both implementation and configuration aspects of 3 main date/time libraries/implementations:

  • "Classic" JDKL java.util.Date, java.util.Calendar (and formatting helpers)
  • Joda date/time
  • Java 8 date/time (java.time) types

differ in many ways, especially regarding default handling, but also with respect to features supported.

It would be important to try to unify default configuration settings and configurability options, features supported.

Challenges

In no particular order:

  1. Mapper/Serialization/DeserializationFeature settings both too simple (on/off) and meant as datatype-agnostic to be sufficient for all configuration needs
  2. Format strings used for JDK-Classic/Joda/Java8-DateTime may differ (i.e. same format string not applicable to all), but @JsonFormat (and related Config Overrides) used interchangeably (can use per-type overrides, but global default would be same; documentation gets tricky)
  3. There are also obvious challenges in how to apply different configuration settings (and if possible, allow layered configuration from global/per-type/per-property) that may be overlapping or even conflicting.
  4. There is also the question of which settings are per-mapper, immutable during use, and which need to be per-call changeable (DeserializationFeature is one of limited number of things that can be changed in this way).

Proposal

No concrete proposal yet.

Preliminary thoughts

@JsonFormat extension?

Since one concrete problem is that of unit of timestamp:

  • Java "classic": milliseconds since epoch (1970-01-01T00:00Z)
  • Unix seconds since epoch
  • Java 8 nanoseconds since... something?

Would it make sense to add unit (or timeUnit) property for @JsonFormat?

On one hand, it is bit datatype-specific, but there is one big benefit: ability to set format defaults, and overrides (both programmatically and via annotations) would make implementation relatively easy

Note that, related to this, for a proposed fix for DurationDeserializer, the plan is to add support for "pattern" in JsonFormat, so that support could be extended to other types. See issue #184.

@JsonFormat(pattern = "h")

DateTimeConfig

With 2.10 and later, ObjectMapper configuration is vastly improved by "Builder" style construction. This would make it easier to add richer configuration options: specifically, while [De]SerializationFeature on/off options are simple, their use does not work well with multiple-options/choices case.

So maybe we should consider datatype-specific Config object like DateTimeConfig?

The idea is to create subset of Date/Time-specific settings, possibly including simple on/off features (DateTimeConfig.Feature.xxx), but not limited to just on/off settings.

What we probably should start doing is to collect kinds of things that need configuring. Coercion settings would be one such feature/aspect. See the date-time-config label for related bugs.

Adding a new Serializer/Deserializer

Perhaps a guiding principle should be "Use the right type for your data", i.e.

If timezone information is to be used, proper type -- "zoned" date/time -- needs to be used Cowtowncoder)

Advantages

This idea was sparked by a solution to Allow Instant to be serialized as epochSecond without the fraction part where, instead of requiring a new [De]SerializationFeature or an annotation, a _new _serializer was added by extending JsonSerializer. This helps address issue #3 above, i.e. using the proper type helps keep the classes consistent and avoids unnecessary complexity, and even bugs, as in the case where one change inadvertently causes something else to break. As an example, see Deserialization of timestamps with UTC timezone to LocalDateTime doesn't yield correct time where @erwich explains a particular test case to illustrate how a previous fix can, in certain cases, cause incorrect values to be parsed.

Disadvantages

Of course, the Java 8 Date/Time library was designed to be extended so this solution is already there and available, but (unless included in the date time module) requires some work on the part of the implementer to add the class, and then additional work if the interface changes in a later Jackson release.

This solution should be used with care as right now, the Date/Time module is mostly aligned with the existing Java classes and this could fall into the trap of a proliferation / explosion of new serializers/deserializers, and further run into the issue of consistency, i.e. do I solve this via an annotation, a [De]SerializationFeature on/off switch, or am I using the wrong type completely?

Clone this wiki locally