JDK-6772689 : java.sql.Date.valueOf("2042-10-xx").toString() wrong in some time zones
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util:i18n
  • Affected Version: 6,6u10
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux,windows_xp
  • CPU: x86
  • Submitted: 2008-11-18
  • Updated: 2015-02-19
  • Resolved: 2011-04-20
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b134Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) Client VM (build 11.0-b15, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
java.sql.Date.valueOf(s).toString() does not return 's' in some time zones for years larger than 2037. The returned string is one day before 's'. The problem seems to be the begin or end of daylight saving that starts before or at midnight in some time zones.

Probably related is that Calendar throws an IllegalArgumentException with message DAY_OF_MONTH when trying to set this day with hour / minute / second 0 (instead an IllegalArgumentException with the message HOUR_OF_DAY).

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
See source code.

ACTUAL -
Date.valueOf("2038-03-21")=2038-03-20 America/Havana
Date.valueOf("2038-03-21")=2038-03-20 Cuba
Date.valueOf("2038-10-17")=2038-10-16 America/Asuncion
Date.valueOf("2038-10-10")=2038-10-09 America/Campo_Grande
Date.valueOf("2038-10-10")=2038-10-09 America/Cuiaba
Date.valueOf("2038-10-10")=2038-10-09 America/Santiago
Date.valueOf("2038-10-10")=2038-10-09 Antarctica/Palmer
Date.valueOf("2038-10-10")=2038-10-09 Chile/Continental
Date.valueOf("2038-10-03")=2038-10-02 AGT
Date.valueOf("2038-10-03")=2038-10-02 America/Argentina/Buenos_Aires
Date.valueOf("2038-10-03")=2038-10-02 America/Argentina/Catamarca
Date.valueOf("2038-10-03")=2038-10-02 America/Argentina/ComodRivadavia
Date.valueOf("2038-10-03")=2038-10-02 America/Argentina/Cordoba
Date.valueOf("2038-10-03")=2038-10-02 America/Argentina/Jujuy
Date.valueOf("2038-10-03")=2038-10-02 America/Argentina/La_Rioja
Date.valueOf("2038-10-03")=2038-10-02 America/Argentina/Mendoza
Date.valueOf("2038-10-03")=2038-10-02 America/Argentina/Rio_Gallegos
Date.valueOf("2038-10-03")=2038-10-02 America/Argentina/San_Juan
Date.valueOf("2038-10-03")=2038-10-02 America/Argentina/Tucuman
Date.valueOf("2038-10-03")=2038-10-02 America/Argentina/Ushuaia
Date.valueOf("2038-10-03")=2038-10-02 America/Buenos_Aires
Date.valueOf("2038-10-03")=2038-10-02 America/Catamarca
Date.valueOf("2038-10-03")=2038-10-02 America/Cordoba
Date.valueOf("2038-10-03")=2038-10-02 America/Jujuy
Date.valueOf("2038-10-03")=2038-10-02 America/Mendoza
Date.valueOf("2038-10-03")=2038-10-02 America/Rosario
Date.valueOf("2038-10-10")=2038-10-09 America/Sao_Paulo
Date.valueOf("2038-10-10")=2038-10-09 BET
Date.valueOf("2038-10-10")=2038-10-09 Brazil/East
Date.valueOf("2038-03-28")=2038-03-27 America/Scoresbysund
Date.valueOf("2038-03-28")=2038-03-27 Atlantic/Azores
Date.valueOf("2038-03-25")=2038-03-24 Asia/Amman
Date.valueOf("2038-03-28")=2038-03-27 Asia/Beirut
Date.valueOf("2038-04-02")=2038-04-01 Asia/Damascus
Date.valueOf("2038-04-01")=2038-03-31 Asia/Gaza
Date.valueOf("2038-03-21")=2038-03-20 Asia/Tehran
Date.valueOf("2038-03-21")=2038-03-20 Iran
End

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.sql.Date;
import java.util.TimeZone;

public class DateProblem {
    public static void main(String[] a) {
        String[] ids = TimeZone.getAvailableIDs();
        for (int i = 0; i < ids.length; i++) {
            TimeZone.setDefault(TimeZone.getTimeZone(ids[i]));
            for (int y = 2037; y < 2039; y++) {
                for (int m = 101; m < 113; m++) {
                    for (int d = 101; d < 129; d++) {
                        test(y, m, d);
                    }
                }
            }
        }
        System.out.println("End");
    }

    static void test(int y, int m, int d) {
        String s = y + "-" + ("" + m).substring(1) + "-" + ("" + d).substring(1);
        String s2 = Date.valueOf(s).toString();
        if (!s.equals(s2)) {
            String e = "Date.valueOf(\"" + s + "\")=" + s2;
            e += " " + TimeZone.getDefault().getID();
            System.out.println(e);
        }
    }
}
---------- END SOURCE ----------

Comments
EVALUATION When ZoneInfo delegates the calculation to a SimpleTimeZone year 2038+, the standard-to-daylight transition is handled in the same way as 1.3.1 GregorianCalendar. When transition is 23:59:59.999 to 1:00:00.000, the date becomes the previous day.
26-11-2008

EVALUATION This is not a java.sql.Date issue. java.sql.Date will call java.util.Date(int,int,int). You can chance the test method in the example to be: static void test(int y, int m, int d) { String s = y + "-" + ("" + m).substring(1) + "-" + ("" + d).substring(1); String s2 = Date.valueOf(s).toString(); int yy = y - 1900; int mm = Integer.parseInt(("" + m).substring(1))-1; int dd = Integer.parseInt(("" + d).substring(1)); if (!s.equals(s2)) { String e = "java.util.Date(" + yy + "," + mm + "," + dd + ")" + (new java.util.Date(yy,mm,dd)) + ", java.sql.Date.valueOf(\"" + s + "\"): \"" + s2 + "\""; e += " TimeZone: " + TimeZone.getDefault().getID(); System.out.println(e); } }
20-11-2008