java.sql.Date不能在不增加年份数的情况下表示2019年12月31日

java.sql.Date不能在不增加年份数的情况下表示2019年12月31日,java,date,datepicker,Java,Date,Datepicker,在转换为java.sql.Date对象时,我遇到了一些令人沮丧的问题 比如说,我选择了一个与s的日期,特别是2020年1月1日。 java.sql.Date对象将正确反映所选日期: System.out.println("d: " + date1DatePicker.getValue().getDayOfMonth()); // Prints 1 System.out.println("m: " + date1DatePicker.getValue().getMonth()); // Print

在转换为java.sql.Date对象时,我遇到了一些令人沮丧的问题

比如说,我选择了一个与s的日期,特别是2020年1月1日。 java.sql.Date对象将正确反映所选日期:

System.out.println("d: " + date1DatePicker.getValue().getDayOfMonth()); // Prints 1
System.out.println("m: " + date1DatePicker.getValue().getMonth()); // Prints 1
System.out.println("y: " + date1DatePicker.getValue().getYear()); // Prints 2020

// This date will be 1-1-2020
java.sql.Date date = Date.valueOf(date1DatePicker.getValue());
但是,如果我选择一天之前,即2019年12月31日,则转换的日期对象将是错误的:

System.out.println("d: " + date1DatePicker.getValue().getDayOfMonth()); // Prints 31
System.out.println("m: " + date1DatePicker.getValue().getMonth()); // Prints 12
System.out.println("y: " + date1DatePicker.getValue().getYear()); // Prints 2019

// This date will be 12-31-2020 !!!!!!!!!!!!!!!!
java.sql.Date date = Date.valueOf(date1DatePicker.getValue());
如果选择2019年12月30日,转换仍将失败:

System.out.println("d: " + date1DatePicker.getValue().getDayOfMonth()); // Prints 30
System.out.println("m: " + date1DatePicker.getValue().getMonth()); // Prints 12
System.out.println("y: " + date1DatePicker.getValue().getYear()); // Prints 2019

// This date will be 12-30-2020 !!!!!!!!!!!!!!!!
java.sql.Date date = Date.valueOf(date1DatePicker.getValue());
System.out.println("d: " + date1DatePicker.getValue().getDayOfMonth()); // Prints 29
System.out.println("m: " + date1DatePicker.getValue().getMonth()); // Prints 12
System.out.println("y: " + date1DatePicker.getValue().getYear()); // Prints 2019

// This date will be 12-29-2019 ** FINALLY CORRECT **
java.sql.Date date = Date.valueOf(date1DatePicker.getValue());
最后,如果我选择2019年12月29日,转换将是正确的:

System.out.println("d: " + date1DatePicker.getValue().getDayOfMonth()); // Prints 30
System.out.println("m: " + date1DatePicker.getValue().getMonth()); // Prints 12
System.out.println("y: " + date1DatePicker.getValue().getYear()); // Prints 2019

// This date will be 12-30-2020 !!!!!!!!!!!!!!!!
java.sql.Date date = Date.valueOf(date1DatePicker.getValue());
System.out.println("d: " + date1DatePicker.getValue().getDayOfMonth()); // Prints 29
System.out.println("m: " + date1DatePicker.getValue().getMonth()); // Prints 12
System.out.println("y: " + date1DatePicker.getValue().getYear()); // Prints 2019

// This date will be 12-29-2019 ** FINALLY CORRECT **
java.sql.Date date = Date.valueOf(date1DatePicker.getValue());
我使用以下方式打印java.sql.Date日期:

System.out.println(new SimpleDateFormat("YYYY-MM-dd").format(date));
这里有什么问题?

A将其值返回为A。正如其文件所示(我的重点):

ISO-8601日历系统中没有时区的日期,如2007-12-03

因此,当您调用
datePicker.getValue()
时,您将返回其中一个

然后将其输入,其文档表明将发生某种类型的转换:

提供的
LocalDate
被解释为本地时区中的本地日期

这可能与你所观察到的有关

为了消除时间和时区问题,您可能希望直接使用
LocalDate
,从而简单地将所有与时间相关的问题放在地板上,或者故意转换为系统时区的一些众所周知的问题。在这里可以帮助你的课程是。希望这有帮助。

A将其值作为值返回。正如其文件所示(我的重点):

ISO-8601日历系统中没有时区的日期,如2007-12-03

因此,当您调用
datePicker.getValue()
时,您将返回其中一个

