From a0b436ce4d1ad7d75feea5d6acf1d0e35039d12b Mon Sep 17 00:00:00 2001 From: Dai MIKURUBE Date: Thu, 20 Aug 2020 11:23:13 +0900 Subject: [PATCH] Minimize use of java.util.Calendar --- .../org/embulk/output/jdbc/BatchInsert.java | 8 +- .../output/jdbc/StandardBatchInsert.java | 21 +++-- .../jdbc/setter/ColumnSetterFactory.java | 26 +++--- .../jdbc/setter/PassThroughColumnSetter.java | 10 +- .../jdbc/setter/SqlDateColumnSetter.java | 10 +- .../jdbc/setter/SqlTimeColumnSetter.java | 10 +- .../jdbc/setter/SqlTimestampColumnSetter.java | 10 +- .../output/oracle/DirectBatchInsert.java | 10 +- .../AbstractPostgreSQLCopyBatchInsert.java | 93 +++++++++++++++---- .../output/sqlserver/NativeBatchInsert.java | 14 +-- .../setter/SQLServerColumnSetterFactory.java | 4 +- .../setter/SQLServerSqlTimeColumnSetter.java | 8 +- 12 files changed, 143 insertions(+), 81 deletions(-) diff --git a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/BatchInsert.java b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/BatchInsert.java index edb3d1b7..a526132e 100644 --- a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/BatchInsert.java +++ b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/BatchInsert.java @@ -1,10 +1,10 @@ package org.embulk.output.jdbc; import java.math.BigDecimal; -import java.util.Calendar; import java.io.IOException; import java.sql.SQLException; import java.time.Instant; +import java.time.ZoneId; public interface BatchInsert { @@ -47,9 +47,9 @@ public interface BatchInsert public void setBytes(byte[] v) throws IOException, SQLException; - public void setSqlDate(Instant v, Calendar cal) throws IOException, SQLException; + public void setSqlDate(Instant v, ZoneId zone) throws IOException, SQLException; - public void setSqlTime(Instant v, Calendar cal) throws IOException, SQLException; + public void setSqlTime(Instant v, ZoneId zone) throws IOException, SQLException; - public void setSqlTimestamp(Instant v, Calendar cal) throws IOException, SQLException; + public void setSqlTimestamp(Instant v, ZoneId zone) throws IOException, SQLException; } diff --git a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/StandardBatchInsert.java b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/StandardBatchInsert.java index de3f2c3b..6b0ce3ba 100644 --- a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/StandardBatchInsert.java +++ b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/StandardBatchInsert.java @@ -1,14 +1,14 @@ package org.embulk.output.jdbc; -import java.util.Calendar; import java.io.IOException; import java.math.BigDecimal; import java.sql.BatchUpdateException; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.sql.Date; import java.sql.Time; import java.time.Instant; +import java.time.ZoneId; +import java.util.Locale; import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -184,28 +184,31 @@ public void setBytes(byte[] v) throws IOException, SQLException nextColumn(v.length + 4); } - public void setSqlDate(final Instant v, final Calendar cal) throws IOException, SQLException + public void setSqlDate(final Instant v, final ZoneId zone) throws IOException, SQLException { // JavaDoc of java.sql.Time says: // >> To conform with the definition of SQL DATE, the millisecond values wrapped by a java.sql.Date instance must be 'normalized' by setting the hours, minutes, seconds, and milliseconds to zero in the particular time zone with which the instance is associated. + final java.util.Calendar cal = java.util.Calendar.getInstance(java.util.TimeZone.getTimeZone(zone), Locale.ENGLISH); cal.setTimeInMillis(v.getEpochSecond() * 1000); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.HOUR_OF_DAY, 0); - Date normalized = new Date(cal.getTimeInMillis()); + cal.set(java.util.Calendar.SECOND, 0); + cal.set(java.util.Calendar.MINUTE, 0); + cal.set(java.util.Calendar.HOUR_OF_DAY, 0); + final java.sql.Date normalized = new java.sql.Date(cal.getTimeInMillis()); batch.setDate(index, normalized, cal); nextColumn(32); } - public void setSqlTime(final Instant v, final Calendar cal) throws IOException, SQLException + public void setSqlTime(final Instant v, final ZoneId zone) throws IOException, SQLException { + final java.util.Calendar cal = java.util.Calendar.getInstance(java.util.TimeZone.getTimeZone(zone), Locale.ENGLISH); Time t = new Time(v.toEpochMilli()); batch.setTime(index, t, cal); nextColumn(32); } - public void setSqlTimestamp(final Instant v, final Calendar cal) throws IOException, SQLException + public void setSqlTimestamp(final Instant v, final ZoneId zone) throws IOException, SQLException { + final java.util.Calendar cal = java.util.Calendar.getInstance(java.util.TimeZone.getTimeZone(zone), Locale.ENGLISH); java.sql.Timestamp t = new java.sql.Timestamp(v.toEpochMilli()); t.setNanos(v.getNano()); batch.setTimestamp(index, t, cal); diff --git a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/ColumnSetterFactory.java b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/ColumnSetterFactory.java index d4db1015..4518fb49 100644 --- a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/ColumnSetterFactory.java +++ b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/ColumnSetterFactory.java @@ -1,8 +1,6 @@ package org.embulk.output.jdbc.setter; -import java.util.Calendar; -import java.util.Locale; -import java.util.TimeZone; +import java.time.ZoneId; import java.util.Optional; import java.sql.Types; import org.embulk.config.ConfigSource; @@ -59,11 +57,11 @@ public ColumnSetter newColumnSetter(JdbcColumn column, JdbcColumnOption option) case "nstring": return new NStringColumnSetter(batch, column, newDefaultValueSetter(column, option), newTimestampFormatter(option)); case "date": - return new SqlDateColumnSetter(batch, column, newDefaultValueSetter(column, option), newCalendar(option)); + return new SqlDateColumnSetter(batch, column, newDefaultValueSetter(column, option), newZoneId(option)); case "time": - return new SqlTimeColumnSetter(batch, column, newDefaultValueSetter(column, option), newCalendar(option)); + return new SqlTimeColumnSetter(batch, column, newDefaultValueSetter(column, option), newZoneId(option)); case "timestamp": - return new SqlTimestampColumnSetter(batch, column, newDefaultValueSetter(column, option), newCalendar(option)); + return new SqlTimestampColumnSetter(batch, column, newDefaultValueSetter(column, option), newZoneId(option)); case "decimal": return new BigDecimalColumnSetter(batch, column, newDefaultValueSetter(column, option)); case "json": @@ -71,25 +69,25 @@ public ColumnSetter newColumnSetter(JdbcColumn column, JdbcColumnOption option) case "null": return new NullColumnSetter(batch, column, newDefaultValueSetter(column, option)); case "pass": - return new PassThroughColumnSetter(batch, column, newDefaultValueSetter(column, option), newCalendar(option)); + return new PassThroughColumnSetter(batch, column, newDefaultValueSetter(column, option), newZoneId(option)); default: throw new ConfigException(String.format("Unknown value_type '%s' for column '%s'", option.getValueType(), column.getName())); } } - protected TimestampFormatter newTimestampFormatter(JdbcColumnOption option) + protected final TimestampFormatter newTimestampFormatter(JdbcColumnOption option) { final String format = option.getTimestampFormat(); final String timezone = option.getTimeZone().orElse(this.defaultTimeZone); return TimestampFormatter.builder(format, true).setDefaultZoneFromString(timezone).build(); } - protected Calendar newCalendar(JdbcColumnOption option) + protected final ZoneId newZoneId(final JdbcColumnOption option) { - return Calendar.getInstance(TimeZone.getTimeZone(getTimeZone(option)), Locale.ENGLISH); + return ZoneId.of(this.getTimeZone(option)); } - protected String getTimeZone(JdbcColumnOption option) + protected final String getTimeZone(JdbcColumnOption option) { return option.getTimeZone().orElse(defaultTimeZone); } @@ -151,11 +149,11 @@ public ColumnSetter newCoalesceColumnSetter(JdbcColumn column, JdbcColumnOption // Time case Types.DATE: - return new SqlDateColumnSetter(batch, column, newDefaultValueSetter(column, option), newCalendar(option)); + return new SqlDateColumnSetter(batch, column, newDefaultValueSetter(column, option), newZoneId(option)); case Types.TIME: - return new SqlTimeColumnSetter(batch, column, newDefaultValueSetter(column, option), newCalendar(option)); + return new SqlTimeColumnSetter(batch, column, newDefaultValueSetter(column, option), newZoneId(option)); case Types.TIMESTAMP: - return new SqlTimestampColumnSetter(batch, column, newDefaultValueSetter(column, option), newCalendar(option)); + return new SqlTimestampColumnSetter(batch, column, newDefaultValueSetter(column, option), newZoneId(option)); // Null case Types.NULL: diff --git a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/PassThroughColumnSetter.java b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/PassThroughColumnSetter.java index c81ee815..51963f1c 100644 --- a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/PassThroughColumnSetter.java +++ b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/PassThroughColumnSetter.java @@ -1,9 +1,9 @@ package org.embulk.output.jdbc.setter; -import java.util.Calendar; import java.io.IOException; import java.sql.SQLException; import java.time.Instant; +import java.time.ZoneId; import org.embulk.output.jdbc.JdbcColumn; import org.embulk.output.jdbc.BatchInsert; @@ -12,14 +12,14 @@ public class PassThroughColumnSetter extends ColumnSetter { - private final Calendar calendar; + private final ZoneId zone; public PassThroughColumnSetter(BatchInsert batch, JdbcColumn column, DefaultValueSetter defaultValue, - Calendar calendar) + ZoneId zone) { super(batch, column, defaultValue); - this.calendar = calendar; + this.zone = zone; } @Override @@ -55,7 +55,7 @@ public void stringValue(String v) throws IOException, SQLException @Override public void timestampValue(final Instant v) throws IOException, SQLException { - batch.setSqlTimestamp(v, calendar); + batch.setSqlTimestamp(v, this.zone); } @Override diff --git a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/SqlDateColumnSetter.java b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/SqlDateColumnSetter.java index 5219e5d7..a50c57c1 100644 --- a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/SqlDateColumnSetter.java +++ b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/SqlDateColumnSetter.java @@ -1,9 +1,9 @@ package org.embulk.output.jdbc.setter; -import java.util.Calendar; import java.io.IOException; import java.sql.SQLException; import java.time.Instant; +import java.time.ZoneId; import org.embulk.output.jdbc.JdbcColumn; import org.embulk.output.jdbc.BatchInsert; @@ -12,14 +12,14 @@ public class SqlDateColumnSetter extends ColumnSetter { - protected final Calendar calendar; + protected final ZoneId zone; public SqlDateColumnSetter(BatchInsert batch, JdbcColumn column, DefaultValueSetter defaultValue, - Calendar calendar) + ZoneId zone) { super(batch, column, defaultValue); - this.calendar = calendar; + this.zone = zone; } @Override @@ -55,7 +55,7 @@ public void stringValue(String v) throws IOException, SQLException @Override public void timestampValue(final Instant v) throws IOException, SQLException { - batch.setSqlDate(v, calendar); + batch.setSqlDate(v, this.zone); } @Override diff --git a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/SqlTimeColumnSetter.java b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/SqlTimeColumnSetter.java index 12575dda..fccc78c2 100644 --- a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/SqlTimeColumnSetter.java +++ b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/SqlTimeColumnSetter.java @@ -1,9 +1,9 @@ package org.embulk.output.jdbc.setter; -import java.util.Calendar; import java.io.IOException; import java.sql.SQLException; import java.time.Instant; +import java.time.ZoneId; import org.embulk.output.jdbc.JdbcColumn; import org.embulk.output.jdbc.BatchInsert; @@ -12,14 +12,14 @@ public class SqlTimeColumnSetter extends ColumnSetter { - protected final Calendar calendar; + protected final ZoneId zone; public SqlTimeColumnSetter(BatchInsert batch, JdbcColumn column, DefaultValueSetter defaultValue, - Calendar calendar) + ZoneId zone) { super(batch, column, defaultValue); - this.calendar = calendar; + this.zone = zone; } @Override @@ -55,7 +55,7 @@ public void stringValue(String v) throws IOException, SQLException @Override public void timestampValue(final Instant v) throws IOException, SQLException { - batch.setSqlTime(v, calendar); + batch.setSqlTime(v, this.zone); } @Override diff --git a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/SqlTimestampColumnSetter.java b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/SqlTimestampColumnSetter.java index 6f885f8c..b988a74b 100644 --- a/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/SqlTimestampColumnSetter.java +++ b/embulk-output-jdbc/src/main/java/org/embulk/output/jdbc/setter/SqlTimestampColumnSetter.java @@ -1,9 +1,9 @@ package org.embulk.output.jdbc.setter; -import java.util.Calendar; import java.io.IOException; import java.sql.SQLException; import java.time.Instant; +import java.time.ZoneId; import org.embulk.output.jdbc.JdbcColumn; import org.embulk.output.jdbc.BatchInsert; @@ -12,14 +12,14 @@ public class SqlTimestampColumnSetter extends ColumnSetter { - protected final Calendar calendar; + protected final ZoneId zone; public SqlTimestampColumnSetter(BatchInsert batch, JdbcColumn column, DefaultValueSetter defaultValue, - Calendar calendar) + ZoneId zone) { super(batch, column, defaultValue); - this.calendar = calendar; + this.zone = zone; } @Override @@ -55,7 +55,7 @@ public void stringValue(String v) throws IOException, SQLException @Override public void timestampValue(final Instant v) throws IOException, SQLException { - batch.setSqlTimestamp(v, calendar); + batch.setSqlTimestamp(v, this.zone); } @Override diff --git a/embulk-output-oracle/src/main/java/org/embulk/output/oracle/DirectBatchInsert.java b/embulk-output-oracle/src/main/java/org/embulk/output/oracle/DirectBatchInsert.java index 49943378..371bed5a 100644 --- a/embulk-output-oracle/src/main/java/org/embulk/output/oracle/DirectBatchInsert.java +++ b/embulk-output-oracle/src/main/java/org/embulk/output/oracle/DirectBatchInsert.java @@ -7,9 +7,9 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.time.Instant; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; -import java.util.Calendar; import java.util.List; import org.embulk.output.jdbc.BatchInsert; @@ -260,24 +260,24 @@ public void setBytes(byte[] v) throws IOException, SQLException } @Override - public void setSqlDate(final Instant v, final Calendar calendar) throws IOException, SQLException + public void setSqlDate(final Instant v, final ZoneId zone) throws IOException, SQLException { throw new SQLException("Unsupported"); } @Override - public void setSqlTime(final Instant v, final Calendar calendar) throws IOException, SQLException + public void setSqlTime(final Instant v, final ZoneId zone) throws IOException, SQLException { throw new SQLException("Unsupported"); } @Override - public void setSqlTimestamp(final Instant v, final Calendar calendar) throws IOException, SQLException + public void setSqlTimestamp(final Instant v, final ZoneId zone) throws IOException, SQLException { java.sql.Timestamp t = new java.sql.Timestamp(v.toEpochMilli()); t.setNanos(v.getNano()); DateFormat format = formats[buffer.getCurrentColumn()]; - format.setTimeZone(calendar.getTimeZone()); + format.setTimeZone(java.util.TimeZone.getTimeZone(zone)); buffer.addValue(format.format(t)); } } diff --git a/embulk-output-postgresql/src/main/java/org/embulk/output/postgresql/AbstractPostgreSQLCopyBatchInsert.java b/embulk-output-postgresql/src/main/java/org/embulk/output/postgresql/AbstractPostgreSQLCopyBatchInsert.java index 80c1cb33..b1c6f522 100644 --- a/embulk-output-postgresql/src/main/java/org/embulk/output/postgresql/AbstractPostgreSQLCopyBatchInsert.java +++ b/embulk-output-postgresql/src/main/java/org/embulk/output/postgresql/AbstractPostgreSQLCopyBatchInsert.java @@ -1,6 +1,5 @@ package org.embulk.output.postgresql; -import java.util.Calendar; import java.util.Locale; import java.io.File; import java.io.FileOutputStream; @@ -10,7 +9,14 @@ import java.nio.charset.Charset; import java.math.BigDecimal; import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import org.embulk.output.jdbc.BatchInsert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public abstract class AbstractPostgreSQLCopyBatchInsert implements BatchInsert @@ -26,6 +32,14 @@ public abstract class AbstractPostgreSQLCopyBatchInsert protected int index; protected int batchRows; + private static final Logger logger = LoggerFactory.getLogger(AbstractPostgreSQLCopyBatchInsert.class); + + private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern( + "HH':'mm':'ss'.'SSSSSS", Locale.ROOT); + private static final DateTimeFormatter TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern( + "uuuu'/'MM'/'DD' 'HH':'mm':'ss'.'SSSSSSZZZ", Locale.ROOT); + + protected AbstractPostgreSQLCopyBatchInsert() throws IOException { this.index = 0; @@ -157,34 +171,66 @@ public void setBytes(byte[] v) throws IOException setEscapedString(String.valueOf(v)); } - public void setSqlDate(final Instant v, final Calendar cal) throws IOException + public void setSqlDate(final Instant v, final ZoneId zone) throws IOException { appendDelimiter(); + + final java.util.Calendar cal = java.util.Calendar.getInstance(java.util.TimeZone.getTimeZone(zone), Locale.ENGLISH); cal.setTimeInMillis(v.getEpochSecond() * 1000); String f = String.format(Locale.ENGLISH, "%02d-%02d-%02d", - cal.get(Calendar.YEAR), - cal.get(Calendar.MONTH) + 1, - cal.get(Calendar.DAY_OF_MONTH)); + cal.get(java.util.Calendar.YEAR), + cal.get(java.util.Calendar.MONTH) + 1, + cal.get(java.util.Calendar.DAY_OF_MONTH)); + + // Creating another formatted string based on java.time. It will replace the java-util-based one once confirmed. + final String formatted; + final ZoneId zoneNormalized = zone.normalized(); + if (zoneNormalized instanceof ZoneOffset) { + formatted = OffsetDateTime.ofInstant(v, (ZoneOffset) zoneNormalized).format(DateTimeFormatter.ISO_LOCAL_DATE); + } else { + formatted = ZonedDateTime.ofInstant(v, zone).format(DateTimeFormatter.ISO_LOCAL_DATE); + } + if (!f.equals(formatted)) { + logger.warn("Different formatted date from java.time-based one: '{}' v.s. '{}'", f, formatted); + } + writer.write(f); } - public void setSqlTime(final Instant v, final Calendar cal) throws IOException + public void setSqlTime(final Instant v, final ZoneId zone) throws IOException { appendDelimiter(); + + final java.util.Calendar cal = java.util.Calendar.getInstance(java.util.TimeZone.getTimeZone(zone), Locale.ENGLISH); cal.setTimeInMillis(v.getEpochSecond() * 1000); String f = String.format(Locale.ENGLISH, "%02d:%02d:%02d.%06d", - cal.get(Calendar.HOUR_OF_DAY), - cal.get(Calendar.MINUTE), - cal.get(Calendar.SECOND), + cal.get(java.util.Calendar.HOUR_OF_DAY), + cal.get(java.util.Calendar.MINUTE), + cal.get(java.util.Calendar.SECOND), v.getNano() / 1000); + + // Creating another formatted string based on java.time. It will replace the java-util-based one once confirmed. + final String formatted; + final ZoneId zoneNormalized = zone.normalized(); + if (zoneNormalized instanceof ZoneOffset) { + formatted = OffsetDateTime.ofInstant(v, (ZoneOffset) zoneNormalized).format(TIME_FORMATTER); + } else { + formatted = ZonedDateTime.ofInstant(v, zone).format(TIME_FORMATTER); + } + if (!f.equals(formatted)) { + logger.warn("Different formatted date from java.time-based one: '{}' v.s. '{}'", f, formatted); + } + writer.write(f); } - public void setSqlTimestamp(final Instant v, final Calendar cal) throws IOException + public void setSqlTimestamp(final Instant v, final ZoneId zone) throws IOException { appendDelimiter(); + + final java.util.Calendar cal = java.util.Calendar.getInstance(java.util.TimeZone.getTimeZone(zone), Locale.ENGLISH); cal.setTimeInMillis(v.getEpochSecond() * 1000); - int zoneOffset = cal.get(Calendar.ZONE_OFFSET) / 1000 / 60; // zone offset considering DST in minute + int zoneOffset = cal.get(java.util.Calendar.ZONE_OFFSET) / 1000 / 60; // zone offset considering DST in minute String offset; if (zoneOffset >= 0) { offset = String.format(Locale.ENGLISH, "+%02d%02d", zoneOffset / 60, zoneOffset % 60); @@ -192,14 +238,27 @@ public void setSqlTimestamp(final Instant v, final Calendar cal) throws IOExcept offset = String.format(Locale.ENGLISH, "-%02d%02d", -zoneOffset / 60, -zoneOffset % 60); } String f = String.format(Locale.ENGLISH, "%d-%02d-%02d %02d:%02d:%02d.%06d%s", - cal.get(Calendar.YEAR), - cal.get(Calendar.MONTH) + 1, - cal.get(Calendar.DAY_OF_MONTH), - cal.get(Calendar.HOUR_OF_DAY), - cal.get(Calendar.MINUTE), - cal.get(Calendar.SECOND), + cal.get(java.util.Calendar.YEAR), + cal.get(java.util.Calendar.MONTH) + 1, + cal.get(java.util.Calendar.DAY_OF_MONTH), + cal.get(java.util.Calendar.HOUR_OF_DAY), + cal.get(java.util.Calendar.MINUTE), + cal.get(java.util.Calendar.SECOND), v.getNano() / 1000, offset); + + // Creating another formatted string based on java.time. It will replace the java-util-based one once confirmed. + final String formatted; + final ZoneId zoneNormalized = zone.normalized(); + if (zoneNormalized instanceof ZoneOffset) { + formatted = OffsetDateTime.ofInstant(v, (ZoneOffset) zoneNormalized).format(TIMESTAMP_FORMATTER); + } else { + formatted = ZonedDateTime.ofInstant(v, zone).format(TIMESTAMP_FORMATTER); + } + if (!f.equals(formatted)) { + logger.warn("Different formatted date from java.time-based one: '{}' v.s. '{}'", f, formatted); + } + writer.write(f); } diff --git a/embulk-output-sqlserver/src/main/java/org/embulk/output/sqlserver/NativeBatchInsert.java b/embulk-output-sqlserver/src/main/java/org/embulk/output/sqlserver/NativeBatchInsert.java index c8917021..68898569 100644 --- a/embulk-output-sqlserver/src/main/java/org/embulk/output/sqlserver/NativeBatchInsert.java +++ b/embulk-output-sqlserver/src/main/java/org/embulk/output/sqlserver/NativeBatchInsert.java @@ -7,7 +7,8 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.time.Instant; -import java.util.Calendar; +import java.time.ZoneId; +import java.util.Locale; import java.util.Optional; import org.embulk.output.jdbc.BatchInsert; @@ -192,20 +193,21 @@ public void setBytes(byte[] v) throws IOException, SQLException } @Override - public void setSqlDate(final Instant v, final Calendar cal) throws IOException, SQLException + public void setSqlDate(final Instant v, final ZoneId zone) throws IOException, SQLException { - setSqlTimestamp(v, cal); + setSqlTimestamp(v, zone); } @Override - public void setSqlTime(final Instant v, final Calendar cal) throws IOException, SQLException + public void setSqlTime(final Instant v, final ZoneId zone) throws IOException, SQLException { - setSqlTimestamp(v, cal); + setSqlTimestamp(v, zone); } @Override - public void setSqlTimestamp(final Instant v, final Calendar cal) throws IOException, SQLException + public void setSqlTimestamp(final Instant v, final ZoneId zone) throws IOException, SQLException { + final java.util.Calendar cal = java.util.Calendar.getInstance(java.util.TimeZone.getTimeZone(zone), Locale.ENGLISH); int columnIndex = nextColumnIndex(); DateFormat format = formats[columnIndex - 1]; format.setCalendar(cal); diff --git a/embulk-output-sqlserver/src/main/java/org/embulk/output/sqlserver/setter/SQLServerColumnSetterFactory.java b/embulk-output-sqlserver/src/main/java/org/embulk/output/sqlserver/setter/SQLServerColumnSetterFactory.java index ee309571..613440a9 100644 --- a/embulk-output-sqlserver/src/main/java/org/embulk/output/sqlserver/setter/SQLServerColumnSetterFactory.java +++ b/embulk-output-sqlserver/src/main/java/org/embulk/output/sqlserver/setter/SQLServerColumnSetterFactory.java @@ -25,7 +25,7 @@ public ColumnSetter newCoalesceColumnSetter(JdbcColumn column, JdbcColumnOption return new SQLServerByteColumnSetter(batch, column, newDefaultValueSetter(column, option)); case Types.TIME: - return new SQLServerSqlTimeColumnSetter(batch, column, newDefaultValueSetter(column, option), newCalendar(option)); + return new SQLServerSqlTimeColumnSetter(batch, column, newDefaultValueSetter(column, option), newZoneId(option)); default: return super.newCoalesceColumnSetter(column, option); @@ -40,7 +40,7 @@ public ColumnSetter newColumnSetter(JdbcColumn column, JdbcColumnOption option) return new SQLServerByteColumnSetter(batch, column, newDefaultValueSetter(column, option)); case "time": - return new SQLServerSqlTimeColumnSetter(batch, column, newDefaultValueSetter(column, option), newCalendar(option)); + return new SQLServerSqlTimeColumnSetter(batch, column, newDefaultValueSetter(column, option), newZoneId(option)); case "coerce": switch (column.getSimpleTypeName().toLowerCase()) { diff --git a/embulk-output-sqlserver/src/main/java/org/embulk/output/sqlserver/setter/SQLServerSqlTimeColumnSetter.java b/embulk-output-sqlserver/src/main/java/org/embulk/output/sqlserver/setter/SQLServerSqlTimeColumnSetter.java index 77a27b92..c4b71ece 100644 --- a/embulk-output-sqlserver/src/main/java/org/embulk/output/sqlserver/setter/SQLServerSqlTimeColumnSetter.java +++ b/embulk-output-sqlserver/src/main/java/org/embulk/output/sqlserver/setter/SQLServerSqlTimeColumnSetter.java @@ -2,8 +2,8 @@ import java.io.IOException; import java.sql.SQLException; -import java.util.Calendar; import java.time.Instant; +import java.time.ZoneId; import org.embulk.output.jdbc.BatchInsert; import org.embulk.output.jdbc.JdbcColumn; @@ -15,15 +15,15 @@ public class SQLServerSqlTimeColumnSetter { public SQLServerSqlTimeColumnSetter(BatchInsert batch, JdbcColumn column, DefaultValueSetter defaultValue, - Calendar calendar) + ZoneId zone) { - super(batch, column, defaultValue, calendar); + super(batch, column, defaultValue, zone); } @Override public void timestampValue(final Instant v) throws IOException, SQLException { // fractional precision of SQLServer TIME is 7, but that of java.sql.Time is only 3. - batch.setSqlTimestamp(v, calendar); + batch.setSqlTimestamp(v, this.zone); } }