Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Calendar inconsistent results

I have searched for the answer to this, but cannot seem to find one. Can someone explain why the following code does not give me the 1 of each month, but jumps to the 31 for some months? It is for a report event that needs to determine the next month's date.

DateFormat formatter = new SimpleDateFormat("dd-MMM-yy"); 
Calendar cal = Calendar.getInstance( TimeZone
    .getTimeZone( "America/Los_Angeles" ) );
DateFormat formatter = new SimpleDateFormat("dd-MMM-yy"); 
Date date;
try
{
  date = (Date)formatter.parse("01-JUN-12");
  cal.setTime(date);
  //cal.set(2012, 05, 01);

  long now = new Date().getTime();
  int frequency = 1;

  System.out.println("Current calendar time=" + cal.getTime().toString()) ;

  while (cal.getTime().getTime() < now)
  {
      cal.add( Calendar.MONTH, frequency );
      System.out.println("In loop - current calendar time=" + cal.getTime().toString()) ;
  }
}
catch (ParseException e)
{
  // TODO Auto-generated catch block
  e.printStackTrace();
} 

The output is:

Current calendar time=Fri Jun 01 00:00:00 EDT 2012

In loop - current calendar time=Sun Jul 01 00:00:00 EDT 2012

In loop - current calendar time=Tue Jul 31 00:00:00 EDT 2012

In loop - current calendar time=Fri Aug 31 00:00:00 EDT 2012

In loop - current calendar time=Mon Oct 01 00:00:00 EDT 2012

In loop - current calendar time=Wed Oct 31 00:00:00 EDT 2012

Notice how it jumps to 31, then back to 1. If I use Calendar.set() instead, the output is correct:

Current calendar time=Fri Jun 01 15:14:26 EDT 2012

In loop - current calendar time=Sun Jul 01 15:14:26 EDT 2012

In loop - current calendar time=Wed Aug 01 15:14:26 EDT 2012

In loop - current calendar time=Sat Sep 01 15:14:26 EDT 2012

In loop - current calendar time=Mon Oct 01 15:14:26 EDT 2012

In loop - current calendar time=Thu Nov 01 15:14:26 EDT 2012

This seems like it is either 1) A bug with the Calendar API, or 2) a lack of understanding of how the Calendar API works. In either case, I just want the next month (same day), unless of course there is a problem with certain months and days. But the above scenario is puzzling me. This does not happen with any other day of the month, only with the 1st.

like image 309
Joshua Burns Avatar asked Oct 23 '12 19:10

Joshua Burns


3 Answers

It's a timezone issue. Replace your existing setup lines with the following, so that the Calendar and the Formatter are both using the same timezone:

    TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
    formatter.setTimeZone(tz);
    Calendar cal = Calendar.getInstance(tz);

and it all works fine:

Current calendar time=Fri Jun 01 08:00:00 BST 2012
In loop - current calendar time=Sun Jul 01 08:00:00 BST 2012
In loop - current calendar time=Wed Aug 01 08:00:00 BST 2012
In loop - current calendar time=Sat Sep 01 08:00:00 BST 2012
In loop - current calendar time=Mon Oct 01 08:00:00 BST 2012
In loop - current calendar time=Thu Nov 01 07:00:00 GMT 2012

You may want to replace the toString() calls with formatter.format() calls so that the output is in the right timezone too (it might look OK to you if you are in EDT, but I'm in the UK timezone, as you can see).

like image 125
DNA Avatar answered Nov 19 '22 11:11

DNA


Instead of just cal.add( Calendar.MONTH, frequency );, try this:

cal.add(Calendar.MONTH, frequency);
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
like image 3
akokskis Avatar answered Nov 19 '22 11:11

akokskis


You are printing the time in the system default time zone. Use formatter to display it.

Set the same time zone for the formatter:

DateFormat formatter = new SimpleDateFormat("dd-MMM-yy");
formatter.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));

And use it to display the time:

while (cal.getTime().getTime() < now) { 
    cal.add(Calendar.MONTH, frequency);
    System.out.println("In loop - current calendar time=" + formatter.format(cal.getTime()));
}
like image 2
Bhesh Gurung Avatar answered Nov 19 '22 10:11

Bhesh Gurung