Java 8 date/time support in Morphia

806 views
Skip to first unread message

Justin Lee

unread,
Jun 2, 2016, 2:26:46 PM6/2/16
to mor...@googlegroups.com, mongod...@googlegroups.com

We're finally looking at adding support for certain Java 8 types in Morphia.  There are a number of options for how to encode each type.  We've made an initial pass at it and have an implementation but would like to elicit some feedback before these serialization formats are finalized.  Please look over the information below and see if the formats fit your needs and expectations.  With these implementations, the intent was to provide support for the most common needs.  These new date/time types often track values to nanosecond precision.  Dates in MongoDB do not have such precision and so certain decisions must be made.  In this initial approach, the decision was made to truncate anything below the millisecond level.  Listed below is the current thinking of how to handle each type with some discussion where necessary covering the decisions/tradeoffs being made and some possible options.

  1. Duration -- Duration.toString()
    • This would look like "PT42S" for a duration of 42 seconds.  This makes the serialized format easily readable and parsable.
    • Another option would be to serialize in to a numeric form of <seconds><millis>.  So for the example of a 42s duration, we'd end up with 42000 in the database (42 seconds and 000 millis).  While this form loses a little bit of readability (just how long is 43429 seconds?) it does mean that durations are range queryable (find all where the duration < 12 hours).
  2. Instant -- converted to java.util.Date
  3. LocalDate -- converted to java.util.Date with the time set to midnight
  4. LocalDateTime -- converted to java.util.Date
  5. LocalTime  --  hhmmss<millis>
    • This type literally tracks the wall clock time.  There is no month/day information so this is being encoded in the triple pair of <hours><minutes><seconds> which have been left-shifted to make room for the milliseconds value.  This means a LocalTime of 12:30:45 will be encoded to a value of 123045000.  With a 0 value for the milliseconds, you can see first 6 digits correspond to the hour/minute/seconds values.
    • Another option would be to convert this to a Date corresponding to this time on 1/1/1970.  A touch more readable but the month/day/year values might be confusing.  This also makes it comparable with a Date instance but care would have to be take to make sure that Date instance was on the correct day.
  6. Period -- Period.toString()
    • Similar to Duration, this would look like "P3M12D" for a Period of 3 months and 12 days.
    • The same considerations and caveats apply here as with Duration.
  7. Year -- just the number
  8. YearMonth -- encoded number in the form of yyyyMM
    • This type is just a year/month pair and is simply encoded as such.
Getting these formats is important since changing them once users rely on them is incredibly difficult.  Also, we'd love feedback on if these serializers are even necessary.  We're trying to provide coverage for the common types but some of these might not be necessary.  Your feedback is greatly appreciated.  Thanks.
--------------------------------

name     : "Justin Lee", 
  title    : "Software Engineer",
  twitter  : "@evanchooly",
  web      : [ "mongodb.com", "antwerkz.com" ],
  location : "New York, NY" }

Justin Lee

unread,
Jun 15, 2016, 8:51:57 AM6/15/16
to Morphia, mongod...@googlegroups.com
I saw an interesting option on a StackOverflow question that I was mildly embarrassed to see hadn't occurred to me.  If you just pass a YearMonth instance to the driver it will be serialized out as
{ "year" : 1988, "month" : 10 } 

Now, there's currently no Codec support in the driver for Java 8 date/time either so there's no way to get that back out.  But it occurred to me that it could be more useful to store YearMonth this was as it would make grouping by year or month much easier.  It would make range queries a bit trickier, though, so it's a bit of a toss up.


On Monday, June 13, 2016 at 3:02:11 PM UTC-4, Justin Lee wrote:
My initial implementation went that route but it was surprising to those who saw it.  What was in the database didn't match the expectations set by what was in the Java code.  This particular approach preserves those expectations and leave open the option of custom converters/codecs for those who need the great precision.  That's the reasoning so far, at least.

--------------------------------

name     : "Justin Lee", 
  title    : "Software Engineer",
  twitter  : "@evanchooly",
  web      : [ "mongodb.com", "antwerkz.com" ],
  location : "New York, NY" }

On Fri, Jun 3, 2016 at 3:03 AM, Ulrich Cech <devel...@gmail.com> wrote:

Basically, I think we should keep the accuracy/precision of the new Time-API, so no compromisses on truncating the nanos or other changes to the original value. The toString()-representation of all units can easyly parsed back to the corresponding classes.

But I see the use-case for using the values for calculation.
So, perhaps, we can introduce some Annotation like the JPA-TemporalType, so that we can control, if the value is stored as string (and is parsed back with the exact value) or as Date for calculation (without the nanos).
Reply all
Reply to author
Forward
0 new messages