diff --git a/pgjdbc/src/main/java/org/postgresql/PGProperty.java b/pgjdbc/src/main/java/org/postgresql/PGProperty.java index df969e58fcc84fdc59b6ad292b07cd2fea7cb9ff..b82f911188dd66372b2d3ffa89b9bdac61cf8e41 100644 --- a/pgjdbc/src/main/java/org/postgresql/PGProperty.java +++ b/pgjdbc/src/main/java/org/postgresql/PGProperty.java @@ -536,6 +536,11 @@ public enum PGProperty { * It is used to detect the thread interval of the survival task on the primary node in the high availability scenario. */ HEARTBEAT_PERIOD("heartbeatPeriod", "0", "heartbeat interval time"), + + /** + * It is used to change timestamp parameter in TimestampUtils convert. + */ + TIMESTAMP_NANO_FORMAT("timestampNanoFormat", "0", "0 main's already add nana seconds. 1 mains nano<1000 will not add"), /** * In the scenario where heartbeat maintenance is enabled for the active node, diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java b/pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java index 66a1c341a4ea00885df5ae8fffc8bf04d6b027d2..5003fe27ec7c223314771d5e7aac61e8b21c9886 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java @@ -313,6 +313,7 @@ public class PgConnection implements BaseConnection { return queryExecutor.getTimeZone(); } }); + timestampUtils.setTimestampNanoFormat(PGProperty.TIMESTAMP_NANO_FORMAT.getInteger(info)); // Initialize common queries. // isParameterized==true so full parse is performed and the engine knows the query diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/TimestampUtils.java b/pgjdbc/src/main/java/org/postgresql/jdbc/TimestampUtils.java index 377818c5698a636457e5fea9a1de1e1993a6b7ab..0c57f9f00978d008eb3e9380d9c14fbce0af3013 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/TimestampUtils.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/TimestampUtils.java @@ -59,6 +59,7 @@ public class TimestampUtils { private TimeZone prevDefaultZoneFieldValue; private TimeZone defaultTimeZoneCache; + private int timestampNanoFormat = 0; static { // The expected maximum value is 60 (seconds), so 64 is used "just in case" @@ -130,6 +131,10 @@ public class TimestampUtils { this.usesDouble = usesDouble; this.timeZoneProvider = timeZoneProvider; } + + public void setTimestampNanoFormat(int format) { + this.timestampNanoFormat = format; + } private Calendar getCalendar(int sign, int hr, int min, int sec) { int rawOffset = sign * (((hr * 60 + min) * 60 + sec) * 1000); @@ -661,7 +666,7 @@ public class TimestampUtils { appendDate(sbuf, cal); sbuf.append(' '); - appendTime(sbuf, cal, nanos); + appendTime(sbuf, cal, nanos, timestampNanoFormat); if (withTimeZone) { appendTimeZone(sbuf, cal); } @@ -708,7 +713,7 @@ public class TimestampUtils { sbuf.setLength(0); - appendTime(sbuf, cal, cal.get(Calendar.MILLISECOND) * 1000000); + appendTime(sbuf, cal, cal.get(Calendar.MILLISECOND) * 1000000, timestampNanoFormat); // The 'time' parser for <= 7.3 doesn't like timezones. if (withTimeZone) { @@ -742,11 +747,11 @@ public class TimestampUtils { sb.append(NUMBERS[day]); } - private static void appendTime(StringBuilder sb, Calendar cal, int nanos) { + private static void appendTime(StringBuilder sb, Calendar cal, int nanos, int format) { int hours = cal.get(Calendar.HOUR_OF_DAY); int minutes = cal.get(Calendar.MINUTE); int seconds = cal.get(Calendar.SECOND); - appendTime(sb, hours, minutes, seconds, nanos); + appendTime(sb, hours, minutes, seconds, nanos, format); } /** @@ -759,7 +764,7 @@ public class TimestampUtils { * @param seconds seconds * @param nanos nanoseconds */ - private static void appendTime(StringBuilder sb, int hours, int minutes, int seconds, int nanos) { + private static void appendTime(StringBuilder sb, int hours, int minutes, int seconds, int nanos, int format) { sb.append(NUMBERS[hours]); sb.append(':'); @@ -773,21 +778,24 @@ public class TimestampUtils { // a two digit fractional second, but we don't need to support 7.1 // anymore and getting the version number here is difficult. // - if (nanos < 1000) { + if (nanos < 1000 && format != 0) { return; } sb.append('.'); int len = sb.length(); sb.append(nanos / 1000); // append microseconds - int needZeros = 6 - (sb.length() - len); + final int NANO_BITS = 6; + int needZeros = NANO_BITS - (sb.length() - len); if (needZeros > 0) { sb.insert(len, ZEROS, 0, needZeros); } int end = sb.length() - 1; - while (sb.charAt(end) == '0') { + int needDelete = NANO_BITS - 1; + while (sb.charAt(end) == '0' && needDelete != 0) { sb.deleteCharAt(end); end--; + needDelete --; } } @@ -855,7 +863,7 @@ public class TimestampUtils { // it relies on the fact that appendTime just truncates 000..999 nanosecond part localTime = localTime.plus(ONE_MICROSECOND); } - appendTime(sbuf, localTime); + appendTime(sbuf, localTime, timestampNanoFormat); return sbuf.toString(); } @@ -879,7 +887,7 @@ public class TimestampUtils { LocalDate localDate = localDateTime.toLocalDate(); appendDate(sbuf, localDate); sbuf.append(' '); - appendTime(sbuf, localDateTime.toLocalTime()); + appendTime(sbuf, localDateTime.toLocalTime(), timestampNanoFormat); appendTimeZone(sbuf, offsetDateTime.getOffset()); appendEra(sbuf, localDate); @@ -911,12 +919,12 @@ public class TimestampUtils { appendDate(sb, year, month, day); } - private static void appendTime(StringBuilder sb, LocalTime localTime) { + private static void appendTime(StringBuilder sb, LocalTime localTime, int format) { int hours = localTime.getHour(); int minutes = localTime.getMinute(); int seconds = localTime.getSecond(); int nanos = localTime.getNano(); - appendTime(sb, hours, minutes, seconds, nanos); + appendTime(sb, hours, minutes, seconds, nanos, format); } private void appendTimeZone(StringBuilder sb, java.time.ZoneOffset offset) {