2

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?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
adaj21
  • 543
  • 3
  • 11
  • 25

2 Answers2

5

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.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • Please use the intended constants for it, e.g. futureDate.set(2011,Calendar.DECEMBER,14) – mhaller Oct 16 '11 at 17:22
  • Thanks. That must be it. I can't use Calendar.NOVEMBER because the value comes from an input field, but now I now to adjust for zero based month values. – adaj21 Oct 16 '11 at 17:28
0

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154