#1656 Support for mapping between String and java.time Duration, Period, Instant

This commit is contained in:
Taras Mychaskiw 2018-12-08 14:25:42 -05:00 committed by Filip Hrisafov
parent d1fe65dbad
commit 780fd73928
6 changed files with 248 additions and 20 deletions

View File

@ -944,6 +944,8 @@ public interface CarMapper {
* Between `java.time.ZonedDateTime`, `java.time.LocalDateTime`, `java.time.LocalDate`, `java.time.LocalTime` from Java 8 Date-Time package and `String`. A format string as understood by `java.text.SimpleDateFormat` can be specified via the `dateFormat` option (see above).
* Between `java.time.Instant`, `java.time.Duration`, `java.time.Period` from Java 8 Date-Time package and `String` using the `parse` method in each class to map from `String` and using `toString` to map into `String`.
* Between `java.time.ZonedDateTime` from Java 8 Date-Time package and `java.util.Date` where, when mapping a `ZonedDateTime` from a given `Date`, the system default timezone is used.
* Between `java.time.LocalDateTime` from Java 8 Date-Time package and `java.util.Date` where timezone UTC is used as the timezone.

View File

@ -9,10 +9,12 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Currency;
@ -171,8 +173,8 @@ public class Conversions {
registerToStringConversion( Boolean.class );
register( char.class, String.class, new CharToStringConversion() );
register( Character.class, String.class, new CharWrapperToStringConversion() );
register( BigInteger.class, String.class, new BigIntegerToStringConversion( ) );
register( BigDecimal.class, String.class, new BigDecimalToStringConversion( ) );
register( BigInteger.class, String.class, new BigIntegerToStringConversion() );
register( BigDecimal.class, String.class, new BigDecimalToStringConversion() );
registerJodaConversions();
@ -217,6 +219,9 @@ public class Conversions {
register( LocalDate.class, String.class, new JavaLocalDateToStringConversion() );
register( LocalDateTime.class, String.class, new JavaLocalDateTimeToStringConversion() );
register( LocalTime.class, String.class, new JavaLocalTimeToStringConversion() );
register( Instant.class, String.class, new StaticParseToStringConversion() );
register( Period.class, String.class, new StaticParseToStringConversion() );
register( Duration.class, String.class, new StaticParseToStringConversion() );
// Java 8 to Date
register( ZonedDateTime.class, Date.class, new JavaZonedDateTimeToDateConversion() );

View File

@ -0,0 +1,36 @@
/*
* 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.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;
/**
* Handles conversion between a target type <tt>T</tt> and {@link String},
* where {@code T#parse(String)} and {@code T#toString} are inverse operations.
* The {@link ConversionContext#getTargetType()} is used as the from target type <tt>T</tt>.
*/
public class StaticParseToStringConversion extends SimpleConversion {
@Override
protected String getToExpression(ConversionContext conversionContext) {
return "<SOURCE>.toString()";
}
@Override
protected String getFromExpression(ConversionContext conversionContext) {
return conversionContext.getTargetType().createReferenceName() + ".parse( <SOURCE> )";
}
@Override
protected Set<Type> getFromConversionImportTypes(ConversionContext conversionContext) {
return Collections.asSet( conversionContext.getTargetType() );
}
}

View File

@ -5,12 +5,12 @@
*/
package org.mapstruct.ap.test.conversion.java8time;
import static org.assertj.core.api.Assertions.assertThat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
@ -23,6 +23,8 @@ import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for conversions to/from Java 8 date and time types.
*/
@ -99,7 +101,7 @@ public class Java8TimeConversionTest {
Target target = new Target();
target.setZonedDateTime( dateTimeAsString );
ZonedDateTime sourceDateTime =
ZonedDateTime.of( java.time.LocalDateTime.of( 2014, 1, 1, 0, 0 ), ZoneId.of( "UTC" ) );
ZonedDateTime.of( java.time.LocalDateTime.of( 2014, 1, 1, 0, 0 ), ZoneId.of( "UTC" ) );
Source src = SourceTargetMapper.INSTANCE.targetToSourceDateTimeMapped( target );
assertThat( src ).isNotNull();
@ -112,7 +114,7 @@ public class Java8TimeConversionTest {
Target target = new Target();
target.setLocalDateTime( dateTimeAsString );
LocalDateTime sourceDateTime =
LocalDateTime.of( 2014, 1, 1, 0, 0, 0 );
LocalDateTime.of( 2014, 1, 1, 0, 0, 0 );
Source src = SourceTargetMapper.INSTANCE.targetToSourceLocalDateTimeMapped( target );
assertThat( src ).isNotNull();
@ -125,7 +127,7 @@ public class Java8TimeConversionTest {
Target target = new Target();
target.setLocalDate( dateTimeAsString );
LocalDate sourceDate =
LocalDate.of( 2014, 1, 1 );
LocalDate.of( 2014, 1, 1 );
Source src = SourceTargetMapper.INSTANCE.targetToSourceLocalDateMapped( target );
assertThat( src ).isNotNull();
@ -138,7 +140,7 @@ public class Java8TimeConversionTest {
Target target = new Target();
target.setLocalTime( dateTimeAsString );
LocalTime sourceTime =
LocalTime.of( 0, 0 );
LocalTime.of( 0, 0 );
Source src = SourceTargetMapper.INSTANCE.targetToSourceLocalTimeMapped( target );
assertThat( src ).isNotNull();
@ -169,13 +171,14 @@ public class Java8TimeConversionTest {
Source src = SourceTargetMapper.INSTANCE.targetToSource( target );
assertThat( src.getZonedDateTime() ).isEqualTo(
ZonedDateTime.of(
java.time.LocalDateTime.of(
2014,
1,
1,
0,
0 ), ZoneId.of( "UTC" ) ) );
ZonedDateTime.of(
java.time.LocalDateTime.of(
2014,
1,
1,
0,
0
), ZoneId.of( "UTC" ) ) );
assertThat( src.getLocalDateTime() ).isEqualTo( LocalDateTime.of( 2014, 1, 1, 0, 0 ) );
assertThat( src.getLocalDate() ).isEqualTo( LocalDate.of( 2014, 1, 1 ) );
assertThat( src.getLocalTime() ).isEqualTo( LocalTime.of( 0, 0 ) );
@ -186,17 +189,17 @@ public class Java8TimeConversionTest {
Source source = new Source();
ZonedDateTime dateTime = ZonedDateTime.of( LocalDateTime.of( 2014, 1, 1, 0, 0 ), ZoneId.of( "UTC" ) );
source.setForCalendarConversion(
dateTime );
dateTime );
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
assertThat( target.getForCalendarConversion() ).isNotNull();
assertThat( target.getForCalendarConversion().getTimeZone() ).isEqualTo(
TimeZone.getTimeZone(
"UTC" ) );
TimeZone.getTimeZone(
"UTC" ) );
assertThat( target.getForCalendarConversion().get( Calendar.YEAR ) ).isEqualTo( dateTime.getYear() );
assertThat( target.getForCalendarConversion().get( Calendar.MONTH ) ).isEqualTo(
dateTime.getMonthValue() - 1 );
dateTime.getMonthValue() - 1 );
assertThat( target.getForCalendarConversion().get( Calendar.DATE ) ).isEqualTo( dateTime.getDayOfMonth() );
assertThat( target.getForCalendarConversion().get( Calendar.MINUTE ) ).isEqualTo( dateTime.getMinute() );
assertThat( target.getForCalendarConversion().get( Calendar.HOUR ) ).isEqualTo( dateTime.getHour() );
@ -212,7 +215,7 @@ public class Java8TimeConversionTest {
Source source = new Source();
ZonedDateTime dateTime = ZonedDateTime.of( LocalDateTime.of( 2014, 1, 1, 0, 0 ), ZoneId.of( "UTC" ) );
source.setForDateConversionWithZonedDateTime(
dateTime );
dateTime );
Target target = SourceTargetMapper.INSTANCE.sourceToTargetDefaultMapping( source );
assertThat( target.getForDateConversionWithZonedDateTime() ).isNotNull();
@ -319,4 +322,124 @@ public class Java8TimeConversionTest {
assertThat( source.getForSqlDateConversionWithLocalDate() ).isEqualTo( localDate );
}
@Test
public void testInstantToStringMapping() {
Source source = new Source();
source.setForInstantConversionWithString( Instant.ofEpochSecond( 42L ) );
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
String periodString = target.getForInstantConversionWithString();
assertThat( periodString ).isEqualTo( "1970-01-01T00:00:42Z" );
}
@Test
public void testInstantToStringNullMapping() {
Source source = new Source();
source.setForInstantConversionWithString( null );
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
String periodString = target.getForInstantConversionWithString();
assertThat( periodString ).isNull();
}
@Test
public void testStringToInstantMapping() {
Target target = new Target();
target.setForInstantConversionWithString( "1970-01-01T00:00:00.000Z" );
Source source = SourceTargetMapper.INSTANCE.targetToSource( target );
Instant instant = source.getForInstantConversionWithString();
assertThat( instant ).isEqualTo( Instant.EPOCH );
}
@Test
public void testStringToInstantNullMapping() {
Target target = new Target();
target.setForInstantConversionWithString( null );
Source source = SourceTargetMapper.INSTANCE.targetToSource( target );
Instant instant = source.getForInstantConversionWithString();
assertThat( instant ).isNull();
}
@Test
public void testPeriodToStringMapping() {
Source source = new Source();
source.setForPeriodConversionWithString( Period.ofDays( 42 ) );
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
String periodString = target.getForPeriodConversionWithString();
assertThat( periodString ).isEqualTo( "P42D" );
}
@Test
public void testPeriodToStringNullMapping() {
Source source = new Source();
source.setForPeriodConversionWithString( null );
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
String periodString = target.getForPeriodConversionWithString();
assertThat( periodString ).isNull();
}
@Test
public void testStringToPeriodMapping() {
Target target = new Target();
target.setForPeriodConversionWithString( "P1Y2M3D" );
Source source = SourceTargetMapper.INSTANCE.targetToSource( target );
Period period = source.getForPeriodConversionWithString();
assertThat( period ).isEqualTo( Period.of( 1, 2, 3 ) );
}
@Test
public void testStringToPeriodNullMapping() {
Target target = new Target();
target.setForPeriodConversionWithString( null );
Source source = SourceTargetMapper.INSTANCE.targetToSource( target );
Period period = source.getForPeriodConversionWithString();
assertThat( period ).isNull();
}
@Test
public void testDurationToStringMapping() {
Source source = new Source();
source.setForDurationConversionWithString( Duration.ofMinutes( 42L ) );
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
String durationString = target.getForDurationConversionWithString();
assertThat( durationString ).isEqualTo( "PT42M" );
}
@Test
public void testDurationToStringNullMapping() {
Source source = new Source();
source.setForDurationConversionWithString( null );
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
String durationString = target.getForDurationConversionWithString();
assertThat( durationString ).isNull();
}
@Test
public void testStringToDurationMapping() {
Target target = new Target();
target.setForDurationConversionWithString( "PT20.345S" );
Source source = SourceTargetMapper.INSTANCE.targetToSource( target );
Duration duration = source.getForDurationConversionWithString();
assertThat( duration ).isEqualTo( Duration.ofSeconds( 20L, 345000000L ) );
}
@Test
public void testStringToDurationNullMapping() {
Target target = new Target();
target.setForDurationConversionWithString( null );
Source source = SourceTargetMapper.INSTANCE.targetToSource( target );
Duration duration = source.getForDurationConversionWithString();
assertThat( duration ).isNull();
}
}

View File

@ -5,10 +5,12 @@
*/
package org.mapstruct.ap.test.conversion.java8time;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.time.ZonedDateTime;
/**
@ -36,6 +38,12 @@ public class Source {
private Instant forDateConversionWithInstant;
private Instant forInstantConversionWithString;
private Period forPeriodConversionWithString;
private Duration forDurationConversionWithString;
public ZonedDateTime getZonedDateTime() {
return zonedDateTime;
}
@ -115,4 +123,28 @@ public class Source {
public void setForDateConversionWithInstant(Instant forDateConversionWithInstant) {
this.forDateConversionWithInstant = forDateConversionWithInstant;
}
public Instant getForInstantConversionWithString() {
return forInstantConversionWithString;
}
public void setForInstantConversionWithString(Instant forInstantConversionWithString) {
this.forInstantConversionWithString = forInstantConversionWithString;
}
public Period getForPeriodConversionWithString() {
return forPeriodConversionWithString;
}
public void setForPeriodConversionWithString(Period forPeriodConversionWithString) {
this.forPeriodConversionWithString = forPeriodConversionWithString;
}
public Duration getForDurationConversionWithString() {
return forDurationConversionWithString;
}
public void setForDurationConversionWithString(Duration forDurationConversionWithString) {
this.forDurationConversionWithString = forDurationConversionWithString;
}
}

View File

@ -33,6 +33,12 @@ public class Target {
private Date forDateConversionWithInstant;
private String forInstantConversionWithString;
private String forPeriodConversionWithString;
private String forDurationConversionWithString;
public String getZonedDateTime() {
return zonedDateTime;
}
@ -112,4 +118,28 @@ public class Target {
public void setForDateConversionWithInstant(Date forDateConversionWithInstant) {
this.forDateConversionWithInstant = forDateConversionWithInstant;
}
public String getForInstantConversionWithString() {
return forInstantConversionWithString;
}
public void setForInstantConversionWithString(String forInstantConversionWithString) {
this.forInstantConversionWithString = forInstantConversionWithString;
}
public String getForPeriodConversionWithString() {
return forPeriodConversionWithString;
}
public void setForPeriodConversionWithString(String forPeriodConversionWithString) {
this.forPeriodConversionWithString = forPeriodConversionWithString;
}
public String getForDurationConversionWithString() {
return forDurationConversionWithString;
}
public void setForDurationConversionWithString(String forDurationConversionWithString) {
this.forDurationConversionWithString = forDurationConversionWithString;
}
}