Skip to content

Support for implicit conversion between java.time.LocalDate and java.time.LocalDateTime #3199

Description

@belkin1667

Expected behavior

Either LocalDateTime map(LocalDate date) results in compilation error or mapping results in date == null ? null : LocalDateTime.of(date, LocalTime.MIN)

Actual behavior

LocalDateTime map(LocalDate date) maps any date to null

The problem seems to be related to incorrect mapping sequence: LocalDate to XMLGregorianCalendar and XMLGregorianCalendar to LocalDateTime. Separately those mappings are correct, but combined are not:
Generated mapper contains the following line:

LocalDateTime localDateTime = xmlGregorianCalendarToLocalDateTime( localDateToXmlGregorianCalendar( date ) ); 

Generated method xmlGregorianCalendarToLocalDateTime(..) returns null if hours, minutes or seconds are equal to DatatypeConstants.FIELD_UNDEFINED, which they are cause localDateToXmlGregorianCalendar(..) calls javax.xml.datatype.DatatypeFactory::newXMLGregorianCalendarDate which sets hours, minuts, seconds and milliseconds as FIELD_UNDEFINED

Methods I'm talking about for reference:

        private static LocalDateTime xmlGregorianCalendarToLocalDateTime( XMLGregorianCalendar xcal ) {
            if ( xcal == null ) {
                return null;
            }

            if ( xcal.getYear() != DatatypeConstants.FIELD_UNDEFINED
                && xcal.getMonth() != DatatypeConstants.FIELD_UNDEFINED
                && xcal.getDay() != DatatypeConstants.FIELD_UNDEFINED
                && xcal.getHour() != DatatypeConstants.FIELD_UNDEFINED
                && xcal.getMinute() != DatatypeConstants.FIELD_UNDEFINED
            ) { //some mapping }
            return null;
        }
private XMLGregorianCalendar localDateToXmlGregorianCalendar( LocalDate localDate ) {
            if ( localDate == null ) {
                return null;
            }

            return datatypeFactory.newXMLGregorianCalendarDate(
                localDate.getYear(),
                localDate.getMonthValue(),
                localDate.getDayOfMonth(),
                DatatypeConstants.FIELD_UNDEFINED );
        }
    public XMLGregorianCalendar newXMLGregorianCalendarDate(
            final int year,
            final int month,
            final int day,
            final int timezone) {

            return newXMLGregorianCalendar(
                    year,
                    month,
                    day,
                    DatatypeConstants.FIELD_UNDEFINED, // hour
                    DatatypeConstants.FIELD_UNDEFINED, // minute
                    DatatypeConstants.FIELD_UNDEFINED, // second
                    DatatypeConstants.FIELD_UNDEFINED, // millisecond
                    timezone);
            }

Steps to reproduce the problem

Define Mapper:

@Mapper
public interface IssueBelkinmikeMapper {

    IssueBelkinmikeMapper INSTANCE = Mappers.getMapper( IssueBelkinmikeMapper.class );

    LocalDateTime map(LocalDate date);
}

Define Test:

@WithClasses({
    IssueBelkinmikeMapper.class
})
@IssueKey("belkinmike")
class IssueBelkinmikeMapperTest {

    @ProcessorTest
    void throwsException() {
        LocalDate source = LocalDate.of(2022, 2, 2);
        LocalDateTime target = IssueBelkinmikeMapper.INSTANCE.map(source);
        assertThat(target).isNotNull();
    }
}

Test should pass or fail at mapper generation stage, but it is not

IMHO: It should fail at generating such mapping, cause I met this problem mapping dtos:

I had this classes

class EntityDto {
    LocalDate dateFrom;
}
class Entity {
    LocalDate dateFrom;
}

interface MyMapper {
    EntityDto map(Entity e);
}

then dto field's type changed to LocalDateTime:

class EntityDto {
    LocalDateTime dateFrom;
}
class Entity {
    LocalDate dateFrom;
}

interface MyMapper {
    EntityDto map(Entity e);
}

And I would expect mapping to fail and attract my attention to it, but it did not

MapStruct Version

main branch (commit id=a7ba12676d237957be0753076f436d7974c9f7f4)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions