From 9f8c0749d1f465221ac7ca856085619081e6219c Mon Sep 17 00:00:00 2001 From: Sivaraman Viswanathan Date: Mon, 15 Oct 2018 12:41:53 -0700 Subject: [PATCH] #1591 Add support for mapping java.time.LocalDate to java.sql.Date --- .../ap/internal/conversion/Conversions.java | 6 +-- .../JavaLocalDateToSqlDateConversion.java | 53 +++++++++++++++++++ .../java8time/Java8TimeConversionTest.java | 24 +++++++++ .../ap/test/conversion/java8time/Source.java | 10 ++++ .../ap/test/conversion/java8time/Target.java | 10 ++++ 5 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateToSqlDateConversion.java diff --git a/processor/src/main/java/org/mapstruct/ap/internal/conversion/Conversions.java b/processor/src/main/java/org/mapstruct/ap/internal/conversion/Conversions.java index dd8c13cc7..70e04146a 100755 --- a/processor/src/main/java/org/mapstruct/ap/internal/conversion/Conversions.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/conversion/Conversions.java @@ -5,8 +5,6 @@ */ package org.mapstruct.ap.internal.conversion; -import static org.mapstruct.ap.internal.conversion.ReverseConversion.reverse; - import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Time; @@ -16,7 +14,6 @@ import java.util.Currency; import java.util.Date; import java.util.HashMap; import java.util.Map; - import javax.lang.model.util.Elements; import org.mapstruct.ap.internal.model.common.Type; @@ -24,6 +21,8 @@ import org.mapstruct.ap.internal.model.common.TypeFactory; import org.mapstruct.ap.internal.util.JavaTimeConstants; import org.mapstruct.ap.internal.util.JodaTimeConstants; +import static org.mapstruct.ap.internal.conversion.ReverseConversion.reverse; + /** * Holds built-in {@link ConversionProvider}s such as from {@code int} to {@code String}. * @@ -222,6 +221,7 @@ public class Conversions { register( JavaTimeConstants.ZONED_DATE_TIME_FQN, Date.class, new JavaZonedDateTimeToDateConversion() ); register( JavaTimeConstants.LOCAL_DATE_TIME_FQN, Date.class, new JavaLocalDateTimeToDateConversion() ); register( JavaTimeConstants.LOCAL_DATE_FQN, Date.class, new JavaLocalDateToDateConversion() ); + register( JavaTimeConstants.LOCAL_DATE_FQN, java.sql.Date.class, new JavaLocalDateToSqlDateConversion() ); register( JavaTimeConstants.INSTANT, Date.class, new JavaInstantToDateConversion() ); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateToSqlDateConversion.java b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateToSqlDateConversion.java new file mode 100644 index 000000000..29663cbcf --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/conversion/JavaLocalDateToSqlDateConversion.java @@ -0,0 +1,53 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.internal.conversion; + +import java.sql.Date; +import java.util.Set; + +import org.mapstruct.ap.internal.model.common.ConversionContext; +import org.mapstruct.ap.internal.model.common.Type; +import org.mapstruct.ap.internal.util.Collections; + +import static org.mapstruct.ap.internal.conversion.ConversionUtils.sqlDate; +import static org.mapstruct.ap.internal.conversion.ConversionUtils.zoneOffset; +import static org.mapstruct.ap.internal.util.JavaTimeConstants.ZONE_OFFSET_FQN; + +/** + * SimpleConversion for mapping {@link java.time.LocalDate} to + * {@link Date} and vice versa. + */ +public class JavaLocalDateToSqlDateConversion extends SimpleConversion { + + @Override + protected String getToExpression(ConversionContext conversionContext) { + return "new " + sqlDate( conversionContext ) + "( " + + ".atStartOfDay( " + + zoneOffset( conversionContext ) + + ".UTC ).toInstant().toEpochMilli() )"; + } + + @Override + protected Set getToConversionImportTypes(ConversionContext conversionContext) { + return Collections.asSet( + conversionContext.getTypeFactory().getType( Date.class ), + conversionContext.getTypeFactory().getType( ZONE_OFFSET_FQN ) + ); + } + + @Override + protected String getFromExpression(ConversionContext conversionContext) { + return ".toLocalDate()"; + } + + @Override + protected Set getFromConversionImportTypes(ConversionContext conversionContext) { + return Collections.asSet( + conversionContext.getTypeFactory().getType( ZONE_OFFSET_FQN ) + ); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/Java8TimeConversionTest.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/Java8TimeConversionTest.java index d04ae629a..271a8d958 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/Java8TimeConversionTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/Java8TimeConversionTest.java @@ -295,4 +295,28 @@ public class Java8TimeConversionTest { assertThat( source.getForDateConversionWithLocalDate() ).isEqualTo( localDate ); } + + @Test + public void testLocalDateToSqlDateMapping() { + TimeZone.setDefault( TimeZone.getTimeZone( "Australia/Melbourne" ) ); + + Source source = new Source(); + LocalDate localDate = LocalDate.of( 2016, 3, 1 ); + source.setForSqlDateConversionWithLocalDate( localDate ); + + Target target = SourceTargetMapper.INSTANCE.sourceToTargetDefaultMapping( source ); + + assertThat( target.getForSqlDateConversionWithLocalDate() ).isNotNull(); + + Calendar instance = Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ); + instance.setTimeInMillis( target.getForSqlDateConversionWithLocalDate().getTime() ); + + assertThat( instance.get( Calendar.YEAR ) ).isEqualTo( localDate.getYear() ); + assertThat( instance.get( Calendar.MONTH ) ).isEqualTo( localDate.getMonthValue() - 1 ); + assertThat( instance.get( Calendar.DATE ) ).isEqualTo( localDate.getDayOfMonth() ); + + source = SourceTargetMapper.INSTANCE.targetToSource( target ); + + assertThat( source.getForSqlDateConversionWithLocalDate() ).isEqualTo( localDate ); + } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/Source.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/Source.java index 97a8f5b62..886297170 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/Source.java @@ -32,6 +32,8 @@ public class Source { private LocalDate forDateConversionWithLocalDate; + private LocalDate forSqlDateConversionWithLocalDate; + private Instant forDateConversionWithInstant; public ZonedDateTime getZonedDateTime() { @@ -98,6 +100,14 @@ public class Source { this.forDateConversionWithLocalDate = forDateConversionWithLocalDate; } + public LocalDate getForSqlDateConversionWithLocalDate() { + return forSqlDateConversionWithLocalDate; + } + + public void setForSqlDateConversionWithLocalDate(LocalDate forSqlDateConversionWithLocalDate) { + this.forSqlDateConversionWithLocalDate = forSqlDateConversionWithLocalDate; + } + public Instant getForDateConversionWithInstant() { return forDateConversionWithInstant; } diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/Target.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/Target.java index aca6aa22a..eac1603d4 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/Target.java +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/Target.java @@ -29,6 +29,8 @@ public class Target { private Date forDateConversionWithLocalDate; + private java.sql.Date forSqlDateConversionWithLocalDate; + private Date forDateConversionWithInstant; public String getZonedDateTime() { @@ -95,6 +97,14 @@ public class Target { this.forDateConversionWithLocalDate = forDateConversionWithLocalDate; } + public java.sql.Date getForSqlDateConversionWithLocalDate() { + return forSqlDateConversionWithLocalDate; + } + + public void setForSqlDateConversionWithLocalDate(java.sql.Date forSqlDateConversionWithLocalDate) { + this.forSqlDateConversionWithLocalDate = forSqlDateConversionWithLocalDate; + } + public Date getForDateConversionWithInstant() { return forDateConversionWithInstant; }