Question

The below code is executing without any problems. But logically it seems to be incorrect. Why is it so?

import java.sql.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

DateFormat df =new SimpleDateFormat("MM/dd/yyyy");

new Date(df.parse("09/01/3~34").getTime());   // Produces '09/01/3'
new Date(df.parse("09/01/100000").getTime()); // Produces ' 000-09-01'
Was it helpful?

Solution

First question:

new Date(df.parse("09/01/3~34").getTime());   // Produces '09/01/3'

According to DateFormat#parse() JavaDoc:

Parses text from the beginning of the given string to produce a date. The method may not use the entire text of the given string.

Because of that, after it parses the value from the String, it stops searching on it. When it found the ~ sign, it parsed the 3 value to the year and stopped looking on the String.

Second question:

new Date(df.parse("09/01/100000").getTime()); // Produces ' 000-09-01'

It's not producing '000-09-01'. The following code:

DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
java.util.Date parsedDate = df.parse("09/01/100000");

System.out.println(parsedDate);
System.out.println(df.format(parsedDate));

Outputs:

Fri Sep 01 00:00:00 BRT 100000
09/01/100000

However, it appears to be a bug with the java.sql.Date#toString method on JDK. To present this java.sql.Date correctly, try passing it to your DateFormat#format method:

java.sql.Date sqlDt = new java.sql.Date(df.parse("09/01/10000").getTime());
System.out.println(df.format(sqlDt));

Output: 09/01/100000

OTHER TIPS

About first question:

The class SimpleDateFormat is VERY lenient and just stops when some invalid chars are hit. Even when you explicitly instruct it to parse strict via df.setLenient(false); you will notice here the same output and no exception. JodaTime, JSR-310 or my time library would correctly reject the input containing invalid chars in strict mode. So here we have a clear bug in JDK.

About second question:

Well, you use java.sql.Date instead of java.util.Date. The sql-version is not designed for years > 9999. This is even specified in its javadoc:

"date milliseconds since January 1, 1970, 00:00:00 GMT not to exceed the milliseconds representation for the year 8099"

Not quite clear in javadoc but Oracle speaks about year offset of 1900 so finally java.sql.Date only supports the year range up to 9999. This is conform with ANSI-SQL, so no that year limitation itself is not a bug, but necessary for interoperability with SQL. Instead another aspect is bad and in my opinion a bug, namely: If you feed the constructor with an invalid year then you don`t get any exception but internally the state will be silently set to something silly and unpredictable.

Conclusion:

Avoid to use java.sql.Date for anything else than in JDBC layer. It is not for the application layer. Furthermore, java.util.Date and also SimpleDateFormat (which are the "standard" in Java-pre8) are more or less horribly broken. Good alternatives are JodaTime, in Java 8 the new JSR-310-API or my library if it reaches non-alpha-state one day.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top