src/share/classes/java/sql/Timestamp.java

Print this page
rev 10459 : 8055055: Improve numeric parsing in java.sql


 154     private int nanos;
 155 
 156     /**
 157      * Converts a <code>String</code> object in JDBC timestamp escape format to a
 158      * <code>Timestamp</code> value.
 159      *
 160      * @param s timestamp in format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>.  The
 161      * fractional seconds may be omitted. The leading zero for <code>mm</code>
 162      * and <code>dd</code> may also be omitted.
 163      *
 164      * @return corresponding <code>Timestamp</code> value
 165      * @exception java.lang.IllegalArgumentException if the given argument
 166      * does not have the format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>
 167      */
 168     public static Timestamp valueOf(String s) {
 169         final int YEAR_LENGTH = 4;
 170         final int MONTH_LENGTH = 2;
 171         final int DAY_LENGTH = 2;
 172         final int MAX_MONTH = 12;
 173         final int MAX_DAY = 31;
 174         String date_s;
 175         String time_s;
 176         String nanos_s;
 177         int year = 0;
 178         int month = 0;
 179         int day = 0;
 180         int hour;
 181         int minute;
 182         int second;
 183         int a_nanos = 0;
 184         int firstDash;
 185         int secondDash;
 186         int dividingSpace;
 187         int firstColon = 0;
 188         int secondColon = 0;
 189         int period = 0;
 190         String formatError = "Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]";
 191         String zeros = "000000000";
 192         String delimiterDate = "-";
 193         String delimiterTime = ":";
 194 
 195         if (s == null) throw new java.lang.IllegalArgumentException("null string");
 196 
 197         // Split the string into date and time components
 198         s = s.trim();
 199         dividingSpace = s.indexOf(' ');
 200         if (dividingSpace > 0) {
 201             date_s = s.substring(0,dividingSpace);
 202             time_s = s.substring(dividingSpace+1);
 203         } else {
 204             throw new java.lang.IllegalArgumentException(formatError);
 205         }
 206 
 207         // Parse the date
 208         firstDash = date_s.indexOf('-');
 209         secondDash = date_s.indexOf('-', firstDash+1);
 210 
 211         // Parse the time
 212         if (time_s == null)
 213             throw new java.lang.IllegalArgumentException(formatError);
 214         firstColon = time_s.indexOf(':');
 215         secondColon = time_s.indexOf(':', firstColon+1);
 216         period = time_s.indexOf('.', secondColon+1);
 217 
 218         // Convert the date
 219         boolean parsedDate = false;
 220         if ((firstDash > 0) && (secondDash > 0) && (secondDash < date_s.length() - 1)) {
 221             String yyyy = date_s.substring(0, firstDash);
 222             String mm = date_s.substring(firstDash + 1, secondDash);
 223             String dd = date_s.substring(secondDash + 1);
 224             if (yyyy.length() == YEAR_LENGTH &&
 225                     (mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&
 226                     (dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {
 227                  year = Integer.parseInt(yyyy);
 228                  month = Integer.parseInt(mm);
 229                  day = Integer.parseInt(dd);
 230 
 231                 if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
 232                     parsedDate = true;
 233                 }
 234             }
 235         }
 236         if (! parsedDate) {
 237             throw new java.lang.IllegalArgumentException(formatError);
 238         }
 239 
 240         // Convert the time; default missing nanos
 241         if ((firstColon > 0) & (secondColon > 0) &
 242             (secondColon < time_s.length()-1)) {
 243             hour = Integer.parseInt(time_s.substring(0, firstColon));
 244             minute =
 245                 Integer.parseInt(time_s.substring(firstColon+1, secondColon));
 246             if ((period > 0) & (period < time_s.length()-1)) {
 247                 second =
 248                     Integer.parseInt(time_s.substring(secondColon+1, period));
 249                 nanos_s = time_s.substring(period+1);
 250                 if (nanos_s.length() > 9)
 251                     throw new java.lang.IllegalArgumentException(formatError);
 252                 if (!Character.isDigit(nanos_s.charAt(0)))
 253                     throw new java.lang.IllegalArgumentException(formatError);
 254                 nanos_s = nanos_s + zeros.substring(0,9-nanos_s.length());
 255                 a_nanos = Integer.parseInt(nanos_s);

 256             } else if (period > 0) {
 257                 throw new java.lang.IllegalArgumentException(formatError);
 258             } else {
 259                 second = Integer.parseInt(time_s.substring(secondColon+1));
 260             }
 261         } else {
 262             throw new java.lang.IllegalArgumentException(formatError);
 263         }
 264 
 265         return new Timestamp(year - 1900, month - 1, day, hour, minute, second, a_nanos);
 266     }
 267 
 268     /**
 269      * Formats a timestamp in JDBC timestamp escape format.
 270      *         <code>yyyy-mm-dd hh:mm:ss.fffffffff</code>,
 271      * where <code>ffffffffff</code> indicates nanoseconds.
 272      *
 273      * @return a <code>String</code> object in
 274      *           <code>yyyy-mm-dd hh:mm:ss.fffffffff</code> format
 275      */
 276     @SuppressWarnings("deprecation")
 277     public String toString () {
 278 
 279         int year = super.getYear() + 1900;




 154     private int nanos;
 155 
 156     /**
 157      * Converts a <code>String</code> object in JDBC timestamp escape format to a
 158      * <code>Timestamp</code> value.
 159      *
 160      * @param s timestamp in format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>.  The
 161      * fractional seconds may be omitted. The leading zero for <code>mm</code>
 162      * and <code>dd</code> may also be omitted.
 163      *
 164      * @return corresponding <code>Timestamp</code> value
 165      * @exception java.lang.IllegalArgumentException if the given argument
 166      * does not have the format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>
 167      */
 168     public static Timestamp valueOf(String s) {
 169         final int YEAR_LENGTH = 4;
 170         final int MONTH_LENGTH = 2;
 171         final int DAY_LENGTH = 2;
 172         final int MAX_MONTH = 12;
 173         final int MAX_DAY = 31;



 174         int year = 0;
 175         int month = 0;
 176         int day = 0;
 177         int hour;
 178         int minute;
 179         int second;
 180         int a_nanos = 0;
 181         int firstDash;
 182         int secondDash;
 183         int dividingSpace;
 184         int firstColon;
 185         int secondColon;
 186         int period;
 187         String formatError = "Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]";



 188 
 189         if (s == null) throw new java.lang.IllegalArgumentException("null string");
 190 
 191         // Split the string into date and time components
 192         s = s.trim();
 193         dividingSpace = s.indexOf(' ');
 194         if (dividingSpace < 0) {



 195             throw new java.lang.IllegalArgumentException(formatError);
 196         }
 197 
 198         // Parse the date
 199         firstDash = s.indexOf('-');
 200         secondDash = s.indexOf('-', firstDash+1);
 201 
 202         // Parse the time
 203         firstColon = s.indexOf(':', dividingSpace + 1);
 204         secondColon = s.indexOf(':', firstColon + 1);
 205         period = s.indexOf('.', secondColon + 1);


 206 
 207         // Convert the date
 208         boolean parsedDate = false;
 209         if ((firstDash > 0) && (secondDash > 0) && (secondDash < dividingSpace - 1)) {
 210             if (firstDash == YEAR_LENGTH &&
 211                     (secondDash - firstDash >= 2 && secondDash - firstDash - 1 <= MONTH_LENGTH) &&
 212                     (dividingSpace - secondDash >= 2 && dividingSpace - secondDash - 1 <= DAY_LENGTH)) {
 213                  year = Integer.parseInt(s, 10, 0, firstDash);
 214                  month = Integer.parseInt(s, 10, firstDash + 1, secondDash);
 215                  day = Integer.parseInt(s, 10, secondDash + 1, dividingSpace);



 216 
 217                 if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
 218                     parsedDate = true;
 219                 }
 220             }
 221         }
 222         if (! parsedDate) {
 223             throw new java.lang.IllegalArgumentException(formatError);
 224         }
 225 
 226         // Convert the time; default missing nanos
 227         if (firstColon > 0 && secondColon > 0 && secondColon < s.length() - 1) {
 228             hour = Integer.parseInt(s, 10, dividingSpace + 1, firstColon);
 229             minute = Integer.parseInt(s, 10, firstColon + 1, secondColon);
 230             if (period > 0 && period < s.length() - 1) {
 231                 second = Integer.parseInt(s, 10, secondColon + 1, period);
 232                 int nanoPrecision = s.length() - (period + 1);
 233                 if (nanoPrecision > 9)
 234                     throw new java.lang.IllegalArgumentException(formatError);
 235                 if (!Character.isDigit(s.charAt(period + 1)))
 236                     throw new java.lang.IllegalArgumentException(formatError);
 237                 int tmpNanos = Integer.parseInt(s, 10, period + 1);
 238                 while (nanoPrecision < 9) {
 239                     tmpNanos *= 10;
 240                     nanoPrecision++;
 241                 }
 242                 a_nanos = tmpNanos;
 243             } else if (period > 0) {
 244                 throw new java.lang.IllegalArgumentException(formatError);
 245             } else {
 246                 second = Integer.parseInt(s, 10, secondColon + 1);
 247             }
 248         } else {
 249             throw new java.lang.IllegalArgumentException(formatError);
 250         }
 251 
 252         return new Timestamp(year - 1900, month - 1, day, hour, minute, second, a_nanos);
 253     }
 254 
 255     /**
 256      * Formats a timestamp in JDBC timestamp escape format.
 257      *         <code>yyyy-mm-dd hh:mm:ss.fffffffff</code>,
 258      * where <code>ffffffffff</code> indicates nanoseconds.
 259      *
 260      * @return a <code>String</code> object in
 261      *           <code>yyyy-mm-dd hh:mm:ss.fffffffff</code> format
 262      */
 263     @SuppressWarnings("deprecation")
 264     public String toString () {
 265 
 266         int year = super.getYear() + 1900;