Date and Calendar Classes in Java
Before Java 8, dates and times were handled by the java.util.Date and java.util.Calendar classes, together with SimpleDateFormat for formatting. These are now called the legacy date classes. You will still meet them in older code and in some libraries, so it's worth knowing how they work, and especially why they caused so many bugs. Since Java 8, the java.time package replaces them. In this lesson, you will learn the legacy classes and their problems.
The Date Class
java.util.Date represents an instant in time, stored as the number of milliseconds since 1 January 1970, 00:00 UTC (called the epoch). Despite its name, it has no separate date or time zone; it only prints itself using the computer's default time zone.
The Calendar Class
java.util.Calendar was added in Java 1.1 to work with fields such as year, month and day, and to do date arithmetic. GregorianCalendar is its usual implementation.
| Method | Description |
|---|---|
Calendar.getInstance() | It is used to get a calendar for the current moment. |
get(Calendar.YEAR) | It returns a field, such as the year or month. |
set(year, month, day) | It sets the date. Months start at 0 (January is 0). |
add(Calendar.DAY_OF_MONTH, n) | It adds or subtracts days, months and so on. |
getTime() | It returns a Date. |
Example: Using Date and Calendar
Let's see an example that also shows two famous traps. The default time zone is set at the start so the output is the same on every computer.
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Legacy {
public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Kolkata"));
Date epoch = new Date(0);
System.out.println("Epoch: " + epoch);
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(2026, 11, 25);
System.out.println("set(2026, 11, 25) gives month "
+ (cal.get(Calendar.MONTH) + 1) + ": " + cal.getTime());
cal.add(Calendar.DAY_OF_MONTH, 10);
SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy");
System.out.println("Ten days later: " + fmt.format(cal.getTime()));
Date d = cal.getTime();
d.setTime(0);
System.out.println("Calendar after changing the Date: "
+ fmt.format(cal.getTime()));
}
}Epoch: Thu Jan 01 05:30:00 IST 1970
set(2026, 11, 25) gives month 12: Fri Dec 25 00:00:00 IST 2026
Ten days later: 04-01-2027
Calendar after changing the Date: 04-01-2027Explanation:
new Date(0)is the epoch, printed in India Standard Time, 5 hours 30 minutes ahead of UTC.cal.set(2026, 11, 25)means December 25, because months count from 0. Writing 12 for December is a classic bug.addcorrectly rolls over into the next year.getTime()returns a newDatecopy, so changing it doesn't affect the calendar. ButDateitself is mutable, which makes sharing dates risky.
Problems with the Legacy Classes
| Problem | Example |
|---|---|
| Mutable | Any code holding a Date can change it with setTime. |
| Confusing numbering | Months start at 0; Date.getYear() returns the year minus 1900. |
| Poor names | Date is really a timestamp, not a date. |
| Not thread-safe | SimpleDateFormat gives wrong results when shared between threads. |
| Time zones are awkward | Date has no time zone but prints with the default one. |
| No separate types | No way to say "just a date" or "just a time". |
| Many deprecated methods | Most of Date's methods are deprecated since Java 1.1. |
Common Mistakes
Passing 12 for December to Calendar.set. That's January of the next year; use Calendar.DECEMBER.
Sharing one SimpleDateFormat between threads. It corrupts results; use DateTimeFormatter, which is immutable.
Using date.getYear(). It's deprecated and returns years since 1900.
Practice
- Easy: Use
Calendarto print the day of the week of 1 January 2027. - Harder: Rewrite the example using
LocalDatefromjava.timeand compare how many traps disappear.
Key Takeaways
Was this tutorial helpful?