JDK-7095853 : Date.valueOf Java 1.6.0_22 doesn't accept 1 digit month, but Java 1.6.0_11 does
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util
  • Affected Version: 6u26
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: linux
  • CPU: x86
  • Submitted: 2011-09-28
  • Updated: 2012-07-13
  • Resolved: 2012-01-11
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_27"
Java(TM) SE Runtime Environment (build 1.6.0_27-b07)
Java HotSpot(TM) Server VM (build 20.2-b06, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux oskar 2.6.30.10-105.2.23.fc11.i586
Linux pawel 2.6.35.6-48.fc14.i686
Linux newapps 2.6.32-5-686-bigmem

A DESCRIPTION OF THE PROBLEM :
Similar to bug ID=6763465.
I have upgraded Java 1.6.0_11 to Java 1.6.0_22 and problem appeared.
Method java.util.Date.valueOf stopped accept one digit month and one digit day. For example Date.valueOf("2011-9-8") will throw exception java.lang.IllegalArgumentException. But in Java 1.6.0_11 this format was accepted.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Java 1.6.0_22
and call
java.util.Date.valueOf("2011-8-13");

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect that Date.valueOf will accept one digit month and one digit day.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/**
 * 28-09-2011
 */
package pl.ziaja.test.date;

import java.util.Date;

/**
 * Test of valueOf methods -  Java 1.6.0_11 vs Java 1.6.0_22.
 * This snipped of code is source from java.util.Date
 * @author Oskar Sawicki
 */
public class TestDateValueOf {

	public static Date valueOf22(String s) {
		final int YEAR_LENGTH = 4;
		final int MONTH_LENGTH = 2;
		final int DAY_LENGTH = 2;
		final int MAX_MONTH = 12;
		final int MAX_DAY = 31;
		int firstDash;
		int secondDash;
		Date d = null;

		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) {
			String yyyy = s.substring(0, firstDash);
			String mm = s.substring(firstDash + 1, secondDash);
			String dd = s.substring(secondDash + 1);
			if (yyyy.length() == YEAR_LENGTH && mm.length() == MONTH_LENGTH
					&& dd.length() == DAY_LENGTH) {
				int year = Integer.parseInt(yyyy);
				int month = Integer.parseInt(mm);
				int day = Integer.parseInt(dd);
				if (month >= 1 && month <= MAX_MONTH) {
					int maxDays = MAX_DAY;
					switch (month) {
					// February determine if a leap year or not
					case 2:
						if (year % 4 == 0 && !(year % 100 == 0) || year % 400 == 0) {
							maxDays = MAX_DAY - 2; // leap year so 29 days in
													// February
						} else {
							maxDays = MAX_DAY - 3; // not a leap year so 28 days
													// in February
						}
						break;
					// April, June, Sept, Nov 30 day months
					case 4:
					case 6:
					case 9:
					case 11:
						maxDays = MAX_DAY - 1;
						break;
					}
					if (day >= 1 && day <= maxDays) {
						d = new Date(year - 1900, month - 1, day);
					}
				}
			}
		}
		if (d == null) {
			throw new java.lang.IllegalArgumentException();
		}
		return d;
	}

	public static Date valueOf11(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);
	}

	public static void main(String[] a) {
		System.out.println(valueOf11("2011-8-13")); // OK
		System.out.println(valueOf22("2011-8-13")); // exception
	}
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
// This is modification of java.util.Date.valueOf method from Java 1.6.0_22

	public static Date valueOf(String s) {
		final int YEAR_LENGTH = 4;
		final int MONTH_MAX_LENGTH = 2;
		final int DAY_MAX_LENGTH = 2;
		final int MONTH_MIN_LENGTH = 1;
		final int DAY_MIN_LENGTH = 1;
		final int MAX_MONTH = 12;
		final int MAX_DAY = 31;
		int firstDash;
		int secondDash;
		Date d = null;

		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) {
			String yyyy = s.substring(0, firstDash);
			String mm = s.substring(firstDash + 1, secondDash);
			String dd = s.substring(secondDash + 1);
			if (yyyy.length() == YEAR_LENGTH && mm.length() >= MONTH_MIN_LENGTH
					&& mm.length() <= MONTH_MAX_LENGTH && dd.length() >= DAY_MIN_LENGTH
					&& dd.length() <= DAY_MAX_LENGTH) {
				int year = Integer.parseInt(yyyy);
				int month = Integer.parseInt(mm);
				int day = Integer.parseInt(dd);
				if (month >= 1 && month <= MAX_MONTH) {
					int maxDays = MAX_DAY;
					switch (month) {
					// February determine if a leap year or not
					case 2:
						if (year % 4 == 0 && !(year % 100 == 0) || year % 400 == 0) {
							maxDays = MAX_DAY - 2; // leap year so 29 days in
													// February
						} else {
							maxDays = MAX_DAY - 3; // not a leap year so 28 days
													// in February
						}
						break;
					// April, June, Sept, Nov 30 day months
					case 4:
					case 6:
					case 9:
					case 11:
						maxDays = MAX_DAY - 1;
						break;
					}
					if (day >= 1 && day <= maxDays) {
						d = new Date(year - 1900, month - 1, day);
					}
				}
			}
		}
		if (d == null) {
			throw new java.lang.IllegalArgumentException();
		}
		return d;
	}

Comments
EVALUATION java.util.Date does not define a valueOf method - what is this bug about? Maybe the submitter meant java.sql.Date, this was changed via 6898593 in 6u18.
11-01-2012