diff --git a/src/main/java/io/ebean/config/JsonConfig.java b/src/main/java/io/ebean/config/JsonConfig.java index bb745cac7..2ee2996d4 100644 --- a/src/main/java/io/ebean/config/JsonConfig.java +++ b/src/main/java/io/ebean/config/JsonConfig.java @@ -5,6 +5,22 @@ package io.ebean.config; */ public abstract class JsonConfig { + /** + * Defined the format used for Date types. + */ + public enum Date { + + /** + * Format as epoch millis. + */ + MILLIS, + + /** + * Format as ISO-8601 date format. + */ + ISO8601 + } + /** * Defined the format used for DateTime types. */ diff --git a/src/main/java/io/ebean/config/ServerConfig.java b/src/main/java/io/ebean/config/ServerConfig.java index 9b394a03e..4b8fbbfc8 100644 --- a/src/main/java/io/ebean/config/ServerConfig.java +++ b/src/main/java/io/ebean/config/ServerConfig.java @@ -171,6 +171,11 @@ public class ServerConfig { */ private JsonConfig.DateTime jsonDateTime = JsonConfig.DateTime.MILLIS; + /** + * The JSON format used for Date types. Default to millis. + */ + private JsonConfig.Date jsonDate = JsonConfig.Date.MILLIS; + /** * For writing JSON specify if null values or empty collections should be exluded. * By default all values are included. @@ -683,6 +688,20 @@ public class ServerConfig { this.jsonDateTime = jsonDateTime; } + /** + * Return the JSON format used for Date types. + */ + public JsonConfig.Date getJsonDate() { + return jsonDate; + } + + /** + * Set the JSON format to use for Date types. + */ + public void setJsonDate(JsonConfig.Date jsonDate) { + this.jsonDate = jsonDate; + } + /** * Return the JSON include mode used when writing JSON. */ @@ -2988,12 +3007,8 @@ public class ServerConfig { queryBatchSize = p.getInt("queryBatchSize", queryBatchSize); jsonInclude = p.getEnum(JsonConfig.Include.class, "jsonInclude", jsonInclude); - String jsonDateTimeFormat = p.get("jsonDateTime", null); - if (jsonDateTimeFormat != null) { - jsonDateTime = JsonConfig.DateTime.valueOf(jsonDateTimeFormat); - } else { - jsonDateTime = JsonConfig.DateTime.MILLIS; - } + jsonDateTime = p.getEnum(JsonConfig.DateTime.class, "jsonDateTime", jsonDateTime); + jsonDate = p.getEnum(JsonConfig.Date.class, "jsonDate", jsonDate); ddlGenerate = p.getBoolean("ddl.generate", ddlGenerate); ddlRun = p.getBoolean("ddl.run", ddlRun); diff --git a/src/main/java/io/ebeaninternal/server/type/DefaultTypeFactory.java b/src/main/java/io/ebeaninternal/server/type/DefaultTypeFactory.java index 8d669aed6..77a69ae21 100644 --- a/src/main/java/io/ebeaninternal/server/type/DefaultTypeFactory.java +++ b/src/main/java/io/ebeaninternal/server/type/DefaultTypeFactory.java @@ -79,27 +79,24 @@ public class DefaultTypeFactory { /** * Create the default ScalarType for java.util.Date. */ - public ScalarType createUtilDate(JsonConfig.DateTime mode) { + public ScalarType createUtilDate(JsonConfig.DateTime mode, JsonConfig.Date jsonDate) { // by default map anonymous java.util.Date to java.sql.Timestamp. - // String mapType = - // properties.getProperty("type.mapping.java.util.Date","timestamp"); int utilDateType = getTemporalMapType("timestamp"); - - return createUtilDate(mode, utilDateType); + return createUtilDate(mode, jsonDate, utilDateType); } /** * Create a ScalarType for java.util.Date explicitly specifying the type to * map to. */ - public ScalarType createUtilDate(JsonConfig.DateTime mode, int utilDateType) { + public ScalarType createUtilDate(JsonConfig.DateTime jsonDateTime, JsonConfig.Date jsonDate, int utilDateType) { switch (utilDateType) { case Types.DATE: - return new ScalarTypeUtilDate.DateType(); + return new ScalarTypeUtilDate.DateType(jsonDate); case Types.TIMESTAMP: - return new ScalarTypeUtilDate.TimestampType(mode); + return new ScalarTypeUtilDate.TimestampType(jsonDateTime); default: throw new RuntimeException("Invalid type " + utilDateType); diff --git a/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java b/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java index ca630c36f..24c11e2b0 100644 --- a/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java +++ b/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java @@ -130,8 +130,6 @@ public final class DefaultTypeManager implements TypeManager { private final ScalarType timeType = new ScalarTypeTime(); - private final ScalarType dateType = new ScalarTypeDate(); - private final ScalarType urlType = new ScalarTypeURL(); private final ScalarType uriType = new ScalarTypeURI(); private final ScalarType localeType = new ScalarTypeLocale(); @@ -143,6 +141,7 @@ public final class DefaultTypeManager implements TypeManager { private final ScalarType classType = new ScalarTypeClass(); private final JsonConfig.DateTime jsonDateTime; + private final JsonConfig.Date jsonDate; private final Object objectMapper; @@ -189,6 +188,7 @@ public final class DefaultTypeManager implements TypeManager { this.java7Present = config.getClassLoadConfig().isJava7Present(); this.jsonDateTime = config.getJsonDateTime(); + this.jsonDate = config.getJsonDate(); this.typeMap = new ConcurrentHashMap<>(); this.nativeMap = new ConcurrentHashMap<>(); this.logicalMap = new ConcurrentHashMap<>(); @@ -205,9 +205,9 @@ public final class DefaultTypeManager implements TypeManager { this.defaultEnumType = config.getDefaultEnumType(); - initialiseStandard(jsonDateTime, config); - initialiseJavaTimeTypes(jsonDateTime, config); - initialiseJodaTypes(jsonDateTime, config); + initialiseStandard(config); + initialiseJavaTimeTypes(config); + initialiseJodaTypes(config); initialiseJacksonTypes(config); loadTypesFromProviders(config, objectMapper); @@ -522,7 +522,7 @@ public final class DefaultTypeManager implements TypeManager { } // a util Date with jdbcType not matching server wide settings if (type.equals(java.util.Date.class)) { - return extraTypeFactory.createUtilDate(jsonDateTime, jdbcType); + return extraTypeFactory.createUtilDate(jsonDateTime, jsonDate, jdbcType); } // a Calendar with jdbcType not matching server wide settings if (type.equals(java.util.Calendar.class)) { @@ -874,7 +874,7 @@ public final class DefaultTypeManager implements TypeManager { } } - private void initialiseJavaTimeTypes(JsonConfig.DateTime mode, ServerConfig config) { + private void initialiseJavaTimeTypes(ServerConfig config) { if (java7Present) { typeMap.put(java.nio.file.Path.class, new ScalarTypePath()); @@ -883,16 +883,16 @@ public final class DefaultTypeManager implements TypeManager { if (config.getClassLoadConfig().isJavaTimePresent()) { logger.debug("Registering java.time data types"); addType(java.time.Period.class, new ScalarTypePeriod()); - addType(java.time.LocalDate.class, new ScalarTypeLocalDate()); - addType(java.time.LocalDateTime.class, new ScalarTypeLocalDateTime(mode)); - addType(OffsetDateTime.class, new ScalarTypeOffsetDateTime(mode)); - addType(ZonedDateTime.class, new ScalarTypeZonedDateTime(mode)); - addType(Instant.class, new ScalarTypeInstant(mode)); + addType(java.time.LocalDate.class, new ScalarTypeLocalDate(jsonDate)); + addType(java.time.LocalDateTime.class, new ScalarTypeLocalDateTime(jsonDateTime)); + addType(OffsetDateTime.class, new ScalarTypeOffsetDateTime(jsonDateTime)); + addType(ZonedDateTime.class, new ScalarTypeZonedDateTime(jsonDateTime)); + addType(Instant.class, new ScalarTypeInstant(jsonDateTime)); addType(DayOfWeek.class, new ScalarTypeDayOfWeek()); addType(Month.class, new ScalarTypeMonth()); addType(Year.class, new ScalarTypeYear()); - addType(YearMonth.class, new ScalarTypeYearMonthDate()); + addType(YearMonth.class, new ScalarTypeYearMonthDate(jsonDate)); addType(MonthDay.class, new ScalarTypeMonthDay()); addType(OffsetTime.class, new ScalarTypeOffsetTime()); addType(ZoneId.class, new ScalarTypeZoneId()); @@ -915,16 +915,16 @@ public final class DefaultTypeManager implements TypeManager { * Detect if Joda classes are in the classpath and if so register the Joda data types. */ @SuppressWarnings("deprecation") - private void initialiseJodaTypes(JsonConfig.DateTime mode, ServerConfig config) { + private void initialiseJodaTypes(ServerConfig config) { // detect if Joda classes are in the classpath if (config.getClassLoadConfig().isJodaTimePresent()) { // Joda classes are in the classpath so register the types logger.debug("Registering Joda data types"); - addType(LocalDateTime.class, new ScalarTypeJodaLocalDateTime(mode)); - addType(DateTime.class, new ScalarTypeJodaDateTime(mode)); - addType(LocalDate.class, new ScalarTypeJodaLocalDate()); - addType(org.joda.time.DateMidnight.class, new ScalarTypeJodaDateMidnight()); + addType(LocalDateTime.class, new ScalarTypeJodaLocalDateTime(jsonDateTime)); + addType(DateTime.class, new ScalarTypeJodaDateTime(jsonDateTime)); + addType(LocalDate.class, new ScalarTypeJodaLocalDate(jsonDate)); + addType(org.joda.time.DateMidnight.class, new ScalarTypeJodaDateMidnight(jsonDate)); addType(org.joda.time.Period.class, new ScalarTypeJodaPeriod()); String jodaLocalTimeMode = config.getJodaLocalTimeMode(); @@ -944,7 +944,7 @@ public final class DefaultTypeManager implements TypeManager { * Register all the standard types supported. This is the standard JDBC types * plus some other common types such as java.util.Date and java.util.Calendar. */ - private void initialiseStandard(JsonConfig.DateTime mode, ServerConfig config) { + private void initialiseStandard(ServerConfig config) { DatabasePlatform databasePlatform = config.getDatabasePlatform(); int platformClobType = databasePlatform.getClobDbType(); @@ -952,10 +952,10 @@ public final class DefaultTypeManager implements TypeManager { nativeMap.put(DbPlatformType.HSTORE, hstoreType); - ScalarType utilDateType = extraTypeFactory.createUtilDate(mode); + ScalarType utilDateType = extraTypeFactory.createUtilDate(jsonDateTime, jsonDate); addType(java.util.Date.class, utilDateType); - ScalarType calType = extraTypeFactory.createCalendar(mode); + ScalarType calType = extraTypeFactory.createCalendar(jsonDateTime); addType(Calendar.class, calType); ScalarType mathBigIntType = extraTypeFactory.createMathBigInteger(); @@ -1079,10 +1079,12 @@ public final class DefaultTypeManager implements TypeManager { // Temporal types addType(Time.class, timeType); nativeMap.put(Types.TIME, timeType); + + ScalarTypeDate dateType = new ScalarTypeDate(jsonDate); addType(Date.class, dateType); nativeMap.put(Types.DATE, dateType); - ScalarType timestampType = new ScalarTypeTimestamp(mode); + ScalarType timestampType = new ScalarTypeTimestamp(jsonDateTime); addType(Timestamp.class, timestampType); nativeMap.put(Types.TIMESTAMP, timestampType); } diff --git a/src/main/java/io/ebeaninternal/server/type/ScalarTypeBaseDate.java b/src/main/java/io/ebeaninternal/server/type/ScalarTypeBaseDate.java index 3806064b4..77ccf5fce 100644 --- a/src/main/java/io/ebeaninternal/server/type/ScalarTypeBaseDate.java +++ b/src/main/java/io/ebeaninternal/server/type/ScalarTypeBaseDate.java @@ -1,9 +1,10 @@ package io.ebeaninternal.server.type; -import io.ebeanservice.docstore.api.mapping.DocPropertyType; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; +import io.ebean.config.JsonConfig; +import io.ebeanservice.docstore.api.mapping.DocPropertyType; import java.io.DataInput; import java.io.DataOutput; @@ -17,8 +18,11 @@ import java.sql.Types; */ public abstract class ScalarTypeBaseDate extends ScalarTypeBase { - public ScalarTypeBaseDate(Class type, boolean jdbcNative, int jdbcType) { + protected final JsonConfig.Date mode; + + public ScalarTypeBaseDate(JsonConfig.Date mode, Class type, boolean jdbcNative, int jdbcType) { super(type, jdbcNative, jdbcType); + this.mode = mode; } /** @@ -93,9 +97,20 @@ public abstract class ScalarTypeBaseDate extends ScalarTypeBase { @Override public void jsonWrite(JsonGenerator writer, T value) throws IOException { - writer.writeNumber(convertToMillis(value)); + switch(mode) { + case ISO8601: + writer.writeString(toIsoFormat(value)); + break; + default: + writer.writeNumber(convertToMillis(value)); + } } + /** + * Convert the value to ISO8601 format. + */ + protected abstract String toIsoFormat(T value); + @Override public DocPropertyType getDocType() { return DocPropertyType.DATE; diff --git a/src/main/java/io/ebeaninternal/server/type/ScalarTypeBaseDateTime.java b/src/main/java/io/ebeaninternal/server/type/ScalarTypeBaseDateTime.java index af15abfa2..17f7c320b 100644 --- a/src/main/java/io/ebeaninternal/server/type/ScalarTypeBaseDateTime.java +++ b/src/main/java/io/ebeaninternal/server/type/ScalarTypeBaseDateTime.java @@ -19,7 +19,7 @@ import java.sql.Types; public abstract class ScalarTypeBaseDateTime extends ScalarTypeBase { - protected final DateTimeJsonParser dateTimeParser = new DateTimeJsonParser(); + protected final UtilDateTimeParser dateTimeParser = new UtilDateTimeParser(); protected final JsonConfig.DateTime mode; diff --git a/src/main/java/io/ebeaninternal/server/type/ScalarTypeDate.java b/src/main/java/io/ebeaninternal/server/type/ScalarTypeDate.java index 90d478bd9..5c9e992de 100644 --- a/src/main/java/io/ebeaninternal/server/type/ScalarTypeDate.java +++ b/src/main/java/io/ebeaninternal/server/type/ScalarTypeDate.java @@ -1,5 +1,6 @@ package io.ebeaninternal.server.type; +import io.ebean.config.JsonConfig; import io.ebeaninternal.server.core.BasicTypeConverter; import java.sql.Date; @@ -11,8 +12,13 @@ import java.sql.Types; */ public class ScalarTypeDate extends ScalarTypeBaseDate { - public ScalarTypeDate() { - super(Date.class, true, Types.DATE); + public ScalarTypeDate(JsonConfig.Date mode) { + super(mode, Date.class, true, Types.DATE); + } + + @Override + protected String toIsoFormat(Date value) { + return value.toLocalDate().toString(); } @Override diff --git a/src/main/java/io/ebeaninternal/server/type/ScalarTypeJodaDateMidnight.java b/src/main/java/io/ebeaninternal/server/type/ScalarTypeJodaDateMidnight.java index 105db9d07..bebd64de7 100644 --- a/src/main/java/io/ebeaninternal/server/type/ScalarTypeJodaDateMidnight.java +++ b/src/main/java/io/ebeaninternal/server/type/ScalarTypeJodaDateMidnight.java @@ -1,6 +1,8 @@ package io.ebeaninternal.server.type; +import io.ebean.config.JsonConfig; import io.ebeaninternal.server.core.BasicTypeConverter; +import org.joda.time.DateMidnight; import java.sql.Date; import java.sql.Types; @@ -14,8 +16,13 @@ public class ScalarTypeJodaDateMidnight extends ScalarTypeBaseDate { - public ScalarTypeJodaLocalDate() { - super(LocalDate.class, false, Types.DATE); + public ScalarTypeJodaLocalDate(JsonConfig.Date mode) { + super(mode, LocalDate.class, false, Types.DATE); + } + + @Override + protected String toIsoFormat(LocalDate value) { + return value.toString(); } @Override diff --git a/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDate.java b/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDate.java index bcb482bae..8b90b9208 100644 --- a/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDate.java +++ b/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDate.java @@ -1,5 +1,6 @@ package io.ebeaninternal.server.type; +import io.ebean.config.JsonConfig; import io.ebeaninternal.server.core.BasicTypeConverter; import java.sql.Date; @@ -14,8 +15,12 @@ import java.time.ZonedDateTime; */ public class ScalarTypeLocalDate extends ScalarTypeBaseDate { - public ScalarTypeLocalDate() { - super(LocalDate.class, false, Types.DATE); + public ScalarTypeLocalDate(JsonConfig.Date mode) { + super(mode, LocalDate.class, false, Types.DATE); + } + + protected String toIsoFormat(LocalDate value) { + return value.toString(); } @Override @@ -55,5 +60,4 @@ public class ScalarTypeLocalDate extends ScalarTypeBaseDate { return new Timestamp(systemTimeMillis).toLocalDateTime().toLocalDate(); } - } diff --git a/src/main/java/io/ebeaninternal/server/type/ScalarTypeUtilDate.java b/src/main/java/io/ebeaninternal/server/type/ScalarTypeUtilDate.java index 034a77902..0d02b81dc 100644 --- a/src/main/java/io/ebeaninternal/server/type/ScalarTypeUtilDate.java +++ b/src/main/java/io/ebeaninternal/server/type/ScalarTypeUtilDate.java @@ -82,10 +82,13 @@ public class ScalarTypeUtilDate { public static class DateType extends ScalarTypeBaseDate { - public DateType() { - super(Date.class, false, Types.DATE); + public DateType(JsonConfig.Date mode) { + super(mode, Date.class, false, Types.DATE); } + protected String toIsoFormat(java.util.Date value) { + return UtilDateParser.format(value); + } @Override public long convertToMillis(java.util.Date value) { diff --git a/src/main/java/io/ebeaninternal/server/type/ScalarTypeYearMonthDate.java b/src/main/java/io/ebeaninternal/server/type/ScalarTypeYearMonthDate.java index 175fd6be9..053950ab7 100644 --- a/src/main/java/io/ebeaninternal/server/type/ScalarTypeYearMonthDate.java +++ b/src/main/java/io/ebeaninternal/server/type/ScalarTypeYearMonthDate.java @@ -1,5 +1,6 @@ package io.ebeaninternal.server.type; +import io.ebean.config.JsonConfig; import io.ebeaninternal.server.core.BasicTypeConverter; import java.sql.Date; @@ -15,8 +16,12 @@ import java.time.ZonedDateTime; */ public class ScalarTypeYearMonthDate extends ScalarTypeBaseDate { - public ScalarTypeYearMonthDate() { - super(YearMonth.class, false, Types.DATE); + public ScalarTypeYearMonthDate(JsonConfig.Date mode) { + super(mode, YearMonth.class, false, Types.DATE); + } + + protected String toIsoFormat(YearMonth value) { + return value.atDay(1).toString(); } protected LocalDate toLocalDate(YearMonth yearMonth) { diff --git a/src/main/java/io/ebeaninternal/server/type/UtilDateParser.java b/src/main/java/io/ebeaninternal/server/type/UtilDateParser.java new file mode 100644 index 000000000..a420f7ecc --- /dev/null +++ b/src/main/java/io/ebeaninternal/server/type/UtilDateParser.java @@ -0,0 +1,26 @@ +package io.ebeaninternal.server.type; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +class UtilDateParser { + + private static final SimpleDateFormat dateTimeProto = new SimpleDateFormat("yyyy-MM-dd"); + + private static SimpleDateFormat formatter() { + return (SimpleDateFormat) dateTimeProto.clone(); + } + + static Date parse(String jsonDateTime) { + try { + return formatter().parse(jsonDateTime); + } catch (ParseException e) { + throw new RuntimeException("Error parsing Date[" + jsonDateTime + "]", e); + } + } + + static String format(Date value) { + return formatter().format(value); + } +} diff --git a/src/main/java/io/ebeaninternal/server/type/DateTimeJsonParser.java b/src/main/java/io/ebeaninternal/server/type/UtilDateTimeParser.java similarity index 96% rename from src/main/java/io/ebeaninternal/server/type/DateTimeJsonParser.java rename to src/main/java/io/ebeaninternal/server/type/UtilDateTimeParser.java index 89e5a5bbb..3b4a8ff84 100644 --- a/src/main/java/io/ebeaninternal/server/type/DateTimeJsonParser.java +++ b/src/main/java/io/ebeaninternal/server/type/UtilDateTimeParser.java @@ -6,15 +6,14 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; -public class DateTimeJsonParser { +class UtilDateTimeParser { private final SimpleDateFormat dateTimeProto20; private final SimpleDateFormat dateTimeProto22; private final SimpleDateFormat dateTimeProto23; private final SimpleDateFormat dateTimeProto24; - - public DateTimeJsonParser() { + UtilDateTimeParser() { dateTimeProto20 = init("yyyy-MM-dd'T'HH:mm:ss'Z'"); dateTimeProto22 = init("yyyy-MM-dd'T'HH:mm:ss.S'Z'"); dateTimeProto23 = init("yyyy-MM-dd'T'HH:mm:ss.SS'Z'"); diff --git a/src/test/java/io/ebean/config/ServerConfigTest.java b/src/test/java/io/ebean/config/ServerConfigTest.java index 52965604d..ef62979ea 100644 --- a/src/test/java/io/ebean/config/ServerConfigTest.java +++ b/src/test/java/io/ebean/config/ServerConfigTest.java @@ -61,6 +61,7 @@ public class ServerConfigTest { props.setProperty("backgroundExecutorSchedulePoolSize", "4"); props.setProperty("dbOffline", "true"); props.setProperty("jsonDateTime", "ISO8601"); + props.setProperty("jsonDate", "ISO8601"); props.setProperty("autoReadOnlyDataSource", "true"); props.setProperty("disableL2Cache", "true"); props.setProperty("notifyL2CacheInForeground", "true"); @@ -86,6 +87,8 @@ public class ServerConfigTest { assertEquals(PersistBatch.ALL, serverConfig.getPersistBatchOnCascade()); assertEquals(PlatformConfig.DbUuid.BINARY, serverConfig.getPlatformConfig().getDbUuid()); assertEquals(JsonConfig.DateTime.ISO8601, serverConfig.getJsonDateTime()); + assertEquals(JsonConfig.Date.ISO8601, serverConfig.getJsonDate()); + assertEquals("r0,users,orgs", serverConfig.getEnabledL2Regions()); assertEquals(42, serverConfig.getJdbcFetchSizeFindEach()); @@ -126,6 +129,8 @@ public class ServerConfigTest { serverConfig.setIdGeneratorAutomatic(false); assertFalse(serverConfig.isIdGeneratorAutomatic()); + assertEquals(JsonConfig.DateTime.MILLIS, serverConfig.getJsonDateTime()); + assertEquals(JsonConfig.Date.MILLIS, serverConfig.getJsonDate()); } @Test diff --git a/src/test/java/io/ebeaninternal/server/type/DateTimeJsonParserTest.java b/src/test/java/io/ebeaninternal/server/type/DateTimeJsonParserTest.java deleted file mode 100644 index a82e8a417..000000000 --- a/src/test/java/io/ebeaninternal/server/type/DateTimeJsonParserTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package io.ebeaninternal.server.type; - - -import org.junit.Test; - -import java.sql.Timestamp; - -import static org.assertj.core.api.StrictAssertions.assertThat; - -public class DateTimeJsonParserTest { - - @Test - public void parseFormat_when_hasMillis() throws Exception { - - DateTimeJsonParser parser = new DateTimeJsonParser(); - - String input = "2016-02-28T20:39:00.123Z"; - String formatted = parseAndFormat(parser, input); - - assertThat(formatted).isEqualTo("2016-02-28T20:39:00.123Z"); - } - - @Test - public void parseFormat_when_noMillis() throws Exception { - - DateTimeJsonParser parser = new DateTimeJsonParser(); - - String input = "2016-02-28T20:39:00Z"; - String formatted = parseAndFormat(parser, input); - - assertThat(formatted).isEqualTo("2016-02-28T20:39:00.000Z"); - } - - @Test - public void parseFormat_when_millis_1dp() throws Exception { - - DateTimeJsonParser parser = new DateTimeJsonParser(); - - String input = "2016-02-28T20:39:00.0Z"; - String formatted = parseAndFormat(parser, input); - - assertThat(formatted).isEqualTo("2016-02-28T20:39:00.000Z"); - } - - @Test - public void parseFormat_when_millis_2dp() throws Exception { - - DateTimeJsonParser parser = new DateTimeJsonParser(); - - String input = "2016-02-28T20:39:00.00Z"; - String formatted = parseAndFormat(parser, input); - - assertThat(formatted).isEqualTo("2016-02-28T20:39:00.000Z"); - } - - @Test - public void parseFormat_when_millis_3dp() throws Exception { - - DateTimeJsonParser parser = new DateTimeJsonParser(); - - String input = "2016-02-28T20:39:00.000Z"; - String formatted = parseAndFormat(parser, input); - - assertThat(formatted).isEqualTo("2016-02-28T20:39:00.000Z"); - } - - private String parseAndFormat(DateTimeJsonParser parser, String input) { - Timestamp timestamp = parser.parse(input); - return parser.format(timestamp); - } -} diff --git a/src/test/java/io/ebeaninternal/server/type/JsonTester.java b/src/test/java/io/ebeaninternal/server/type/JsonTester.java index 83257d69c..de6f2e324 100644 --- a/src/test/java/io/ebeaninternal/server/type/JsonTester.java +++ b/src/test/java/io/ebeaninternal/server/type/JsonTester.java @@ -25,7 +25,7 @@ public class JsonTester { this.type = type; } - public void test(T value) throws IOException { + public String test(T value) throws IOException { StringWriter writer = new StringWriter(); @@ -48,5 +48,6 @@ public class JsonTester { T val1 = type.jsonRead(parser); assertEquals(value, val1); + return writer.toString(); } } diff --git a/src/test/java/io/ebeaninternal/server/type/ScalarTypeDateTest.java b/src/test/java/io/ebeaninternal/server/type/ScalarTypeDateTest.java index 14b0e8b4d..5e938c854 100644 --- a/src/test/java/io/ebeaninternal/server/type/ScalarTypeDateTest.java +++ b/src/test/java/io/ebeaninternal/server/type/ScalarTypeDateTest.java @@ -1,14 +1,18 @@ package io.ebeaninternal.server.type; +import io.ebean.config.JsonConfig; import org.junit.Test; +import java.io.IOException; import java.sql.Date; +import java.time.LocalDate; +import static org.assertj.core.api.StrictAssertions.assertThat; import static org.junit.Assert.assertEquals; public class ScalarTypeDateTest { - ScalarTypeDate type = new ScalarTypeDate(); + private ScalarTypeDate type = new ScalarTypeDate(JsonConfig.Date.MILLIS); @Test public void formatParse_PG_DATE_POSITIVE_INFINITY() { @@ -19,4 +23,16 @@ public class ScalarTypeDateTest { Date parsed = type.parse(format); assertEquals(parsed, postgresInfinityDate); } + + @Test + public void json() throws IOException { + + Date val = Date.valueOf(LocalDate.of(2019, 5, 9)); + + JsonTester jsonMillis = new JsonTester<>(type); + assertThat(jsonMillis.test(val)).isEqualTo("{\"key\":1557316800000}"); + + JsonTester jsonIso = new JsonTester<>(new ScalarTypeDate(JsonConfig.Date.ISO8601)); + assertThat(jsonIso.test(val)).isEqualTo("{\"key\":\"2019-05-09\"}"); + } } diff --git a/src/test/java/io/ebeaninternal/server/type/ScalarTypeJodaLocalDateTest.java b/src/test/java/io/ebeaninternal/server/type/ScalarTypeJodaLocalDateTest.java index 60ee1c92d..c5b5bbdb3 100644 --- a/src/test/java/io/ebeaninternal/server/type/ScalarTypeJodaLocalDateTest.java +++ b/src/test/java/io/ebeaninternal/server/type/ScalarTypeJodaLocalDateTest.java @@ -1,8 +1,10 @@ package io.ebeaninternal.server.type; +import io.ebean.config.JsonConfig; import org.joda.time.LocalDate; import org.junit.Test; +import java.io.IOException; import java.sql.Date; import static org.assertj.core.api.Assertions.assertThat; @@ -10,7 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class ScalarTypeJodaLocalDateTest { - private ScalarTypeJodaLocalDate type = new ScalarTypeJodaLocalDate(); + private ScalarTypeJodaLocalDate type = new ScalarTypeJodaLocalDate(JsonConfig.Date.MILLIS); @Test public void convertToMillis_convertFromMillis() { @@ -58,4 +60,15 @@ public class ScalarTypeJodaLocalDateTest { assertThat(beanType).isEqualTo(localDate); } + @Test + public void json() throws IOException { + + LocalDate val = new LocalDate(2019, 5, 9); + + JsonTester jsonMillis = new JsonTester<>(type); + assertThat(jsonMillis.test(val)).isEqualTo("{\"key\":1557316800000}"); + + JsonTester jsonIso = new JsonTester<>(new ScalarTypeJodaLocalDate(JsonConfig.Date.ISO8601) ); + assertThat(jsonIso.test(val)).isEqualTo("{\"key\":\"2019-05-09\"}"); + } } diff --git a/src/test/java/io/ebeaninternal/server/type/ScalarTypeLocalDateTest.java b/src/test/java/io/ebeaninternal/server/type/ScalarTypeLocalDateTest.java index 92386ba4a..e9250a30f 100644 --- a/src/test/java/io/ebeaninternal/server/type/ScalarTypeLocalDateTest.java +++ b/src/test/java/io/ebeaninternal/server/type/ScalarTypeLocalDateTest.java @@ -1,19 +1,22 @@ package io.ebeaninternal.server.type; +import io.ebean.config.JsonConfig; import org.junit.Test; +import java.io.IOException; import java.sql.Date; import java.time.LocalDate; +import static org.assertj.core.api.StrictAssertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class ScalarTypeLocalDateTest { - ScalarTypeLocalDate type = new ScalarTypeLocalDate(); + ScalarTypeLocalDate type = new ScalarTypeLocalDate(JsonConfig.Date.MILLIS); @Test - public void testConvertToMillis() throws Exception { + public void testConvertToMillis() { LocalDate date = LocalDate.of(2014, 5, 20); long millis = type.convertToMillis(date); @@ -23,7 +26,7 @@ public class ScalarTypeLocalDateTest { } @Test - public void testConvertFromDate() throws Exception { + public void testConvertFromDate() { LocalDate localDate = LocalDate.now(); Date date = Date.valueOf(localDate); @@ -37,7 +40,7 @@ public class ScalarTypeLocalDateTest { @Test - public void testToJdbcType() throws Exception { + public void testToJdbcType() { LocalDate localDate = LocalDate.now(); Object o = type.toJdbcType(localDate); @@ -45,7 +48,7 @@ public class ScalarTypeLocalDateTest { } @Test - public void testToBeanType() throws Exception { + public void testToBeanType() { LocalDate localDate = LocalDate.now(); Date date = Date.valueOf(localDate); @@ -54,4 +57,15 @@ public class ScalarTypeLocalDateTest { assertEquals(localDate, localDate1); } + @Test + public void json() throws IOException { + + LocalDate val = LocalDate.of(2019, 5, 9); + + JsonTester jsonMillis = new JsonTester<>(type); + assertThat(jsonMillis.test(val)).isEqualTo("{\"key\":1557316800000}"); + + JsonTester jsonIso = new JsonTester<>(new ScalarTypeLocalDate(JsonConfig.Date.ISO8601) ); + assertThat(jsonIso.test(val)).isEqualTo("{\"key\":\"2019-05-09\"}"); + } } diff --git a/src/test/java/io/ebeaninternal/server/type/ScalarTypeUtilDateTest.java b/src/test/java/io/ebeaninternal/server/type/ScalarTypeUtilDateTest.java new file mode 100644 index 000000000..4d614655e --- /dev/null +++ b/src/test/java/io/ebeaninternal/server/type/ScalarTypeUtilDateTest.java @@ -0,0 +1,26 @@ +package io.ebeaninternal.server.type; + +import io.ebean.config.JsonConfig; +import org.junit.Test; + +import java.io.IOException; +import java.util.Date; + +import static org.assertj.core.api.StrictAssertions.assertThat; + +public class ScalarTypeUtilDateTest { + + private ScalarTypeUtilDate.DateType dateType = new ScalarTypeUtilDate.DateType(JsonConfig.Date.MILLIS); + + @Test + public void json() throws IOException { + + Date val = dateType.parse("2019-05-09"); + + JsonTester jsonMillis = new JsonTester<>(dateType); + assertThat(jsonMillis.test(val)).isEqualTo("{\"key\":1557316800000}"); + + JsonTester jsonIso = new JsonTester<>(new ScalarTypeUtilDate.DateType(JsonConfig.Date.ISO8601) ); + assertThat(jsonIso.test(val)).isEqualTo("{\"key\":\"2019-05-09\"}"); + } +} diff --git a/src/test/java/io/ebeaninternal/server/type/ScalarTypeYearMonthDateTest.java b/src/test/java/io/ebeaninternal/server/type/ScalarTypeYearMonthDateTest.java index d449a2a1a..fc57ab04f 100644 --- a/src/test/java/io/ebeaninternal/server/type/ScalarTypeYearMonthDateTest.java +++ b/src/test/java/io/ebeaninternal/server/type/ScalarTypeYearMonthDateTest.java @@ -1,19 +1,22 @@ package io.ebeaninternal.server.type; +import io.ebean.config.JsonConfig; import org.junit.Test; +import java.io.IOException; import java.sql.Date; import java.time.LocalDate; import java.time.YearMonth; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; public class ScalarTypeYearMonthDateTest { - ScalarTypeYearMonthDate type = new ScalarTypeYearMonthDate(); + private ScalarTypeYearMonthDate type = new ScalarTypeYearMonthDate(JsonConfig.Date.MILLIS); @Test - public void testConvertFromMillis() throws Exception { + public void testConvertFromMillis() { LocalDate today = LocalDate.now(); LocalDate firstMonthDay = today.withDayOfMonth(1); @@ -27,7 +30,7 @@ public class ScalarTypeYearMonthDateTest { } @Test - public void testConvertDate() throws Exception { + public void testConvertDate() { LocalDate today = LocalDate.now(); LocalDate firstMonthDay = today.withDayOfMonth(1); @@ -40,7 +43,7 @@ public class ScalarTypeYearMonthDateTest { @Test - public void testToJdbcType() throws Exception { + public void testToJdbcType() { LocalDate today = LocalDate.now(); LocalDate firstMonthDay = today.withDayOfMonth(1); @@ -51,4 +54,16 @@ public class ScalarTypeYearMonthDateTest { assertEquals(date, val1); } + @Test + public void json() throws IOException { + + YearMonth val = YearMonth.of(2019, 5); + + JsonTester jsonMillis = new JsonTester<>(type); + assertThat(jsonMillis.test(val)).isEqualTo("{\"key\":1556625600000}"); + + JsonTester jsonIso = new JsonTester<>(new ScalarTypeYearMonthDate(JsonConfig.Date.ISO8601) ); + assertThat(jsonIso.test(val)).isEqualTo("{\"key\":\"2019-05-01\"}"); + } + } diff --git a/src/test/java/io/ebeaninternal/server/type/UtilDateParserTest.java b/src/test/java/io/ebeaninternal/server/type/UtilDateParserTest.java new file mode 100644 index 000000000..50131893b --- /dev/null +++ b/src/test/java/io/ebeaninternal/server/type/UtilDateParserTest.java @@ -0,0 +1,18 @@ +package io.ebeaninternal.server.type; + +import org.junit.Test; + +import java.util.Date; + +import static org.assertj.core.api.Assertions.assertThat; + +public class UtilDateParserTest { + + @Test + public void parse() { + + Date val = UtilDateParser.parse("2019-05-09"); + String format = UtilDateParser.format(val); + assertThat(format).isEqualTo("2019-05-09"); + } +} diff --git a/src/test/java/io/ebeaninternal/server/type/UtilDateTimeParserTest.java b/src/test/java/io/ebeaninternal/server/type/UtilDateTimeParserTest.java new file mode 100644 index 000000000..c27e73810 --- /dev/null +++ b/src/test/java/io/ebeaninternal/server/type/UtilDateTimeParserTest.java @@ -0,0 +1,44 @@ +package io.ebeaninternal.server.type; + + +import org.junit.Test; + +import java.sql.Timestamp; + +import static org.assertj.core.api.StrictAssertions.assertThat; + +public class UtilDateTimeParserTest { + + private UtilDateTimeParser parser = new UtilDateTimeParser(); + + @Test + public void parseFormat_when_hasMillis() { + parseAndFormat("2016-02-28T20:39:00.123Z", "2016-02-28T20:39:00.123Z"); + } + + @Test + public void parseFormat_when_noMillis() { + parseAndFormat("2016-02-28T20:39:00Z", "2016-02-28T20:39:00.000Z"); + } + + @Test + public void parseFormat_when_millis_1dp() { + parseAndFormat("2016-02-28T20:39:00.0Z", "2016-02-28T20:39:00.000Z"); + } + + @Test + public void parseFormat_when_millis_2dp() { + parseAndFormat("2016-02-28T20:39:00.00Z", "2016-02-28T20:39:00.000Z"); + } + + @Test + public void parseFormat_when_millis_3dp() { + parseAndFormat("2016-02-28T20:39:00.000Z", "2016-02-28T20:39:00.000Z"); + } + + private void parseAndFormat(String input, String expected) { + Timestamp timestamp = parser.parse(input); + String format = parser.format(timestamp); + assertThat(format).isEqualTo(expected); + } +} diff --git a/src/test/java/org/tests/transaction/TestExplicitTransactionMode.java b/src/test/java/org/tests/transaction/TestExplicitTransactionMode.java index 86e939ec9..66da8f645 100644 --- a/src/test/java/org/tests/transaction/TestExplicitTransactionMode.java +++ b/src/test/java/org/tests/transaction/TestExplicitTransactionMode.java @@ -1,7 +1,5 @@ package org.tests.transaction; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParser; import io.ebean.BaseTestCase; import io.ebean.EbeanServer; import io.ebean.EbeanServerFactory; @@ -9,6 +7,7 @@ import io.ebean.Query; import io.ebean.Transaction; import io.ebean.annotation.ForPlatform; import io.ebean.annotation.Platform; +import io.ebean.config.JsonConfig; import io.ebean.config.ServerConfig; import io.ebean.config.properties.PropertiesLoader; import io.ebean.datasource.DataSourceConfig; @@ -19,7 +18,6 @@ import org.junit.Test; import org.tests.model.basic.UTDetail; import org.tests.model.basic.UTMaster; -import java.io.IOException; import java.sql.Connection; import java.sql.SQLException; import java.time.LocalDate; @@ -127,14 +125,8 @@ public class TestExplicitTransactionMode extends BaseTestCase { public static class ScalarTypeLocalDateAsString extends ScalarTypeLocalDate { - @Override - public LocalDate jsonRead(JsonParser parser) throws IOException { - return super.jsonRead(parser); - } - - @Override - public void jsonWrite(JsonGenerator writer, LocalDate value) throws IOException { - writer.writeString(value.toString()); + public ScalarTypeLocalDateAsString() { + super(JsonConfig.Date.ISO8601); } } } diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 82935fc18..d5aba8ffa 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -86,13 +86,13 @@ - - + + - - - - + + + +