aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2018-12-28 04:19:21 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2018-12-28 04:19:21 +0000
commit0f568a46209da6557cfeab5f351bc6ee432eb3ea (patch)
treed028bfaf7a201d55acd842e400869d9ed2eb1a03 /src/main
parent61024b0227e3bd4455a4e55fae0e498f40fdda5a (diff)
downloadjackcess-0f568a46209da6557cfeab5f351bc6ee432eb3ea.tar.gz
jackcess-0f568a46209da6557cfeab5f351bc6ee432eb3ea.zip
add system prop for date/time type; rework how date/times are written based on date/time type
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/jdk8@1253 f203690c-595d-4dc9-a70b-905162fa7fd2
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/Database.java9
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java75
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java47
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/DateTimeContext.java (renamed from src/main/java/com/healthmarketscience/jackcess/impl/ZoneContext.java)4
4 files changed, 97 insertions, 38 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/Database.java b/src/main/java/com/healthmarketscience/jackcess/Database.java
index 13e45a5..4fa8741 100644
--- a/src/main/java/com/healthmarketscience/jackcess/Database.java
+++ b/src/main/java/com/healthmarketscience/jackcess/Database.java
@@ -106,7 +106,7 @@ public interface Database extends Iterable<Table>, Closeable, Flushable
"com.healthmarketscience.jackcess.brokenNio";
/** system property which can be used to set the default sort order for
- * table columns. Value should be one {@link Table.ColumnOrder} enum
+ * table columns. Value should be one of {@link Table.ColumnOrder} enum
* values.
* @usage _intermediate_field_
*/
@@ -134,6 +134,13 @@ public interface Database extends Iterable<Table>, Closeable, Flushable
public static final String ENABLE_EXPRESSION_EVALUATION_PROPERTY =
"com.healthmarketscience.jackcess.enableExpressionEvaluation";
+ /** system property which can be used to set the default date/Time type.
+ * Value should be one of {@link DateTimeType} enum values.
+ * @usage _general_field_
+ */
+ public static final String DATE_TIME_TYPE_PROPERTY =
+ "com.healthmarketscience.jackcess.dateTimeType";
+
/**
* Enum which indicates which version of Access created the database.
* @usage _general_class_
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
index 6ab88ab..4172874 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/ColumnImpl.java
@@ -76,7 +76,7 @@ import org.apache.commons.logging.LogFactory;
* @author Tim McCune
* @usage _intermediate_class_
*/
-public class ColumnImpl implements Column, Comparable<ColumnImpl>, ZoneContext
+public class ColumnImpl implements Column, Comparable<ColumnImpl>, DateTimeContext
{
protected static final Log LOG = LogFactory.getLog(ColumnImpl.class);
@@ -506,7 +506,8 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, ZoneContext
return getDatabase().getZoneId();
}
- protected DateTimeFactory getDateTimeFactory() {
+ @Override
+ public DateTimeFactory getDateTimeFactory() {
return getDatabase().getDateTimeFactory();
}
@@ -1042,21 +1043,12 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, ZoneContext
* Date/Calendar/Number/Temporal time value.
* @usage _advanced_method_
*/
- private static double toDateDouble(Object value, ZoneContext zc)
- {
- if(value instanceof TemporalAccessor) {
- return toDateDouble(toLocalDateTime((TemporalAccessor)value, zc));
- }
-
- // seems access stores dates in the local timezone. guess you just
- // hope you read it in the same timezone in which it was written!
- long time = toDateLong(value);
- time += getToLocalTimeZoneOffset(time, zc.getTimeZone());
- return toLocalDateDouble(time);
+ private static double toDateDouble(Object value, DateTimeContext dtc) {
+ return dtc.getDateTimeFactory().toDateDouble(value, dtc);
}
private static LocalDateTime toLocalDateTime(
- TemporalAccessor value, ZoneContext zc) {
+ TemporalAccessor value, DateTimeContext dtc) {
// handle some common Temporal types
if(value instanceof LocalDateTime) {
@@ -1065,10 +1057,10 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, ZoneContext
if(value instanceof ZonedDateTime) {
// if the temporal value has a timezone, convert it to this db's timezone
return ((ZonedDateTime)value).withZoneSameInstant(
- zc.getZoneId()).toLocalDateTime();
+ dtc.getZoneId()).toLocalDateTime();
}
if(value instanceof Instant) {
- return LocalDateTime.ofInstant((Instant)value, zc.getZoneId());
+ return LocalDateTime.ofInstant((Instant)value, dtc.getZoneId());
}
if(value instanceof LocalDate) {
return ((LocalDate)value).atTime(BASE_LT);
@@ -1092,7 +1084,7 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, ZoneContext
if(zone != null) {
// the Temporal has a zone, see if it is the right zone. if not,
// adjust it
- ZoneId zoneId = zc.getZoneId();
+ ZoneId zoneId = dtc.getZoneId();
if(!zoneId.equals(zone)) {
return ZonedDateTime.of(ld, lt, zone).withZoneSameInstant(zoneId)
.toLocalDateTime();
@@ -1107,6 +1099,16 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, ZoneContext
}
}
+ private static Instant toInstant(TemporalAccessor value, DateTimeContext dtc) {
+ if(value instanceof ZonedDateTime) {
+ return ((ZonedDateTime)value).toInstant();
+ }
+ if(value instanceof Instant) {
+ return (Instant)value;
+ }
+ return toLocalDateTime(value, dtc).atZone(dtc.getZoneId()).toInstant();
+ }
+
static double toLocalDateDouble(long time) {
time += MILLIS_BETWEEN_EPOCH_AND_1900;
@@ -2191,7 +2193,7 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, ZoneContext
}
}
- static DateTimeFactory getDateTimeFactory(DateTimeType type) {
+ protected static DateTimeFactory getDateTimeFactory(DateTimeType type) {
return ((type == DateTimeType.LOCAL_DATE_TIME) ?
LDT_DATE_TIME_FACTORY : DEF_DATE_TIME_FACTORY);
}
@@ -2676,19 +2678,21 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, ZoneContext
/**
* Factory which handles date/time values appropriately for a DateTimeType.
*/
- static abstract class DateTimeFactory
+ protected static abstract class DateTimeFactory
{
public abstract DateTimeType getType();
public abstract Object fromDateBits(ColumnImpl col, long dateBits);
+ public abstract double toDateDouble(Object value, DateTimeContext dtc);
+
public abstract Object toInternalValue(DatabaseImpl db, Object value);
}
/**
* Factory impl for legacy Date handling.
*/
- static final class DefaultDateTimeFactory extends DateTimeFactory
+ private static final class DefaultDateTimeFactory extends DateTimeFactory
{
@Override
public DateTimeType getType() {
@@ -2703,6 +2707,23 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, ZoneContext
}
@Override
+ public double toDateDouble(Object value, DateTimeContext dtc) {
+ // ZoneId and TimeZone have different rules for older timezones, so we
+ // need to consistently use one or the other depending on the date/time
+ // type
+ long time = 0L;
+ if(value instanceof TemporalAccessor) {
+ time = toInstant((TemporalAccessor)value, dtc).toEpochMilli();
+ } else {
+ time = toDateLong(value);
+ }
+ // seems access stores dates in the local timezone. guess you just
+ // hope you read it in the same timezone in which it was written!
+ time += getToLocalTimeZoneOffset(time, dtc.getTimeZone());
+ return toLocalDateDouble(time);
+ }
+
+ @Override
public Object toInternalValue(DatabaseImpl db, Object value) {
return ((value instanceof Date) ? value :
new Date(toDateLong(value)));
@@ -2712,7 +2733,7 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, ZoneContext
/**
* Factory impl for LocalDateTime handling.
*/
- static final class LDTDateTimeFactory extends DateTimeFactory
+ private static final class LDTDateTimeFactory extends DateTimeFactory
{
@Override
public DateTimeType getType() {
@@ -2725,6 +2746,18 @@ public class ColumnImpl implements Column, Comparable<ColumnImpl>, ZoneContext
}
@Override
+ public double toDateDouble(Object value, DateTimeContext dtc) {
+ // ZoneId and TimeZone have different rules for older timezones, so we
+ // need to consistently use one or the other depending on the date/time
+ // type
+ if(!(value instanceof TemporalAccessor)) {
+ value = Instant.ofEpochMilli(toDateLong(value));
+ }
+ return ColumnImpl.toDateDouble(
+ toLocalDateTime((TemporalAccessor)value, dtc));
+ }
+
+ @Override
public Object toInternalValue(DatabaseImpl db, Object value) {
if(value instanceof TemporalAccessor) {
return toLocalDateTime((TemporalAccessor)value, db);
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
index 1a34dbd..c005651 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
@@ -88,7 +88,7 @@ import org.apache.commons.logging.LogFactory;
* @author Tim McCune
* @usage _intermediate_class_
*/
-public class DatabaseImpl implements Database, ZoneContext
+public class DatabaseImpl implements Database, DateTimeContext
{
private static final Log LOG = LogFactory.getLog(DatabaseImpl.class);
@@ -346,8 +346,7 @@ public class DatabaseImpl implements Database, ZoneContext
/** shared context for evaluating expressions */
private DBEvalContext _evalCtx;
/** factory for the appropriate date/time type */
- private ColumnImpl.DateTimeFactory _dtf =
- ColumnImpl.getDateTimeFactory(DateTimeType.DATE);
+ private ColumnImpl.DateTimeFactory _dtf;
/**
* Open an existing Database. If the existing file is not writeable or the
@@ -537,8 +536,9 @@ public class DatabaseImpl implements Database, ZoneContext
_allowAutoNumInsert = getDefaultAllowAutoNumberInsert();
_evaluateExpressions = getDefaultEvaluateExpressions();
_fileFormat = fileFormat;
- _pageChannel = new PageChannel(channel, closeChannel, _format, autoSync);
setZoneInfo(timeZone, null);
+ _dtf = ColumnImpl.getDateTimeFactory(getDefaultDateTimeType());
+ _pageChannel = new PageChannel(channel, closeChannel, _format, autoSync);
if(provider == null) {
provider = DefaultCodecProvider.INSTANCE;
}
@@ -710,7 +710,8 @@ public class DatabaseImpl implements Database, ZoneContext
_dtf = ColumnImpl.getDateTimeFactory(dateTimeType);
}
- protected ColumnImpl.DateTimeFactory getDateTimeFactory() {
+ @Override
+ public ColumnImpl.DateTimeFactory getDateTimeFactory() {
return _dtf;
}
@@ -2043,16 +2044,8 @@ public class DatabaseImpl implements Database, ZoneContext
*/
public static Table.ColumnOrder getDefaultColumnOrder()
{
- String coProp = System.getProperty(COLUMN_ORDER_PROPERTY);
- if(coProp != null) {
- coProp = coProp.trim();
- if(coProp.length() > 0) {
- return Table.ColumnOrder.valueOf(coProp);
- }
- }
-
- // use default order
- return DEFAULT_COLUMN_ORDER;
+ return getEnumSystemProperty(Table.ColumnOrder.class, COLUMN_ORDER_PROPERTY,
+ DEFAULT_COLUMN_ORDER);
}
/**
@@ -2101,6 +2094,17 @@ public class DatabaseImpl implements Database, ZoneContext
}
/**
+ * Returns the default DateTimeType. This defaults to
+ * {@link DateTimeType#DATE}, but can be overridden using the system
+ * property {@value com.healthmarketscience.jackcess.Database#DATE_TIME_TYPE_PROPERTY}.
+ * @usage _advanced_method_
+ */
+ public static DateTimeType getDefaultDateTimeType() {
+ return getEnumSystemProperty(DateTimeType.class, DATE_TIME_TYPE_PROPERTY,
+ DateTimeType.DATE);
+ }
+
+ /**
* Copies the given db InputStream to the given channel using the most
* efficient means possible.
*/
@@ -2196,6 +2200,19 @@ public class DatabaseImpl implements Database, ZoneContext
return msg + " (Db=" + dbName + ")";
}
+ private static <E extends Enum<E>> E getEnumSystemProperty(
+ Class<E> enumClass, String propName, E defaultValue)
+ {
+ String prop = System.getProperty(propName);
+ if(prop != null) {
+ prop = prop.trim().toUpperCase();
+ if(!prop.isEmpty()) {
+ return Enum.valueOf(enumClass, prop);
+ }
+ }
+ return defaultValue;
+ }
+
/**
* Utility class for storing table page number and actual name.
*/
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/ZoneContext.java b/src/main/java/com/healthmarketscience/jackcess/impl/DateTimeContext.java
index 0134e1f..8045755 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/ZoneContext.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/DateTimeContext.java
@@ -24,9 +24,11 @@ import java.util.TimeZone;
*
* @author James Ahlborn
*/
-interface ZoneContext
+interface DateTimeContext
{
public ZoneId getZoneId();
public TimeZone getTimeZone();
+
+ public ColumnImpl.DateTimeFactory getDateTimeFactory();
}