adaj21
adaj21

Reputation: 573

java.util.Date to java.sql.Date conversion gives wrong month

Consider the following snippet:

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());

The printout from futureDate.toString() is:

.....YEAR=2011,MONTH=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,MILLISECOND=117,ZONE_OFFSET=-18000000,DST_OFFSET=3600000]

which shows that the Calendare object holds the correct date. However, after converting to sql date and storing in the database (MySQL through JDBC), the MySQL table shows '2011-12-14' for this date instead of '2011-11-14'. I would have suspected locale and time zone, but these would cause discrepancy in the time of day not in the month part of the date.

Any clues to what I did wrong?

Upvotes: 2

Views: 2030

Answers (2)

Basil Bourque
Basil Bourque

Reputation: 339043

tl;dr

LocalDate.of( 2011 , 11 , 14 )  // November 14th, 2011

Details

The Answer by Matt Ball is correct. But now there is a much improved way.

java.time

The troublesome old date-time classes such as Calendar, java.util.Date, and java.sql.Date are now legacy, supplanted by the java.time classes.

Unlike the legacy classes, the java.time classes have sane numbering, such as months being numbered 1-12 for January to December, and 1-7 for Monday to Sunday.

The LocalDate class represents a date-only value without time-of-day and without time zone.

LocalDate ld = LocalDate.of( 2011 , 11 , 14 ) ;

Or use the handy Month enum.

LocalDate ld = LocalDate.of( 2011 , Month.NOVEMBER , 14 ) ;

With a JDBC driver supporting JDBC 4.2 and later, you may pass your java.time objects directly to the database.

myPreparedStatement.setObject( … , ld ) ;

When fetching, use getObject.

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Upvotes: 0

Matt Ball
Matt Ball

Reputation: 359936

Calendar#set(int, int, int) interprets the month argument as zero-based, so futureDate.set(2011, 11, 14) sets the calendar's month to December.

Upvotes: 5

Related Questions