java.util.Date到java.sql.Date转换给出了错误的月份
请考虑以下代码段:
Calendar futureDate = Calendar.getInstance(); int year = 2011; int month = 11; int day = 14; futureDate.set(year,month, day); System.out.println(futureDate.toString()); java.sql.Date sqlDate = new java.sql.Date( futureDate.getTime().getTime());
futureDate.toString()的打印输出是:
….. YEAR = 2011,月= 11,WEEK_OF_YEAR = 43,WEEK_OF_MONTH = 4,DAY_OF_MONTH = 14,DAY_OF_YEAR = 289,DAY_OF_WEEK = 1,DAY_OF_WEEK_IN_MONTH = 3,AM_PM = 0,HOUR = 11,HOUR_OF_DAY = 11,MINUTE = 32,SECOND = 51,微差= 117,ZONE_OFFSET = -18000000,DST_OFFSET = 3600000]
这表明Calendare对象保存了正确的日期。 但是,在转换为sql日期并存储在数据库(MySQL通过JDBC)之后,MySQL表显示此日期的“2011-12-14”而不是“2011-11-14”。 我会怀疑语言环境和时区,但这些会导致一天中的时间与日期的月份不一致。
我做错了什么线索?
Calendar#set(int, int, int)
将month参数解释为从零开始,因此futureDate.set(2011, 11, 14)
将日历的月份设置为12月。
TL;博士
LocalDate.of( 2011 , 11 , 14 ) // November 14th, 2011
细节
Matt Ball的回答是正确的。 但现在有一种改进的方式。
java.time
令人烦恼的旧日期时间类(如Calendar
, java.util.Date
和java.sql.Date
现在已成为遗留问题,取而代之的是java.time类。
与遗留类不同,java.time类具有合理的编号 ,例如1月到12月的编号为1-12 ,星期一到星期日的编号为 1-7。
LocalDate
类表示没有时间且没有时区的仅日期值。
LocalDate ld = LocalDate.of( 2011 , 11 , 14 ) ;
或者使用方便的Month
枚举。
LocalDate ld = LocalDate.of( 2011 , Month.NOVEMBER , 14 ) ;
使用支持JDBC 4.2及更高版本的JDBC驱动程序,您可以将java.time对象直接传递给数据库。
myPreparedStatement.setObject( … , ld ) ;
获取时,使用getObject
。
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
关于java.time
java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.Date
, Calendar
和SimpleDateFormat
。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。
从哪里获取java.time类?
- Java SE 8 , Java SE 9及更高版本
- 内置。
- 带有捆绑实现的标准Java API的一部分。
- Java 9增加了一些小function和修复。
- Java SE 6和Java SE 7
- 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
- Android的
- ThreeTenABP项目特别适用于Android的ThreeTen-Backport (如上所述)。
- 请参见如何使用ThreeTenABP ….
ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如Interval
, YearWeek
, YearQuarter
等。