# HG changeset patch # User redestad # Date 1410536053 -7200 # Node ID c840e66313274400f2c29e4996ee1f9e81a62e15 # Parent 85ea379d419a5273382c34b40757fb293748f1e6 8058230: Improve java.sql toString formatting Reviewed-by: lancea diff -r 85ea379d419a -r c840e6631327 jdk/src/java.sql/share/classes/java/sql/Date.java --- a/jdk/src/java.sql/share/classes/java/sql/Date.java Wed Aug 13 18:40:16 2014 +0200 +++ b/jdk/src/java.sql/share/classes/java/sql/Date.java Fri Sep 12 17:34:13 2014 +0200 @@ -27,6 +27,8 @@ import java.time.Instant; import java.time.LocalDate; +import sun.misc.SharedSecrets; +import sun.misc.JavaLangAccess; /** *

A thin wrapper around a millisecond value that allows @@ -42,6 +44,8 @@ */ public class Date extends java.util.Date { + private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); + /** * Constructs a Date object initialized with the given * year, month, and day. @@ -155,17 +159,30 @@ int month = super.getMonth() + 1; int day = super.getDate(); - char buf[] = "2000-00-00".toCharArray(); - buf[0] = Character.forDigit(year/1000,10); - buf[1] = Character.forDigit((year/100)%10,10); - buf[2] = Character.forDigit((year/10)%10,10); - buf[3] = Character.forDigit(year%10,10); - buf[5] = Character.forDigit(month/10,10); - buf[6] = Character.forDigit(month%10,10); - buf[8] = Character.forDigit(day/10,10); - buf[9] = Character.forDigit(day%10,10); + char buf[] = new char[10]; + formatDecimalInt(year, buf, 0, 4); + buf[4] = '-'; + Date.formatDecimalInt(month, buf, 5, 2); + buf[7] = '-'; + Date.formatDecimalInt(day, buf, 8, 2); + + return jla.newStringUnsafe(buf); + } - return new String(buf); + /* + * Formats an unsigned integer into a char array in decimal output format. + * Numbers will be zero-padded or truncated if the string representation + * of the integer is smaller than or exceeds len, respectively. + * + * Should consider moving this to Integer and expose it through + * JavaLangAccess similar to Integer::formatUnsignedInt + */ + protected static void formatDecimalInt(int val, char[] buf, int offset, int len) { + int charPos = offset + len; + do { + buf[--charPos] = (char)('0' + (val % 10)); + val /= 10; + } while (charPos > offset); } // Override all the time operations inherited from java.util.Date; diff -r 85ea379d419a -r c840e6631327 jdk/src/java.sql/share/classes/java/sql/Time.java --- a/jdk/src/java.sql/share/classes/java/sql/Time.java Wed Aug 13 18:40:16 2014 +0200 +++ b/jdk/src/java.sql/share/classes/java/sql/Time.java Fri Sep 12 17:34:13 2014 +0200 @@ -27,6 +27,8 @@ import java.time.Instant; import java.time.LocalTime; +import sun.misc.SharedSecrets; +import sun.misc.JavaLangAccess; /** *

