Skip to content

JSTEP 5

Tatu Saloranta edited this page Jun 2, 2024 · 12 revisions

(Back to JSTEP page)


Unify Date/Time handling

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

Author

Tatu Saloranta (@cowtowncoder)

Version history

  • 2022-09-18: minor changes
  • 2021-02-01: add example of the kinds of things that need configuring.
  • 2020-10-13: add idea about JsonFormat pattern.
  • 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

Status

No progress as of Jackson 2.18; not yet started.

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")

DateTimeFeature

With 2.14 and later, a new DatatypeFeature functionality was introduced (originally with JsonNodeFeature and EnumFeature). This makes it easy to add further feature sets, specifically DateTimeFeature, with minimal code changes and convenient if simple global default configurability specific to Date/Time value types.

What we probably should start doing is to collect kinds of things that need configuring. Coercion settings would be one such feature/aspect.

Examples:

  • Allow the year format to be configurable, for example setting the format to 'uuuu' (year) instead of 'yyyy' (year-of-era). This would only affect cases where defaults are not overridden by annotation or config overrides for types.

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?

Related

JSTEP-2 proposes some changes to DeserializationFeatures relevant for Date/Time handling. We may consider alternatively moving some of those features under DateTimeFeatures.

Clone this wiki locally