Sunday, August 19, 2007

Calendar class - Better Way to Manipulate Dates.

Java’s Calendar class offers a set of methods for converting and manipulating temporal information. In addition to retrieving the current date and time, the Calendar class also provides an API for date arithmetic. Calendar’s built-in date/time arithmetic API is extremely useful.

This tutorial examines the Calendar class API and presents examples of how you can use Calendar objects to add and subtract time spans to and from dates and times, as well as how to evaluate whether one date precedes or follows another.

Adding time spans

Let’s say you want to add a time span to a starting date and print the result. Consider the following example, which initializes a Calendar to 16 July 2007 and then adds two months and three days to it to obtain a new value:

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;     
public class CalenderDemo{
 public static void main(String[] args) {
  CalenderDemo tdt = new CalenderDemo();
 private void calculateDate(){
  //Creating a calendar instance with initial date
16 July 2007
  Calendar calendar = new GregorianCalendar
  System.out.println("Initial date is: ");
  // Adding 2 Months and 3 day here
  // printing modified date value
  System.out.println("New date is: ");
 /** Method to print Formatted Date
SimpleDateFormat */
 private void printFormattedDate(Calendar calendar){
  // define output format and print
  SimpleDateFormat sdf = new SimpleDateFormat
("d MMM yyyy hh:mm aaa");
  String date = sdf.format(calendar.getTime());

The main workhorse of this class is the doMath() method, which begins by initializing a new GregorianCalendar object to 16 July 2007. Next, the object’s add() method is invoked; this method accepts two arguments: the name of the field to add the value to and the amount of time to be added. In this example, the add() method is called twice — first to add two months to the starting date and then to add a further one day to the result. Once the addition is performed, the printCalendar() utility method is used to print the final result.

The use of the SimpleDateFormat object to turn the output of getTime() into a human-readable string. This class is a part of java.text. package.

When you run the class, this is the output you’ll see:

Initial date is:
 16 July 2007 12:00 AM
New date is:
 19 September 2007 12:00 AM

This kind of addition also works with time values. To illustrate, consider the next example, which adds 14 hours and 55 minutes to a starting time value:

* Creating an Instance of Calendar with Year,
* Month, data, Hours and Minutes **/
Calendar calendar =new GregorianCalendar
(2007,Calendar.JANUARY,1, 1,0);
System.out.println(“Initial Date is :”);
//Defined in Above example
 // Add 14h 55min
//Print after Adding the hours and minutes        
System.out.println(“Modified Date is :”);
printFormattedDate(calendar);  //Defined in Above example.
This is almost identical to the previous class except
that the calls to add() involve the calendar’s hour
and minute fields. Here’s the output:
Initial Date is:

1 Jan 2007 01:00 AM

Modified Date is
1 Jan 2007 03:55 PM

Subtracting time spans

Subtraction is fairly easy as well — you simply use negative values as the second argument to add(). Here’s an example:

// Creating a Date Instance with Year, Month, Day, Hours and Minutes
Calendar calendar = new GregorianCalendar
(2007,Calendar.JANUARY,2, 3,30);
System.out.println("Starting date is: ");
//Defined in First Example.
// Subtracting 1 Year 1 Day 4 Hours and 5 Minutes
System.out.println("Subtracting 1 Year 1
Day 4 Hours and 5 Minutes");
// print result
System.out.println("Ending date is ");

Here’s the output:

Starting date is:
2 Jan 2007 03:30 AM
Subtracting 1y 1d 4h 5min...
Ending date is
31 Dec 2005 11:25 PM

In this example, the Calendar object automatically takes care of adjusting the year and the day when the subtraction results in the date “overflowing” from 1 Jan 2006 to 31 Dec 2005.

Adding vs. rolling

As the previous example illustrates, the add() method automatically takes care of rolling over days, months, and years when a particular calendar field “overflows” as a result of addition or subtraction. However, this behavior is often not what you want. In those situations, the Calendar object also has a roll() method, which avoids incrementing or decrementing larger calendar fields when such overflow occurs. To see how this works, look at the following example:

Calendar calendar = new GregorianCalendar
(2006, Calendar.DECEMBER,1);
System.out.println("Starting date for add()  is: ");
System.out.println("After add()ing 1 month, ending date is: ");
calendar.add(Calendar.MONTH, 1);
// initialize calendar
Calendar calendar2 = new GregorianCalendar

(2006, Calendar.DECEMBER,1);
System.out.println("Starting date for roll() is: ");
System.out.println("After roll()ing 1 month,  ending date is: ");
Calendar2.roll(Calendar.MONTH, 1);

Here’s the output:

Starting date for add() is:
 1 Dec 2006 12:00 AM
 After add()ing 1 month, ending date is:
 1 Jan 2007 12:00 AM     
 Starting date for roll() is:
 1 Dec 2006 12:00 AM
 After roll()ing 1 month, ending date is:
 1 Jan 2006 12:00 AM

In the first case, when one month is added to the starting date of 1 Dec 2006, the add() method realizes that a year change will occur as a result of the addition, and the year is rolled over to 2007. When using roll(), this behavior is disabled, and only the month field is incremented by 1, with the year change ignored. In many situations, roll() is very useful.

Checking date precedence

The Calendar object also includes the compareTo() method, which lets you compare two dates to find out which one comes earlier. The compareTo() method accepts another Calendar object as an input argument and returns a value less than zero if the following conditions are true:

  • The date and time of the input Calendar object is later than that of the calling Calendar object.
  • A value greater than zero if the reverse is true.
  • A value of 0 if the two Calendar objects represent the same date.

Here’s an example that compares 1 Jan 2007 12:00 AM and 1 Jan 2007 12:01 AM with compareTo():

// initialize two calendars
Calendar calendar1 = new GregorianCalendar
Calendar calendar2 = new GregorianCalendar
// define date format
String date1 = null;
String date2 = null;
SimpleDateFormat sdf = new SimpleDateFormat
("d MMM yyyy hh:mm aaa");
// compare dates
if((calendar1.compareTo(calendar2)) <>
    date1 = sdf.format(calendar1.getTime());
    date2 = sdf.format(calendar2.getTime());
    date1 = sdf.format(calendar2.getTime());
    date2 = sdf.format(calendar1.getTime());
System.out.println(date1 + " occurs before " + date2);
System.out.println(date2 + " occurs after  " + date1);

Here’s the output:

1 Jan 2007 12:00 AM occurs before 1 Jan 2007 12:01 AM
1 Jan 2007 12:01 AM occurs after  1 Jan 2007 12:00 AM

Since Most of the Date/Time classes are deprecated,
Calendar class is very handy to work with.
Alongwith this java.text.DateFormat and
java.text.SimpleDateFormat are very useful to
convert the date to different Locales and
different format.