Search code examples
javadozermodelmapper

How to map LocalDate to Date using Dozer or ModelMapper?


How to properly setup mapping of either Dozer 6.4.1 or ModelMapper 2.2.0 to successfuly map java.time.LocalDate field to java.util.Date field and vice versa?

Consider these classes:

public class Foo {
    private LocalDate signatureDate;
    // getters and setters
}

public class Bar {
    private Date signatureDate;
    // getters and setters
}

Then calling mapper.map(fooInstance, Bar.class); won't work.

I've tried creating and registering custom converters. Using Dozer, I created class LocalDateToDateConverter that extends DozerConverter<LocalDate, Date> and implemented correct conversion. Then registered it like this:

mapper = DozerBeanMapperBuilder
        .create()
        .withCustomConverter(new LocalDateToDateConverter())
        .build();

but the com.github.dozermapper.core.converters.DateConverter is used instead when it comes to converting the class.

Also it's worth noting, that I would like a generic solution for all classes that may need this type conversion, so that I don't have to make converter for each class.


Solution

  • Using model mapper you can configure converters between Date and LocalDate for Bar and Foo classes.

    Converters:

    private static final Converter<Date, LocalDate> DATE_TO_LOCAL_DATE_CONVERTER = mappingContext -> {
        Date source = mappingContext.getSource();
        return source.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    };
    
    private static final Converter<LocalDate, Date> LOCAL_DATE_TO_DATE_CONVERTER = mappingContext -> {
        LocalDate source = mappingContext.getSource();
        return Date.from(source.atStartOfDay(ZoneId.systemDefault()).toInstant());
    };
    

    Mapper configuration:

    ModelMapper mapper = new ModelMapper();
    
    TypeMap<Bar, Foo> barToFooMapping = mapper.createTypeMap(Bar.class, Foo.class);
    barToFooMapping.addMappings(mapping -> mapping.using(DATE_TO_LOCAL_DATE_CONVERTER).map(Bar::getSignatureDate, Foo::setSignatureDate));
    TypeMap<Foo, Bar> fooToBarMapping = mapper.createTypeMap(Foo.class, Bar.class);
    fooToBarMapping.addMappings(mapping -> mapping.using(LOCAL_DATE_TO_DATE_CONVERTER).map(Foo::getSignatureDate, Bar::setSignatureDate));
    

    Please pay attention to the timezones while converting Date to LocalDate and LocalDate to Date.