#420 - Review JodaLocalTime (being stored and fetched using UTC)

This commit is contained in:
Robin Bygrave
2016-02-17 21:34:52 +13:00
parent a22574b0c9
commit f055a0d0cb
7 changed files with 141 additions and 10 deletions
@@ -387,6 +387,8 @@ public class ServerConfig {
*/
private boolean expressionEqualsWithNullAsNoop;
private String jodaLocalTimeMode;
/**
* Construct a Server Configuration for programmatically creating an EbeanServer.
*/
@@ -1640,6 +1642,20 @@ public class ServerConfig {
this.disableClasspathSearch = disableClasspathSearch;
}
/**
* Return the mode to use for Joda LocalTime support 'normal' or 'utc'.
*/
public String getJodaLocalTimeMode() {
return jodaLocalTimeMode;
}
/**
* Set the mode to use for Joda LocalTime support 'normal' or 'utc'.
*/
public void setJodaLocalTimeMode(String jodaLocalTimeMode) {
this.jodaLocalTimeMode = jodaLocalTimeMode;
}
/**
* Programmatically add classes (typically entities) that this server should
* use.
@@ -2286,6 +2302,7 @@ public class ServerConfig {
dbUuid = DbUuid.BINARY;
}
localTimeWithNanos = p.getBoolean("localTimeWithNanos", localTimeWithNanos);
jodaLocalTimeMode = p.get("jodaLocalTimeMode", jodaLocalTimeMode);
lazyLoadBatchSize = p.getInt("lazyLoadBatchSize", lazyLoadBatchSize);
queryBatchSize = p.getInt("queryBatchSize", queryBatchSize);
@@ -7,7 +7,6 @@ import com.avaje.ebean.annotation.EnumValue;
import com.avaje.ebean.config.*;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebean.config.dbplatform.DbType;
import com.avaje.ebeaninternal.api.ClassUtil;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
import com.avaje.ebeaninternal.server.type.reflect.*;
@@ -285,7 +284,15 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
*/
@SuppressWarnings("unchecked")
public <T> ScalarType<T> getScalarType(Class<T> type) {
return (ScalarType<T>) typeMap.get(type);
ScalarType<T> found = (ScalarType<T>) typeMap.get(type);
if (found == null) {
if (type.getName().equals("org.joda.time.LocalTime")) {
throw new IllegalStateException(
"ScalarType of Joda LocalTime not defined. You need to set ServerConfig.jodaLocalTimeMode to"
+ " either 'normal' or 'utc'. UTC is the old mode using UTC timezone but local time zone is now preferred as 'normal' mode.");
}
}
return found;
}
public ScalarDataReader<?> getScalarDataReader(Class<?> propertyType, int sqlType) {
@@ -805,8 +812,18 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
typeMap.put(LocalDateTime.class, new ScalarTypeJodaLocalDateTime(mode));
typeMap.put(DateTime.class, new ScalarTypeJodaDateTime(mode));
typeMap.put(LocalDate.class, new ScalarTypeJodaLocalDate());
typeMap.put(LocalTime.class, new ScalarTypeJodaLocalTime());
typeMap.put(DateMidnight.class, new ScalarTypeJodaDateMidnight());
String jodaLocalTimeMode = config.getJodaLocalTimeMode();
if ("normal".equalsIgnoreCase(jodaLocalTimeMode)) {
// use the expected/normal local time zone
typeMap.put(LocalTime.class, new ScalarTypeJodaLocalTime());
logger.debug("registered ScalarTypeJodaLocalTime");
} else if ("utc".equalsIgnoreCase(jodaLocalTimeMode)) {
// use the old UTC based
typeMap.put(LocalTime.class, new ScalarTypeJodaLocalTimeUTC());
logger.debug("registered ScalarTypeJodaLocalTimeUTC");
}
}
}
@@ -28,8 +28,7 @@ public class ScalarTypeJodaLocalTime extends ScalarTypeBase<LocalTime> {
if (value == null) {
b.setNull(Types.TIME);
} else {
Time sqlTime = new Time(value.getMillisOfDay());
b.setTime(sqlTime);
b.setTime(new Time(value.getHourOfDay(), value.getMinuteOfHour(), value.getSecondOfMinute()));
}
}
@@ -40,14 +39,15 @@ public class ScalarTypeJodaLocalTime extends ScalarTypeBase<LocalTime> {
if (sqlTime == null) {
return null;
} else {
return new LocalTime(sqlTime, DateTimeZone.UTC);
return new LocalTime(sqlTime, DateTimeZone.getDefault());
}
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof LocalTime) {
return new Time(((LocalTime) value).getMillisOfDay());
LocalTime lt = (LocalTime) value;
return new Time(lt.getHourOfDay(), lt.getMinuteOfHour(), lt.getSecondOfMinute());
}
return BasicTypeConverter.toTime(value);
}
@@ -55,7 +55,7 @@ public class ScalarTypeJodaLocalTime extends ScalarTypeBase<LocalTime> {
@Override
public LocalTime toBeanType(Object value) {
if (value instanceof java.util.Date) {
return new LocalTime(value, DateTimeZone.UTC);
return new LocalTime(value, DateTimeZone.getDefault());
}
return (LocalTime) value;
}
@@ -88,7 +88,7 @@ public class ScalarTypeJodaLocalTime extends ScalarTypeBase<LocalTime> {
@Override
public LocalTime convertFromMillis(long systemTimeMillis) {
return new LocalTime(systemTimeMillis);
return new LocalTime(systemTimeMillis, DateTimeZone.getDefault());
}
@Override
@@ -0,0 +1,62 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalTime;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Types;
/**
* ScalarType for Joda LocalTime. This maps to a JDBC Time.
*/
public class ScalarTypeJodaLocalTimeUTC extends ScalarTypeJodaLocalTime {
public ScalarTypeJodaLocalTimeUTC() {
super();
}
@Override
public void bind(DataBind b, LocalTime value) throws SQLException {
if (value == null) {
b.setNull(Types.TIME);
} else {
Time sqlTime = new Time(value.getMillisOfDay());
b.setTime(sqlTime);
}
}
@Override
public LocalTime read(DataReader dataReader) throws SQLException {
Time sqlTime = dataReader.getTime();
if (sqlTime == null) {
return null;
} else {
return new LocalTime(sqlTime, DateTimeZone.UTC);
}
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof LocalTime) {
return new Time(((LocalTime) value).getMillisOfDay());
}
return BasicTypeConverter.toTime(value);
}
@Override
public LocalTime toBeanType(Object value) {
if (value instanceof java.util.Date) {
return new LocalTime(value, DateTimeZone.UTC);
}
return (LocalTime) value;
}
@Override
public LocalTime convertFromMillis(long systemTimeMillis) {
return new LocalTime(systemTimeMillis);
}
}