1. Switching from the Date class to the Calendar class

Programmers loved the Date class for its simplicity and support for Unix standards, but as you know, every rose has its thorns.

Programmers wanted a "smart" Date class. And they got what they wanted in the form of the Calendar class. It was conceived as a way to not only store dates, but also to perform difficult operations with dates.

The full name of the Calendar class is java.util.Calendar. Don't forget to add it to an import statement if you decide to use it in your code.

You can create a Calendar object with this command:

Calendar date = Calendar.getInstance();

The static getInstance() method of the Calendar class creates a Calendar object initialized with the current date. The calendar you want will be created based on the settings of the computer running the program.

Or more accurately, the calendar you get... That's because humans on Earth aren't limited to a single calendar. Instead, they use many. And almost every one of them is associated with some religion or country. The Calendar class supports 3 of them:

Calendar Description
GregorianCalendar Christian Gregorian calendar
BuddhistCalendar Buddhist calendar
JapaneseImperialCalendar Japanese imperial calendar

But there are also Chinese and Arabic calendars. Basically, working with time is not as easy as it seems.

In the Chinese calendar, the year is officially 4716 at the time of the writing of this lesson. And according to the Muslim calendar, the year is 1398. Welcome to the big world, my programmer friend.

2. Creating a calendar object

We will use the Gregorian calendar, since it is the most common in the world. At least until China buys Oracle and makes the Chinese calendar the main one.

You can create a calendar object with any date using a statement like this:

Calendar date = new GregorianCalendar(year, month, day);

Yes, you have to write GregorianCalendar every time. Instead of Calendar, you can also write GregorianCalendar — that will also work. But writing just Calendar is shorter.

The year must be written in full, e.g. you can't write 19 instead of 2019. Months are still numbered from zero. But as before, the days of the month are not numbered from zero. Nerds!

To set the time as well as the date, you need to pass in the time as additional arguments:

... = new GregorianCalendar(year, month, day, hours, minutes, seconds);

You can even pass in milliseconds if needed. They are the parameter after the number of seconds.

3. Displaying a calendar object on the screen

If you simply print a calendar object on the screen, you will not be very pleased with the result.

Code
Calendar calendar = new GregorianCalendar(2019, 03, 12);
System.out.println(calendar);
Console output
java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Helsinki",offset=7200000,dstSavings=3600000,useDaylight=true,transitions=118,lastRule=java.util.SimpleTimeZone[id=Europe/Helsinki,offset=7200000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=?,YEAR=2019,MONTH=3,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=12,DAY_OF_YEAR=?,DAY_OF_WEEK=?,DAY_OF_WEEK_IN_MONTH=?,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?]

The thing to keep in mind here is that a calendar is a calendar, not a date: it has all kinds of settings that will all be displayed on the screen.

It would be proper to use a SimpleDateFormat object to display a calendar, but until we study it, you can use this life hack.

Date date = calendar.getTime();

A Calendar object can be easily converted to a Date object, and you already know how to display a Date object. You can use code like this to convert a Calendar object to a Date:

Using the getTime() method:

Code Console output
Calendar calendar = new GregorianCalendar(2019, 03, 12);
System.out.println(calendar.getTime());
 Fri Apr 12 00:00:00 EEST 2019

That's quite a different matter, isn't it?

4. Working with elements of a date

To get a specific element of a date (e.g. the year, month, ...), the Calendar class has the get() method. It's a single method, but it has parameters:

int month = calendar.get(Calendar.MONTH);

Where calendar is a Calendar variable, and MONTH is a constant field of the Calendar class.

You pass one of the Calendar class's constant fields as an argument to the get method, and you get the desired value as the result.

Examples

Code Description
Calendar calendar = Calendar.getInstance();

int era = calendar.get(Calendar.ERA);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);

int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
int hour = calendar.get(Calendar.HOUR);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);


era (before or after the common era)
year
month
day of the month

day of the week
hours
minutes
seconds

To change an element of a date, use the set method:

calendar.set(Calendar.MONTH, value);

Where calendar is a Calendar variable, and MONTH is a constant field of the Calendar class.

When working with set method, you pass one of the Calendar class's constant fields as the first argument, and the new value as the second argument.

Examples

Code Description
Calendar calendar = new GregorianCalendar();

calendar.set(Calendar.YEAR, 2019);
calendar.set(Calendar.MONTH, 6);
calendar.set(Calendar.DAY_OF_MONTH, 4);
calendar.set(Calendar.HOUR_OF_DAY, 12);
calendar.set(Calendar.MINUTE, 15);
calendar.set(Calendar.SECOND, 0);

System.out.println(calendar.getTime());


year = 2019
month = July (numbered from 0)
4th day
hours
minutes
seconds

5. Constants of the Calendar class

The constant fields of the Calendar class are not limited to those for naming elements of a date. There seem to be fields for every occasion.

Calendar date = new GregorianCalendar(2019, Calendar.JANUARY, 31);

For example, there are constant fields to refer to months:

And also the days of the week:

Calendar calendar = new GregorianCalendar(2019, Calendar.JANUARY, 31);
if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY)
{
   System.out.println("It's Friday");
}

We won't list everything. We just don't want you to be surprised if you see constants like this in the code.

Using constants makes the code more readable, which is why the programmers use them. And months are numbered from zero also to improve readability. Or not.

6. Changing the date in a Calendar object

The Calendar class has a method that lets you operate on a date in more intelligent ways. For example, you can add a year, a month, or several days to a date. Or take away them away. This method is called add(). Working with it looks like this:

calendar.add(Calendar.MONTH, value);

Where calendar is a Calendar variable, and MONTH is a constant field of the Calendar class.

When working with add method, you pass one of the Calendar class's constant fields as the first argument, and as the second argument — the new value to be added.

This is another intelligent method. Let's see how smart it is:

Code
Calendar calendar = new GregorianCalendar(2019, Calendar.FEBRUARY, 27);
calendar.add(Calendar.DAY_OF_MONTH, 2);
System.out.println(calendar.getTime());
Console output
Fri Mar 01 00:00:00 EET 2019

This method understands that there are only 28 days in February 2019, so the resulting date is March 1.

Now let's take away 2 months! What should we get? December 27, 2018! Let's check now.

To perform an operation that results in an earlier date, you need to pass a negative value to the add() method:

Code
Calendar calendar = new GregorianCalendar(2019, Calendar.FEBRUARY, 27);
calendar.add(Calendar.MONTH, -2);
System.out.println(calendar.getTime());
Console output
Thu Dec 27 00:00:00 EET 2018

It works!

This method accounts the differing lengths of months as well as leap years. All in all, a great method. It's exactly what most programmers who work with dates need.

7. Rolling elements of a date

But sometimes there are situations when we don't want this smart behavior, e.g. you want to do something to one part of the date without changing everything else.

The Calendar class has the special roll() method for this. Its signature is just like the add() method, but this method changes only one element of the date, leaving the rest unchanged.

Example:

Code
Calendar calendar = new GregorianCalendar(2019, Calendar.FEBRUARY, 27);
calendar.roll(Calendar.MONTH, -2);
System.out.println(calendar.getTime());
Console output
Fri Dec 27 00:00:00 EET 2019

We changed the month, but the year and date remained unchanged.