mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#2264 - Use of default timezone for OffsetDateTime offsets problematic for unit tests and presentation layer
This commit is contained in:
@@ -750,12 +750,15 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
|
||||
private void initialiseJavaTimeTypes(DatabaseConfig config) {
|
||||
|
||||
ZoneId zoneId = getZoneId(config);
|
||||
|
||||
typeMap.put(java.nio.file.Path.class, new ScalarTypePath());
|
||||
addType(java.time.Period.class, new ScalarTypePeriod());
|
||||
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(OffsetDateTime.class, new ScalarTypeOffsetDateTime(jsonDateTime, zoneId));
|
||||
addType(ZonedDateTime.class, new ScalarTypeZonedDateTime(jsonDateTime, zoneId));
|
||||
addType(Instant.class, new ScalarTypeInstant(jsonDateTime));
|
||||
addType(DayOfWeek.class, new ScalarTypeDayOfWeek());
|
||||
addType(Month.class, new ScalarTypeMonth());
|
||||
@@ -771,6 +774,11 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
addType(Duration.class, (durationNanos) ? new ScalarTypeDurationWithNanos() : new ScalarTypeDuration());
|
||||
}
|
||||
|
||||
private ZoneId getZoneId(DatabaseConfig config) {
|
||||
final String dataTimeZone = config.getDataTimeZone();
|
||||
return (dataTimeZone == null) ? ZoneOffset.systemDefault() : TimeZone.getTimeZone(dataTimeZone).toZoneId();
|
||||
}
|
||||
|
||||
private void addType(Class<?> clazz, ScalarType<?> scalarType) {
|
||||
typeMap.put(clazz, scalarType);
|
||||
logicalMap.putIfAbsent(clazz.getSimpleName(), scalarType);
|
||||
|
||||
@@ -15,8 +15,11 @@ import static io.ebeaninternal.server.type.IsoJsonDateTimeParser.formatIso;
|
||||
*/
|
||||
public class ScalarTypeOffsetDateTime extends ScalarTypeBaseDateTime<OffsetDateTime> {
|
||||
|
||||
public ScalarTypeOffsetDateTime(JsonConfig.DateTime mode) {
|
||||
private final ZoneId zoneId;
|
||||
|
||||
public ScalarTypeOffsetDateTime(JsonConfig.DateTime mode, ZoneId zoneId) {
|
||||
super(mode, OffsetDateTime.class, false, Types.TIMESTAMP);
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -46,7 +49,7 @@ public class ScalarTypeOffsetDateTime extends ScalarTypeBaseDateTime<OffsetDateT
|
||||
|
||||
@Override
|
||||
public OffsetDateTime convertFromInstant(Instant ts) {
|
||||
return OffsetDateTime.ofInstant(ts, ZoneId.systemDefault());
|
||||
return OffsetDateTime.ofInstant(ts, zoneId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,8 +13,11 @@ import java.time.ZonedDateTime;
|
||||
*/
|
||||
public class ScalarTypeZonedDateTime extends ScalarTypeBaseDateTime<ZonedDateTime> {
|
||||
|
||||
public ScalarTypeZonedDateTime(JsonConfig.DateTime mode) {
|
||||
private final ZoneId zoneId;
|
||||
|
||||
public ScalarTypeZonedDateTime(JsonConfig.DateTime mode, ZoneId zoneId) {
|
||||
super(mode, ZonedDateTime.class, false, Types.TIMESTAMP);
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -44,7 +47,7 @@ public class ScalarTypeZonedDateTime extends ScalarTypeBaseDateTime<ZonedDateTim
|
||||
|
||||
@Override
|
||||
public ZonedDateTime convertFromInstant(Instant ts) {
|
||||
return ZonedDateTime.ofInstant(ts, ZoneId.systemDefault());
|
||||
return ZonedDateTime.ofInstant(ts, zoneId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+44
-6
@@ -5,6 +5,8 @@ import org.junit.Test;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -14,12 +16,12 @@ import static org.junit.Assert.assertTrue;
|
||||
public class ScalarTypeOffsetDateTimeTest {
|
||||
|
||||
|
||||
ScalarTypeOffsetDateTime type = new ScalarTypeOffsetDateTime(JsonConfig.DateTime.MILLIS);
|
||||
ScalarTypeOffsetDateTime type = new ScalarTypeOffsetDateTime(JsonConfig.DateTime.MILLIS, ZoneOffset.systemDefault());
|
||||
|
||||
OffsetDateTime warmUp = OffsetDateTime.now();
|
||||
|
||||
@Test
|
||||
public void testConvertToMillis() throws Exception {
|
||||
public void testConvertToMillis() {
|
||||
|
||||
warmUp.hashCode();
|
||||
|
||||
@@ -30,7 +32,43 @@ public class ScalarTypeOffsetDateTimeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertFromTimestamp() throws Exception {
|
||||
public void convertFromInstant_with_UTC_expect_matchingZoneOffset() {
|
||||
final TimeZone timeZoneToUse = TimeZone.getTimeZone("UTC");
|
||||
final ZoneOffset expectedZoneOffset = ZoneOffset.UTC;
|
||||
|
||||
convertFromInstantWithConfiguredTimeZone(timeZoneToUse, expectedZoneOffset);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertFromInstant_with_EST_expect_matchingZoneOffset() {
|
||||
final TimeZone timeZoneToUse = TimeZone.getTimeZone("EST");
|
||||
final ZoneOffset expectedOffset = OffsetDateTime.now(timeZoneToUse.toZoneId()).getOffset();
|
||||
|
||||
convertFromInstantWithConfiguredTimeZone(timeZoneToUse, expectedOffset);
|
||||
}
|
||||
|
||||
private void convertFromInstantWithConfiguredTimeZone(TimeZone timeZoneToUse, ZoneOffset expectedZoneOffset) {
|
||||
TimeZone previous = TimeZone.getDefault();
|
||||
try {
|
||||
OffsetDateTime dateTime = OffsetDateTime.parse("2021-01-01T00:00:00+11:00");
|
||||
|
||||
// test ScalarTypeOffsetDateTime with the configured timeZone to use
|
||||
ScalarTypeOffsetDateTime type = new ScalarTypeOffsetDateTime(JsonConfig.DateTime.MILLIS, timeZoneToUse.toZoneId());
|
||||
|
||||
// effectively we desire to ignore the system timezone and use the configured one
|
||||
TimeZone.setDefault(timeZoneToUse);
|
||||
|
||||
final OffsetDateTime offsetDateTime = type.convertFromInstant(dateTime.toInstant());
|
||||
|
||||
assertEquals(expectedZoneOffset, offsetDateTime.getOffset());
|
||||
|
||||
} finally {
|
||||
TimeZone.setDefault(previous);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertFromTimestamp() {
|
||||
|
||||
Timestamp now = new Timestamp(System.currentTimeMillis());
|
||||
|
||||
@@ -69,11 +107,11 @@ public class ScalarTypeOffsetDateTimeTest {
|
||||
JsonTester<OffsetDateTime> jsonTester = new JsonTester<>(type);
|
||||
jsonTester.test(now);
|
||||
|
||||
ScalarTypeOffsetDateTime typeNanos = new ScalarTypeOffsetDateTime(JsonConfig.DateTime.NANOS);
|
||||
ScalarTypeOffsetDateTime typeNanos = new ScalarTypeOffsetDateTime(JsonConfig.DateTime.NANOS, ZoneOffset.systemDefault());
|
||||
jsonTester = new JsonTester<>(typeNanos);
|
||||
jsonTester.test(now);
|
||||
|
||||
ScalarTypeOffsetDateTime typeIso = new ScalarTypeOffsetDateTime(JsonConfig.DateTime.ISO8601);
|
||||
ScalarTypeOffsetDateTime typeIso = new ScalarTypeOffsetDateTime(JsonConfig.DateTime.ISO8601, ZoneOffset.systemDefault());
|
||||
jsonTester = new JsonTester<>(typeIso);
|
||||
jsonTester.test(now);
|
||||
}
|
||||
@@ -81,7 +119,7 @@ public class ScalarTypeOffsetDateTimeTest {
|
||||
@Test
|
||||
public void isoJsonFormatParse() {
|
||||
|
||||
ScalarTypeOffsetDateTime typeIso = new ScalarTypeOffsetDateTime(JsonConfig.DateTime.ISO8601);
|
||||
ScalarTypeOffsetDateTime typeIso = new ScalarTypeOffsetDateTime(JsonConfig.DateTime.ISO8601, ZoneOffset.systemDefault());
|
||||
|
||||
OffsetDateTime now = OffsetDateTime.now();
|
||||
String asJson = typeIso.toJsonISO8601(now);
|
||||
|
||||
+45
-6
@@ -4,7 +4,11 @@ import io.ebean.config.JsonConfig;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.*;
|
||||
@@ -12,12 +16,12 @@ import static org.junit.Assert.*;
|
||||
public class ScalarTypeZonedDateTimeTest {
|
||||
|
||||
|
||||
ScalarTypeZonedDateTime type = new ScalarTypeZonedDateTime(JsonConfig.DateTime.MILLIS);
|
||||
ScalarTypeZonedDateTime type = new ScalarTypeZonedDateTime(JsonConfig.DateTime.MILLIS, ZoneId.systemDefault());
|
||||
|
||||
ZonedDateTime warmUp = ZonedDateTime.now();
|
||||
|
||||
@Test
|
||||
public void testConvertToMillis() throws Exception {
|
||||
public void testConvertToMillis() {
|
||||
|
||||
warmUp.hashCode();
|
||||
|
||||
@@ -29,7 +33,7 @@ public class ScalarTypeZonedDateTimeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertFromTimestamp() throws Exception {
|
||||
public void testConvertFromTimestamp() {
|
||||
|
||||
Timestamp now = new Timestamp(System.currentTimeMillis());
|
||||
|
||||
@@ -39,6 +43,41 @@ public class ScalarTypeZonedDateTimeTest {
|
||||
assertEquals(now, timestamp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertFromInstant_with_UTC_expect_matchingZoneOffset() {
|
||||
final TimeZone timeZoneToUse = TimeZone.getTimeZone("UTC");
|
||||
final ZoneOffset expectedZoneOffset = ZoneOffset.UTC;
|
||||
|
||||
convertFromInstantWithConfiguredTimeZone(timeZoneToUse, expectedZoneOffset);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertFromInstant_with_EST_expect_matchingZoneOffset() {
|
||||
final TimeZone timeZoneToUse = TimeZone.getTimeZone("EST");
|
||||
final ZoneOffset expectedOffset = OffsetDateTime.now(timeZoneToUse.toZoneId()).getOffset();
|
||||
|
||||
convertFromInstantWithConfiguredTimeZone(timeZoneToUse, expectedOffset);
|
||||
}
|
||||
|
||||
private void convertFromInstantWithConfiguredTimeZone(TimeZone timeZoneToUse, ZoneOffset expectedZoneOffset) {
|
||||
TimeZone previous = TimeZone.getDefault();
|
||||
try {
|
||||
OffsetDateTime dateTime = OffsetDateTime.parse("2021-01-01T00:00:00+11:00");
|
||||
|
||||
// test ScalarTypeOffsetDateTime with the configured timeZone to use
|
||||
ScalarTypeZonedDateTime type = new ScalarTypeZonedDateTime(JsonConfig.DateTime.MILLIS, timeZoneToUse.toZoneId());
|
||||
|
||||
// effectively we desire to ignore the system timezone and use the configured one
|
||||
TimeZone.setDefault(timeZoneToUse);
|
||||
|
||||
final ZonedDateTime zonedDateTime = type.convertFromInstant(dateTime.toInstant());
|
||||
|
||||
assertEquals(expectedZoneOffset, zonedDateTime.getOffset());
|
||||
|
||||
} finally {
|
||||
TimeZone.setDefault(previous);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToJdbcType() throws Exception {
|
||||
@@ -68,11 +107,11 @@ public class ScalarTypeZonedDateTimeTest {
|
||||
JsonTester<ZonedDateTime> jsonTester = new JsonTester<>(type);
|
||||
jsonTester.test(now);
|
||||
|
||||
ScalarTypeZonedDateTime typeNanos = new ScalarTypeZonedDateTime(JsonConfig.DateTime.NANOS);
|
||||
ScalarTypeZonedDateTime typeNanos = new ScalarTypeZonedDateTime(JsonConfig.DateTime.NANOS, ZoneId.systemDefault());
|
||||
jsonTester = new JsonTester<>(typeNanos);
|
||||
jsonTester.test(now);
|
||||
|
||||
ScalarTypeZonedDateTime typeIso = new ScalarTypeZonedDateTime(JsonConfig.DateTime.ISO8601);
|
||||
ScalarTypeZonedDateTime typeIso = new ScalarTypeZonedDateTime(JsonConfig.DateTime.ISO8601, ZoneId.systemDefault());
|
||||
jsonTester = new JsonTester<>(typeIso);
|
||||
jsonTester.test(now);
|
||||
}
|
||||
@@ -80,7 +119,7 @@ public class ScalarTypeZonedDateTimeTest {
|
||||
@Test
|
||||
public void toJsonISO8601() {
|
||||
|
||||
ScalarTypeZonedDateTime typeIso = new ScalarTypeZonedDateTime(JsonConfig.DateTime.ISO8601);
|
||||
ScalarTypeZonedDateTime typeIso = new ScalarTypeZonedDateTime(JsonConfig.DateTime.ISO8601, ZoneId.systemDefault());
|
||||
|
||||
ZonedDateTime now = ZonedDateTime.now();
|
||||
String asJson = typeIso.toJsonISO8601(now);
|
||||
|
||||
Reference in New Issue
Block a user