Java has several ways of representing dates. Let’s delve into them now.
java.util.Date and java.sql.Date
Note that we’ve specified the packages for these two classes, since they have the same name. They differ mainly in how to create instances.
java.util.Date is the simpler of the two. These statements:
import java.util.Date
...
Date now = new Date();
set now to the current date and time, to the millisecond.
java.sql.Date exists to hold dates for use with DATE fields in SQL databases. These don’t have a time-of-day component, so it’s assumed that the milliseconds, seconds, minutes, and hours are all zero; regrettably, unless the value has been read from a database or from the valueOf() function (below), this isn’t automatic. java.sql.Date does not have a default constructor, but the static valueOf() function lets you initialize an instance with the date of your choosing:
import java.sql.Date;
...
Date independenceDay = Date.valueOf("1776-07-04");
These two classes do have one common constructor: new Date(long date)
, where date is a value in milliseconds since January 1, 1970.
Date myDate = new Date(<time in milliseconds>);
In fact, the value of either Date class is the number of milliseconds elapsed since midnight GMT, January 1, 1970 (known as the epoch).
Thus you can go from an instance of one class to an instance of the other:
java.util.Date now = new Date();
java.sql.Date sqlNow = new java.sql.Date(now.getTime());
Note that in this scenario, sqlNow will have a nonzero milliseconds, seconds, minutes, and hours–which is not allowed! We’ll give you a neat way of fixing this later.
Methods for java.util.Date and java.sql.Date
Aside from the constructors and method mentioned above, the methods for the two Date classes are identical:
Method | Function |
boolean after(Date when) boolean before(Date when) | Returns true if this date is later than/earlier than when. Equivalent to this.compareTo(when) > 0 and this.compareTo(when) < 0 , respectively. |
int compareTo(Date anotherDate) | Returns a value less than zero if the current date precedes anotherDate, greater than zero if current date follows anotherDate, and zero if they are equal. |
long getTime() | Returns the number of milliseconds since midnight GMT, Jan. 1, 1970. |
setTime(long time) | Sets the value to time, which is the number of milliseconds since midnight GMT, Jan. 1, 1970. |
Calendar
The two Date classes may suit you just fine most of the time. But if you need to do date or time arithmetic, or find information such as the day of the week a date represents, you need the Calendar class which, like Date, contains both a date and a time represented as milliseconds since midnight GMT, January 1, 1970.
Calendar is, in fact, an abstract class. It provides a method, getInstance(), to return an concrete instance of a subclass initialized to the current date and time. In almost all instances, the class returned is GregorianCalendar. The getInstance() method accepts as arguments a Locale, a TimeZone, neither, or both, which govern the behavior of the underlying concrete class. For example, this statements executed on a computer in the United States…
Calendar usCal = Calendar.getInstance();
Calendar frenchCal = Calendar.getInstance(Locale.FRANCE);
makes usCal a default Calendar for which the first day of the week is Sunday, and frenchCal a Calendar for which the first day of the week is Monday.
Calendar, and by extension GregorianCalendar, have an amazing array of methods and constants useful for date inquiry and manipulation. Please check the documentation for Calendar and GregorianCalendar for complete lists, and detailed descriptions of how these classes function. (Just follow the links in this paragraph.) Here’s a sampling:
Constant | Description |
APRIL | A value representing April |
DATE DAY_OF_MONTH | Two synonymous field type identifiers for the day of the month |
MONDAY | A value representing Monday |
DAY_OF_YEAR | A field type identifier for the day of the year |
HOUR | A field type identifier for the hour of the morning or afternoon |
HOUR_OF_DAY | A field type identifier for the hour of the day (e.g., for 2:15 PM, HOUR_OF_DAY is 14) |
Method | Description |
void add(int field, int amount) | Adds amount to the field indicated by field. amount may be negative. Example: cal.add(Calendar.DAY_OF_WEEK, -1); changes the calendar’s date to the previous day. |
boolean before(Object when) boolean after(Object when) boolean compareTo(Object when) | These behave the same as they do for Date, but notice that any compatible type of object may be provided for when. |
int get(int field) | Returns the current value of the indicated field. Example: int theYear = cal.get(Calendar.YEAR); sets theYear to the value of the calendar year. |
void roll(int field, boolean up) void roll(int field, int amount) | Rolls the indicated field up/down one unit of time (first version), or the desired amount of units of time, without changing other fields. Examples: cal.roll(Calendar.MONTH, true); sets the month to the next value. cal.roll(Calendar.MONTH, -3); sets the month to three months earlier. |
int getFirstDayOfWeek() void setFirstDayOfWeek(int value) | Returns or sets the day of the week (Calendar.SUNDAY, Calendar.MONDAY, … Calendar.SATURDAY) the Calendar uses as the first day of a week. |
int get(int field) | Returns the current value of the indicated field. Example: int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK) ;returns the cal’s current day-of-week value. |
void set(int field, int value) | Sets the indicated field to the specified value. Example: cal.set(Calendar.MINUTE, 59); sets the current minute value of cal to 59. |
java.util.Date getTime() | Returns the java.util.Date value of the Calendar (i.e., date and time). |
It may have occurred to you that if your Calendar is set to February 29 and you set its Calendar.DAY_OF_MONTH to 30, your date is now February 30. Or if you roll the minute of the time 06:28:32 up by a Calendar.HOUR value of 20, the time of day is now 26:28:32.
Whenever you change a Calendar field using set() or roll(), Calendar not only makes the value change; it records it. The next time get(), getTime(), getTimeInMillis(), add(), or roll() is called, all the pending value changes are used to recompute the Calendar’s value in milliseconds. (On the other hand, a call to add() recomputes the value immediately.)
The results can be complex, and we again refer you to the documentation for a full explanation. For example (taken from the documentation), if a GregorianCalendar is set to August 31, 1999, this call:
cal.set(Calendar.MONTH, Calendar.SEPTEMBER);
changes the value to September 31, 1999. This will resolve to October 1, 1999 if getTime() is called. But if this call is made before getTime():
cal.set(Calendar.DAY_OF_MONTH, 30);
the date will be September 30, 1999, since a call to set() doesn’t force the recomputation first.
Exercise
Write a program to display the dates of Labor Day in the United States for the years 2011 through 2025. You can use toString() to format the resulting dates. Your output should look something like this:
Labor Day 2011 is Mon Sep 05 13:16:57 EEST 2011
Labor Day 2012 is Mon Sep 03 13:16:57 EEST 2012
Labor Day 2013 is Mon Sep 02 13:16:57 EEST 2013
Labor Day 2014 is Mon Sep 01 13:16:57 EEST 2014
Labor Day 2015 is Mon Sep 07 13:16:57 EEST 2015
Labor Day 2016 is Mon Sep 05 13:16:57 EEST 2016
Labor Day 2017 is Mon Sep 04 13:16:57 EEST 2017
Labor Day 2018 is Mon Sep 03 13:16:57 EEST 2018
Labor Day 2019 is Mon Sep 02 13:16:57 EEST 2019
Labor Day 2020 is Mon Sep 07 13:16:57 EEST 2020
Labor Day 2021 is Mon Sep 06 13:16:57 EEST 2021
Labor Day 2022 is Mon Sep 05 13:16:57 EEST 2022
Labor Day 2023 is Mon Sep 04 13:16:57 EEST 2023
Labor Day 2024 is Mon Sep 02 13:16:57 EEST 2024
Labor Day 2025 is Mon Sep 01 13:16:57 EEST 2025
Once you’re done–or if you’re stuck–download a possible solution here. Our version uses a couple of tricks you might not have thought of. Good luck!
DateUtils
It’s not always easy to deal with dates and calendars. Fortunately, there are third parties ready to help. One of the most prominent is the Apache Software Foundation’s Apache Commons project. Their mission: to produce reusable Java software components. We’ve included some of their software in the Libs project we created as part of setup.
The component we’re interested in here is the DateUtils class. Here’s how to add it to your project.
- In Eclipse, open the Libs project we created in Lesson 3.
- Right-click on your project in the Package Explorer and select Build Path/Configure Build Path. Click on Classpath in the window in the center, then click on Add JARs…. Expand the Libs node and you’ll see a dialog similar to this:
- Click on the JAR to select it and click OK. You’ve now added the JAR to the build classpath and have access to all its code.
What Is a JAR?
You’ve just added a JAR (Java Archive) to your build classpath, and will probably put it in an execution classpath as well. A JAR is nothing more than a ZIP file of compiled Java classes and/or other resources, arranged in a directory structure. The compiler and the JVM treat a JAR just as though the directories and files it contains actually appeared in a file system, but in a more portable format.
It may well happen that you discover you have need of a class from a JAR you don’t have on hand. When this happens, the solution is to download an appropriate JAR from the Internet. There are web sites like jar.download.com, devoted to helping you find JARs by searching on the name of the class you need.
Back to DateUtils
As we said, the Apache DateUtils class contains methods and constants for working with dates. Please follow this link for more information, but here are some of its more useful methods and fields.
Field | Description |
static long MILLIS_PER_DAY static long MILLIS_PER_HOUR static long MILLIS_PER_MINUTE static long MILLIS_PER_SECOND | Number of milliseconds in a standard day/hour/minute/second |
Method | Description |
public static boolean isSameDate(Date date1, Date date2 | Returns a boolean indicating whether the two dates are the same day, irrespective of time of day. |
public static boolean isSameDate(Calendar cal1, Calendar cal2 | Returns a boolean indicating whether the two calendars are the same day, irrespective of time of day. |
public static Date parseDate (String str, String… parsePatterns) throws ParseException | Parses str against one or more parsePattern patterns, returning the first successful parsed value. Each parsePattern is in the form of a SimpleDateFormat expression. parseDate has a number of overloads; see the documentation for details. |
public static Date addYears(Date date, int amount) public static Date addMonths(Date date, int amount) public static Date addWeeks(Date date, int amount) public static Date addDays(Date date, int amount) public static Date addHours(Date date, int amount) public static Date addMinutes(Date date, int amount) public static Date addSeconds(Date date, int amount) public static Date addMilliseconds(Date date, int amount) | Adds the amount (which may be negative) to the pertinent time unit in date and returns the result, leaving date unchanged. |
public static Date setYears(Date date, int amount) public static Date setMonths(Date date, int amount) public static Date setWeeks(Date date, int amount) public static Date setDays(Date date, int amount) public static Date setHours(Date date, int amount) public static Date setMinutes(Date date, int amount) public static Date setSeconds(Date date, int amount) public static Date setMilliseconds(Date date, int amount) | Sets the pertinent time unit in date to amount and returns the result, leaving date unchanged. |
public static Calendar toCalendar(Date date) | Converts date to a Calendar. |
public static Date round(Date date, int field) public static Calendar round(Calendar date, int field) | Rounds a date/time, leaving the field specified as the most significant field. For example, if date is 28 Mar 2002 13:45:01.231 and field is Calendar.HOUR, the result is 28 Mar 2002 14:00:00.000. |
public static Date truncate(Date date, int field) public static Calendar truncate(Calendar date, int field) | Truncates a date/time to the field specified. For example, if date is 28 Mar 2002 13:45:01.231 and field is Calendar.HOUR, the result is 28 Mar 2002 13:00:00.000. |
public static Date ceiling(Date date, int field) public static Calendar ceiling(Calendar date, int field) | Gets a date ceiling, leaving the field specified as the most significant field. For example, if date is 28 Mar 2002 13:45:01.231 and field is Calendar.HOUR, the result is 28 Mar 2002 14:00:00.000. |
What You Need to Know
- Java as two Date classes for simple handling of date/time values.
- Java has a Calendar class for date computations.
- The Apache Software Foundation is dedicated to providing open-source Java components.
- DateUtils is a class of useful Date and Calendar methods.
Next up: Internal and External Representations, and Formatting