Using OffsetDateTime with Spring Boot and MongoDB

MongoDB natively supports Date as a field type, but here only a time is stored without time zone or offset. Using a converter we can support OffsetDateTime directly in our Spring Boot application and persist it as a custom type with date and offset.

If we save a document with an OffsetDateTime without a converter, we get the following error message.

org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class java.time.OffsetDateTime.

In order to persist our date without loss and also restore it when reading from MongoDB, we store time and offset separately in a custom type. For this we need the following converters.

public class MongoOffsetDateTimeReader implements Converter<Document, OffsetDateTime> {

    @Override
    public OffsetDateTime convert(final Document document) {
        final Date dateTime = document.getDate(MongoOffsetDateTimeWriter.DATE_FIELD);
        final ZoneOffset offset = ZoneOffset.of(document.getString(MongoOffsetDateTimeWriter.OFFSET_FIELD));
        return OffsetDateTime.ofInstant(dateTime.toInstant(), offset);
    }

}

Converter for reading OffsetDateTime from MongoDB

public class MongoOffsetDateTimeWriter implements Converter<OffsetDateTime, Document> {

    public static final String DATE_FIELD = "dateTime";
    public static final String OFFSET_FIELD = "offset";

    @Override
    public Document convert(final OffsetDateTime offsetDateTime) {
        final Document document = new Document();
        document.put(DATE_FIELD, Date.from(offsetDateTime.toInstant()));
        document.put(OFFSET_FIELD, offsetDateTime.getOffset().toString());
        return document;
    }

}

Converter for writing OffsetDateTime to MongoDB

By providing a MongoCustomConversions bean in our configuration, these are made available in the application context and automatically picked up by Spring Data MongoDB. So our original error message is gone and we can use OffsetDateTime in our documents without worrying about their way of persistence! This approach can be adapted to work with ZonedDateTime as well.

@Configuration
public class MongoConfig {

    // ...

    @Bean
    public MongoCustomConversions mongoCustomConversions() {
        return new MongoCustomConversions(Arrays.asList(
                new MongoOffsetDateTimeWriter(),
                new MongoOffsetDateTimeReader()
        ));
    }

}

Providing the converters in our config

Using Bootify, a Spring Boot application for MongoDB can be generated in the Free plan without registration, including the documents, fields and relations. The converters are also pre-configured if at least one field is to be persisted with OffsetDateTime. In the Professional plan, Mongock is available to create collections together with a JSON schema for basic validation.

» Start Project on Bootify.io