A thin wrapper around the java.util.Date class that allows the JDBC @@ -39,6 +41,8 @@ */ public class Time extends java.util.Date { + private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); + /** * Constructs a Time object initialized with the * given values for the hour, minute, and second. @@ -120,26 +124,15 @@ int hour = super.getHours(); int minute = super.getMinutes(); int second = super.getSeconds(); - String hourString; - String minuteString; - String secondString; - if (hour < 10) { - hourString = "0" + hour; - } else { - hourString = Integer.toString(hour); - } - if (minute < 10) { - minuteString = "0" + minute; - } else { - minuteString = Integer.toString(minute); - } - if (second < 10) { - secondString = "0" + second; - } else { - secondString = Integer.toString(second); - } - return (hourString + ":" + minuteString + ":" + secondString); + char[] buf = new char[8]; + Date.formatDecimalInt(hour, buf, 0, 2); + buf[2] = ':'; + Date.formatDecimalInt(minute, buf, 3, 2); + buf[5] = ':'; + Date.formatDecimalInt(second, buf, 6, 2); + + return jla.newStringUnsafe(buf); } // Override all the date operations inherited from java.util.Date; diff -r 85ea379d419a -r c840e6631327 jdk/src/java.sql/share/classes/java/sql/Timestamp.java --- a/jdk/src/java.sql/share/classes/java/sql/Timestamp.java Wed Aug 13 18:40:16 2014 +0200 +++ b/jdk/src/java.sql/share/classes/java/sql/Timestamp.java Fri Sep 12 17:34:13 2014 +0200 @@ -27,7 +27,8 @@ import java.time.Instant; import java.time.LocalDateTime; -import java.util.StringTokenizer; +import sun.misc.SharedSecrets; +import sun.misc.JavaLangAccess; /** *

A thin wrapper around java.util.Date that allows @@ -71,6 +72,8 @@ */ public class Timestamp extends java.util.Date { + private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); + /** * Constructs a Timestamp object initialized * with the given values. @@ -262,95 +265,41 @@ * yyyy-mm-dd hh:mm:ss.fffffffff format */ @SuppressWarnings("deprecation") - public String toString () { - + public String toString() { int year = super.getYear() + 1900; int month = super.getMonth() + 1; int day = super.getDate(); int hour = super.getHours(); int minute = super.getMinutes(); int second = super.getSeconds(); - String yearString; - String monthString; - String dayString; - String hourString; - String minuteString; - String secondString; - String nanosString; - String zeros = "000000000"; - String yearZeros = "0000"; - StringBuffer timestampBuf; - if (year < 1000) { - // Add leading zeros - yearString = "" + year; - yearString = yearZeros.substring(0, (4-yearString.length())) + - yearString; - } else { - yearString = "" + year; - } - if (month < 10) { - monthString = "0" + month; - } else { - monthString = Integer.toString(month); - } - if (day < 10) { - dayString = "0" + day; + int trailingZeros = 0; + int tmpNanos = nanos; + if (tmpNanos == 0) { + trailingZeros = 8; } else { - dayString = Integer.toString(day); - } - if (hour < 10) { - hourString = "0" + hour; - } else { - hourString = Integer.toString(hour); - } - if (minute < 10) { - minuteString = "0" + minute; - } else { - minuteString = Integer.toString(minute); - } - if (second < 10) { - secondString = "0" + second; - } else { - secondString = Integer.toString(second); - } - if (nanos == 0) { - nanosString = "0"; - } else { - nanosString = Integer.toString(nanos); - - // Add leading zeros - nanosString = zeros.substring(0, (9-nanosString.length())) + - nanosString; - - // Truncate trailing zeros - char[] nanosChar = new char[nanosString.length()]; - nanosString.getChars(0, nanosString.length(), nanosChar, 0); - int truncIndex = 8; - while (nanosChar[truncIndex] == '0') { - truncIndex--; + while (tmpNanos % 10 == 0) { + tmpNanos /= 10; + trailingZeros++; } - - nanosString = new String(nanosChar, 0, truncIndex + 1); } - // do a string buffer here instead. - timestampBuf = new StringBuffer(20+nanosString.length()); - timestampBuf.append(yearString); - timestampBuf.append("-"); - timestampBuf.append(monthString); - timestampBuf.append("-"); - timestampBuf.append(dayString); - timestampBuf.append(" "); - timestampBuf.append(hourString); - timestampBuf.append(":"); - timestampBuf.append(minuteString); - timestampBuf.append(":"); - timestampBuf.append(secondString); - timestampBuf.append("."); - timestampBuf.append(nanosString); + char[] buf = new char[29 - trailingZeros]; + Date.formatDecimalInt(year, buf, 0, 4); + buf[4] = '-'; + Date.formatDecimalInt(month, buf, 5, 2); + buf[7] = '-'; + Date.formatDecimalInt(day, buf, 8, 2); + buf[10] = ' '; + Date.formatDecimalInt(hour, buf, 11, 2); + buf[13] = ':'; + Date.formatDecimalInt(minute, buf, 14, 2); + buf[16] = ':'; + Date.formatDecimalInt(second, buf, 17, 2); + buf[19] = '.'; + Date.formatDecimalInt(tmpNanos, buf, 20, 9 - trailingZeros); - return (timestampBuf.toString()); + return jla.newStringUnsafe(buf); } /**