Team LiB
Previous Section Next Section

5.4. Dates and Times

Java allows dates and times to be represented and manipulated in three forms: as long values or as java.util.Date or java.util.Calendar objects. Java 5.0 introduces the enumerated type java.util.concurrent.TimeUnit. The values of this type represent time granularities or units: seconds, milliseconds, microseconds, and nanoseconds. They have useful convenience methods but do not themselves represent a time value.

5.4.1. Milliseconds and Nanoseconds

At the lowest level, dates and times are represented as a long value that holds the positive or negative number of milliseconds since midnight on January 1, 1970. This special date and time is known as the epoch and is measured in Greenwich Mean Time (GMT) or Universal Time (UTC). To query the current time in this millisecond representation, use System.currentTimeMillis()

long now = System.currentTimeMillis();

In Java 5.0 and later, you can use System.nanoTime() to query time in nanoseconds. This method returns a long number of nanoseconds long. Unlike currentTimeMillis( ), the nanoTime() does not return a time relative to any defined epoch. nanoTime() is good for measuring relative or elapsed time (as long as the elapsed time is not more than 292 years) but is not suitable for absolute time:

long start = System.nanoTime();
doSomething();
long end = System.nanoTime();
long elapsedNanoSeconds = end - start;

5.4.2. The Date Class

java.util.Date is an object wrapper around a long that holds a number of milliseconds since the epoch. Using a Date object instead of a long allows simple conversion to a nonlocalized string with the toString method. Date objects can be compared for equality with the equals( ) method and they can be compared for order with the compareTo() method or the before( ) and after() methods.

The no-argument version of the Date( ) constructor creates a Date that represents the current time. You can also pass a long number of milliseconds to create a Date that represents some other time. getTime( ) returns the millisecond representation of the Date. Date is a mutable class, so you can also pass a number of milliseconds to setTime( ).

Date has a number of methods for querying and setting the year, month, day, hour, minute, and second. All of these methods have been deprecated, however, in favor of the Calendar class, described next.

5.4.3. The Calendar Class

The java.util.Calendar class is a properly localized version of Date. It is simply a wrapper around a long number of milliseconds but can represent that instant in time according to the calendar of the current locale (usually a Gregorian calendar) and the time zone of the current locale. Furthermore, it has methods for querying, setting, and doing arithmetic on the various fields of the date and time.

The code below shows common uses of the Calendar class. Note that the set( ), get(), and add( ) methods all take an initial argument that specifies what field of the date or time is being set, queried, or added to. Fields such as year, day of month, day of week, hour, minute, and second are defined by integer constants in the class. Other integer constants define values for the months and weekdays of the Gregorian calendar. The month constant UNDECIMBER represents a 13th month used in lunar calendars.

// Get a Calendar for current locale and time zone
Calendar cal = Calendar.getInstance();  

// Figure out what day of the year today is
cal.setTimeInMillis(System.currentTimeMillis()); // Set to the current time
int dayOfYear = cal.get(Calendar.DAY_OF_YEAR);  // What day of the year is it?

// What day of the week does the leap day in the year 2008 occur on?
cal.set(2008, Calendar.FEBRUARY, 29);            // Set year, month, day fields
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);   // Query a different field

// What day of the month is the 3rd Thursday of May, 2005?
cal.set(Calendar.YEAR, 2005);                    // Set the year
cal.set(Calendar.MONTH, Calendar.MAY);           // Set the month
cal.set(Calendar.DAY_OF_WEEK,Calendar.THURSDAY); // Set the day of week
cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, 3);       // Set the week
int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH); // Query the day in month

// Get a Date object that represents three months from now
cal.setTimeInMillis(System.currentTimeMillis()); // Current time
cal.add(Calendar.MONTH, 3);                      // Add 3 months
Date expiration = cal.getTime();                 // Retrieve result as a Date
long millis = cal.getTimeInMillis();             // or get it as a long

5.4.4. Formatting Dates and Times

The toString() method of Date produces a textual representation of a date and time but does no localization and allows no customization of which fields (day, month and year or hours and minutes, for example) are to be displayed. The toString( ) method should be used only to produce a machine-readable timestamp, not a human-readable string.

Like numbers, dates and times can be converted to strings using the String.format( ) method and the related java.util.Formatter class of Java 5.0. Format strings for displaying dates and times are all two-character sequences that begin with the letter t. The second letter of each sequence specifies the field or set of fields of the date or time to display. For example %tr displays the hours and minutes fields using 24-hour time, and %TD displays the month, day, and year fields separated by slashes. String.format( ) can format a date or time specified as a long, a Date, or a Calendar:

// current hours and minutes
long now = System.currentTimeMillis();
String s = String.format("%tR", now);         // "15:12"

// Current month/day/year
Date d = new Date(now);
s = String.format("%tD", d);                  // "07/13/04"

// Hours and minutes using 12-hour clock
Calendar c = Calendar.getInstance();
c.setTime(d);
s = String.format("%tl:%tM %tp", now, d, c);  // "3:12 pm"

Prior to Java 5.0 and its Formatter class, you can format dates and times using the java.text.DateFormat class, which automatically handles locale-specific conventions for date and time formatting. DateFormat even works correctly in locales that use a calendar other than the common era (Gregorian) calendar in use throughout much of the world:

import java.util.Date;
import java.text.*;

// Display today's date using a default format for the current locale
DateFormat defaultDate = DateFormat.getDateInstance();
System.out.println(defaultDate.format(new Date()));

// Display the current time using a short time format for the current locale
DateFormat shortTime = DateFormat.getTimeInstance(DateFormat.SHORT);
System.out.println(shortTime.format(new Date()));

// Display date and time using a long format for both
DateFormat longTimestamp = 
  DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
System.out.println(longTimestamp.format(new Date()));

// Use SimpleDateFormat to define your own formatting template
// See java.text.SimpleDateFormat for the template syntax
DateFormat myformat = new SimpleDateFormat("yyyy.MM.dd");  
System.out.println(myformat.format(new Date()));
try {   // DateFormat can parse dates too
  Date leapday = myformat.parse("2000.02.29"); 
}
catch (ParseException e) { /* Handle parsing exception */ }

    Team LiB
    Previous Section Next Section