tags:

views:

32

answers:

2

I'm converting a date stored in a calendar object in a string for a query in MySQL. I need the string in format "yyyy-MM-dd HH:mm:ss", i.e.: "2010-01-01 15:30:00". I'm using a code like:

    Calendar TimeStop = Calendar.getInstance();
    TimeStop.set(2010, 01, 01, 15, 30, 0);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String TimeStop_Str = sdf.format(TimeStop.getTime());

now, the string, instead of being "2010-01-01 15:30:00" like I would expect is "2010-02-01 15:30:00". I have already checked on http://download.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html for possible errors in the parser formula (for example the capital MM for month or capital HH for hours) but it didn't worked.

I guess that there is some other field that I should set, or maybe there is another method... any idea?

Thanks!

+2  A: 

Calendar.JANUARY is actually 0, not 1.

When you provide 01 for the month field in set, you're actually setting the month to February, which is why you get 02 when SimpleDateFormat renders it as MM.

When you use any of the Calendar.get/set methods, you must take extra precautions to make sure that you are aware of this discrepancy between the "natural" 1-based indexing, and the more "awkward" Calendar's 0-based indexing. Any time you're getting/setting the month of a Calendar, there's always this potential to cause a serious bug.

This is just one of those really awkward design in Calendar that leaves a lot to be desired. One of the better, more pleasant date/time API library available out there is Joda Time, so if at all possible, you may consider a switch to that library instead.

API links

  • Calendar.MONTH - "Field number for get and set indicating the month. This is a calendar-specific value. The first month of the year [...] is JANUARY which is 0".
  • Calendar.set(…, int month, …) - "month - the value used to set the MONTH calendar field. Month value is 0-based. e.g., 0 for January."

On octal literals

Also, note that 01 is actually an octal literal (i.e. base 8). You shouldn't make a habit of prepending 0 to integer literals (§3.10.1), because they can cause subtle bugs/errors unless you're very careful.

For example, int i = 09; is an illegal Java code.

    System.out.println(010); // prints 8, not 10

See also

polygenelubricants
Danke!this means that the Calendar starts from "0", but the parser start from "1"... okThank you also for the other comment
andystrath
@andystrath: For month fields of `java.util.Calendar`, yes, it starts from `0`. That's why when you `set` the month to `1`, it's actually `February`, which is `02` in `MM` format.
polygenelubricants
+2  A: 

It's just that months start from 0 (not 1)

That said, you should not convert to string in order to insert a date in the DB. You can either use the timestamp, or java.sql.Date together with PreparedStatement

Bozho
(regarding the DB stuff) +1 from me; I don't know the exact details, but this does sound like the more sensible thing to do.
polygenelubricants