ZonedDateTime with MongoDB

Gurkha :

Trying to use ZonedDateTime with MongoDB. I'm able to save ZonedDateTime in MongoDB but when i look at the record it has so much unnecessary stuffs in there:

> "timestamp" : {
>             "dateTime" : ISODate("2016-12-13T13:45:53.991Z"),
>             "offset" : {
>                 "_id" : "-05:00",
>                 "totalSeconds" : -18000
>             },
>             "zone" : {
>                 "_class" : "java.time.ZoneRegion",
>                 "_id" : "America/New_York",
>                 "rules" : {
>                     "standardTransitions" : [ 
>                         NumberLong(-2717650800)
>                     ],
>                     "standardOffsets" : [ 
>                         {
>                             "_id" : "-04:56:02",
>                             "totalSeconds" : -17762
>                         }, 
>                         {
>                             "_id" : "-05:00",
>                             "totalSeconds" : -18000
>                         }
>                     ],
>                     "savingsInstantTransitions" : [ 
>                         NumberLong(-2717650800), 
>                         NumberLong(-1633280400), 
>                         NumberLong(-1615140000), 
>                         NumberLong(-1601830800), 
>                         NumberLong(-1583690400), 
>                         NumberLong(-1570381200),
> and so on....

Also when i try to retrieve this same date, it gives me following:

> org.springframework.data.mapping.model.MappingException: No property
> null found on entity class java.time.ZonedDateTime to bind constructor
> parameter to!

I didn't have this problem when working with LocalDateTime. First question is can we change some settings somewhere that will only persist ISODate with ZonedDateTime? Second question, is there something like Jsr310JpaConverters for mongodb?

UPDATE: Referencing the following questionaire I created custom converters and registered them,however, the issue still persists. Spring Data MongoDB with Java 8 LocalDate MappingException

public class ZonedDateTimeToLocalDateTimeConverter implements Converter<ZonedDateTime, LocalDateTime> {
    @Override
    public LocalDateTime convert(ZonedDateTime source) {
        return source == null ? null : LocalDateTime.ofInstant(source.toInstant(), ZoneId
                .systemDefault());
    }
}

And

public class LocalDateTimeToZonedDateTimeConverter implements Converter<LocalDateTime,
        ZonedDateTime> {
    @Override
    public ZonedDateTime convert(LocalDateTime source) {
        return source == null ? null : ZonedDateTime.of(source, ZoneId.systemDefault());
    }
}

Registered them as follows:

@Bean
public CustomConversions customConversions(){
        List<Converter<?,?>> converters = new ArrayList<Converter<?,?>>();
        converters.add(new ZonedDateTimeToLocalDateTimeConverter());
        converters.add(new LocalDateTimeToZonedDateTimeConverter());
        return new CustomConversions(converters);
    }

@Bean
public MongoTemplate getMongoTemplate() throws UnknownHostException {
        MappingMongoConverter converter = new MappingMongoConverter(
                new DefaultDbRefResolver(getMongoDbFactory()), new MongoMappingContext());
        converter.setCustomConversions(customConversions());
        converter.afterPropertiesSet();
        return new MongoTemplate(getMongoDbFactory(), converter);
    }
Sagar Veeram :

Looks like Spring has support for all the java time converter minus zoned date time converter. You can register one as follows.

@Bean
public CustomConversions customConversions(){
    List<Converter<?,?>> converters = new ArrayList<Converter<?,?>>();
    converters.add(new DateToZonedDateTimeConverter());
    converters.add(new ZonedDateTimeToDateConverter());
    return new CustomConversions(converters);
}

@Bean
public MongoTemplate getMongoTemplate() throws UnknownHostException {
    MappingMongoConverter converter = new MappingMongoConverter(
            new DefaultDbRefResolver(getMongoDbFactory()), new MongoMappingContext());
    converter.setCustomConversions(customConversions());
    converter.afterPropertiesSet();
    return new MongoTemplate(getMongoDbFactory(), converter);
}

class DateToZonedDateTimeConverter implements Converter<Date, ZonedDateTime> {

     @Override
     public ZonedDateTime convert(Date source) {
              return source == null ? null : ofInstant(source.toInstant(), systemDefault());
         }
     }

class ZonedDateTimeToDateConverter implements Converter<ZonedDateTime, Date> {

    @Override
    public Date convert(ZonedDateTime source) {
             return source == null ? null : Date.from(source.toInstant());
       }
   }

One other alternative solution would be to just use the ZonedDateTime and change it to date while persisting into MongoDB. You can easily change it back from date back to Zoned Date Time while fetching.

Below are the relavant methods to help with conversions.

ZoneId zoneID = ZoneId.of("America/Chicago");

From ZonedDateTime to java util date.

Instant instant = Instant.now();
ZonedDateTime zonedDateTime = instant.atZone(zoneId);
Date date = Date.from(zdt.toInstant());

From Date to ZonedDateTime

Instant instant = date.toInstant();
ZonedDateTime zonedDateTime = instant.atZone(zoneId);

The other alternative is to implement custom codec to help with conversions. I've created one for YearMonth at Filtering YearMonth from Mongo document. I'll leave it as exercise to the reader if they want to create custom codec for Zoned Date Time.

You can use below library for codec based approach.

https://github.com/ylemoigne/mongo-jackson-codec

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=454150&siteId=1