JDK-4808839 : Enhance efficiency of java.sql.Date valueOf()
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.sql
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2003-01-27
  • Updated: 2014-09-25
  • Resolved: 2014-09-25
Related Reports
Relates :  
Relates :  
Description

Name: jl125535			Date: 01/27/2003


FULL PRODUCT VERSION :
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)

A DESCRIPTION OF THE PROBLEM :
java.sql.Date valueOf() is written making extensive use of
String's subString and indexOf to parse a JDBC Escaped Date
string into a java.sql.Date instance. Suggested enhancement
removes dependence on String and Integer.parseInt() and
makes one pass through a char buffer extracted from String
and directly parses the characters into an int array.
Previous code did little validation of the parsed values,
suggested enhancement code does quick but complete
validateion of the parsed values. Current code has a bug in
it that it will accept "2000-0--1" or "2000-0-0" or "2000-0-"
and return unpredicatable results.


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
Current source code:
    public static Date valueOf(String s) {
	int year;
	int month;
	int day;
	int firstDash;
	int secondDash;

	if (s == null) throw new java.lang.IllegalArgumentException();

	firstDash = s.indexOf('-');
	secondDash = s.indexOf('-', firstDash+1);
	if ((firstDash > 0) & (secondDash > 0) & (secondDash < s.length()-1)) {
	    year = Integer.parseInt(s.substring(0, firstDash)) - 1900;
	    month = Integer.parseInt(s.substring(firstDash+1, secondDash)) - 1;
	    day = Integer.parseInt(s.substring(secondDash+1));
	} else {
	    throw new java.lang.IllegalArgumentException();
	}
			
	return new Date(year, month, day);
    }

  Suggested enhancement:
    public static Date valueOf(String s) {
	if (s == null) {
	    throw new java.lang.IllegalArgumentException();
	}

	char buf[] = s.toCharArray();
	int results[] = {0,0,0};
	int r = 0;	// results index to 0
	int i=0;	// buf index to 0
	while (i < buf.length) {
	    char c = buf[i++];
	    if (c == '-') {
		if (r++ >= results.length) {
		    throw new java.lang.IllegalArgumentException();
		}
	    } else {
		int digit = Character.digit(c, 10);
		if (digit < 0) {
		    throw new NumberFormatException(s);
		}
		results[r] = (results[r] * 10) + digit;
		if (results[r] > 9999) {
		    // None of the fields should exceed 9999
		    throw new NumberFormatException(s);
		}
	    }
	}

	// Validate results
	if (
	    // Diddn't reach end of buffer
	    (i != buf.length) ||
	    // Didn't parse all of our int's
	    (r != results.length - 1) ||
	    // No need to check year, already done above
	    // Month is too large
	    (results[1] > 11) ||
	    // Day out of range
	    ((results[2] == 0) || (results[2] > 31))) {
	    throw new NumberFormatException(s);
	}

	// Create and return new Date
	return new Date(results[0]-1900, results[1], results[2]);
    }

---------- END SOURCE ----------
(Review ID: 153582) 
======================================================================

Comments
Duplicate of 8055055
25-09-2014

EVALUATION Target for consideration during Tiger time-frame. ###@###.### 2003-01-28 This is being addressed in JDBC 4.0 specification. ###@###.### 2003-11-24
28-01-2003