I want my auditable (@CreatedDate
and @LastModifiedDate
) MongoDB document to work with ZonedDateTime
fields.
Apparently this type is not supported by Spring Data (have a look at org.springframework.data.auditing.AnnotationAuditingMetadata
).
Framework version: Spring Boot 2.0.0 and Spring Data MongoDB 2.0.0
java.lang.IllegalArgumentException: Invalid date type for member <MEMBER NAME>!
Supported types are [org.joda.time.DateTime, org.joda.time.LocalDateTime, java.util.Date, java.lang.Long, long].
@Configuration
@EnableMongoAuditing
public class MongoConfiguration {
}
public abstract class BaseDocument {
@CreatedDate
private ZonedDateTime createdDate;
@LastModifiedDate
private ZonedDateTime lastModifiedDate;
}
I also tried creating a custom converter for ZonedDateTime
, but it is not considered by Spring Data. The class DateConvertingAuditableBeanWrapper
has a ConversionService
which is configured in the constructor method with JodaTimeConverters
, Jsr310Converters
and ThreeTenBackPortConverters
.
@Component
public class LocalDateTimeToZonedDateTimeConverter implements Converter<LocalDateTime, ZonedDateTime> {
@Override
public ZonedDateTime convert(LocalDateTime source) {
return source.atZone(ZoneId.systemDefault());
}
}
class DefaultAuditableBeanWrapperFactory implements AuditableBeanWrapperFactory {
abstract static class DateConvertingAuditableBeanWrapper implements AuditableBeanWrapper {
private final ConversionService conversionService;
}
}
Is it possible to audit ZonedDateTime
fields?
How can I register a converter?
Create a DateTimeProvider
to provide the current time to be used when auditing:
@Component("dateTimeProvider")
public class CustomDateTimeProvider implements DateTimeProvider {
@Override
public Optional<TemporalAccessor> getNow() {
return Optional.of(ZonedDateTime.now());
}
}
And then:
DateTimeProvider
component in the @EnableMongoAuditing
annotation;Converter
s for Date
and ZonedDateTime
;Converter
instances to a MongoCustomConversions
instance;MongoCustomConversions
instance as a @Bean
.@Configuration
@EnableMongoAuditing(dateTimeProviderRef = "dateTimeProvider")
public class MongoConfiguration {
@Bean
public MongoCustomConversions customConversions() {
List<Converter<?, ?>> converters = new ArrayList<>();
converters.add(new DateToZonedDateTimeConverter());
converters.add(new ZonedDateTimeToDateConverter());
return new MongoCustomConversions(converters);
}
class DateToZonedDateTimeConverter implements Converter<Date, ZonedDateTime> {
@Override
public ZonedDateTime convert(Date source) {
return source == null ? null :
ZonedDateTime.ofInstant(source.toInstant(), ZoneId.systemDefault());
}
}
class ZonedDateTimeToDateConverter implements Converter<ZonedDateTime, Date> {
@Override
public Date convert(ZonedDateTime source) {
return source == null ? null : Date.from(source.toInstant());
}
}
}
I wouldn't, however, use ZonedDateTime
for this purpose. I would stick to OffsetDateTime
:
OffsetDateTime
,ZonedDateTime
andInstant
all store an instant on the time-line to nanosecond precision. Instant is the simplest, simply representing the instant.OffsetDateTime
adds to the instant the offset from UTC/Greenwich, which allows the local date-time to be obtained.ZonedDateTime
adds full time-zone rules.It is intended that
ZonedDateTime
orInstant
is used to model data in simpler applications. This class may be used when modeling date-time concepts in more detail, or when communicating to a database or in a network protocol.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With