然后将其输入,其文档表明将发生某种类型的转换:

提供的
LocalDate
被解释为本地时区中的本地日期

这可能与你所观察到的有关


为了消除时间和时区问题,您可能希望直接使用
LocalDate
,从而简单地将所有与时间相关的问题放在地板上,或者故意转换为系统时区的一些众所周知的问题。在这里可以帮助你的课程是。希望这有帮助。

问题是您正在通过
YYYY-MM-dd
打印它。大写的
Y
表示周年,这意味着返回的年是属于该特定日期的周数的年

由于12月30日和31日是2020年第1周,因此返回该年的数字


Date
中包含的值正确;它的格式化输出非常混乱。您应该改用
yyyy-MM-dd

问题是您正在通过
yyy-MM-dd
打印它。大写的
Y
表示周年,这意味着返回的年是属于该特定日期的周数的年

由于12月30日和31日是2020年第1周,因此返回该年的数字


Date
中包含的值正确;它的格式化输出非常混乱。您应该改用
yyyy-MM-dd

其他两个答案是正确的。我会补充一些想法

java.sql.Date
已过时 可怕的类
java.sql.Date
在几年前被JSR310中定义的现代java.time类所取代

无需再次使用
java.sql.Date
。现在替换为
java.time.LocalDate
。使用JDBC4.2及更高版本,我们可以与数据库交换java.time对象

写入数据库

LocalDate ld = myDatePicker.getValue() ;  // Extract `LocalDate` from JavaFX widget.
myPreparedDatabase.setObject( … , ld ) ;  // Write to database.
LocalDate ld =  myResultSet.getObject( … , LocalDate.class ) ;
从数据库中检索

LocalDate ld = myDatePicker.getValue() ;  // Extract `LocalDate` from JavaFX widget.
myPreparedDatabase.setObject( … , ld ) ;  // Write to database.
LocalDate ld =  myResultSet.getObject( … , LocalDate.class ) ;
转换 如果您必须使用
java.sql.Date
与尚未更新为java.time的旧代码进行互操作,请转换。查看添加到旧类的新方法

java.sql.Date myJSD = Date.valueOf( myLocalDate ) ;
往另一个方向走

LocalDate myLocalDate = myJSD.toLocalDate() ;

另外两个答案是正确的。我会补充一些想法

java.sql.Date
已过时 可怕的类
java.sql.Date
在几年前被JSR310中定义的现代java.time类所取代

无需再次使用
java.sql.Date
。现在替换为
java.time.LocalDate
。使用JDBC4.2及更高版本,我们可以与数据库交换java.time对象

写入数据库

LocalDate ld = myDatePicker.getValue() ;  // Extract `LocalDate` from JavaFX widget.
myPreparedDatabase.setObject( … , ld ) ;  // Write to database.
LocalDate ld =  myResultSet.getObject( … , LocalDate.class ) ;
从数据库中检索

LocalDate ld = myDatePicker.getValue() ;  // Extract `LocalDate` from JavaFX widget.
myPreparedDatabase.setObject( … , ld ) ;  // Write to database.
LocalDate ld =  myResultSet.getObject( … , LocalDate.class ) ;
转换 如果您必须使用
java.sql.Date
与尚未更新为java.time的旧代码进行互操作,请转换。查看添加到旧类的新方法

java.sql.Date myJSD = Date.valueOf( myLocalDate ) ;
往另一个方向走

LocalDate myLocalDate = myJSD.toLocalDate() ;

您如何知道
Date
包含这些值?您是否打印对象(因此调用
toString
)?我使用:new SimpleDateFormat(“YYYY-MM-dd”)。格式(日期)为了补充Lard的答案-不要信任日期对象的
toString
实现-使用适当的
DateTimeFormatter
,并确保您知道已经使用的时区,很糟糕的
java.sql.date
类在几年前被
java.time.LocalDate
取代,采用了JSR 310.I建议不要使用
SimpleDataFormat
java.sql.Date
。这些类设计得很糟糕,而且早已过时,其中前者尤其令人讨厌。特别是因为您显然可以从中使用
LocalDateTime
。要进行格式化,请使用
DateTimeFormatter
LocalDate
toString()
方法。如何知道
Date
包含这些值?您是否打印对象(因此调用
toString
)?我使用:new SimpleDateFormat(“YYYY-MM-dd”).格式(日期)打印以添加到Lard的答案中-不要信任
toString