Calendar Utilities

The JDK 1.0 support for dates was poorly designed. With the benefit of hindsight, it would have been better to throw it out and start over again, but backward compatibility was seen as the more important goal. In JDK 1.1 most of the constructors and methods of java.util.Date class were deprecated, and other classes were provided to offer better support for time zones and internationalization.

The following classes specifically relate to date and time:

  • The class Date represents a specific instant in time with millisecond precision. It's really a timestamp, not a date.

  • The class Calendar is an abstract class for converting between a Date object and a set of integer fields such as year, month, day, and hour.

  • The class GregorianCalendar is the only concrete subclass of Calendar in the jdk. It does the date-to-fields conversions for the calendar system in common use.

  • The class DateFormat is an abstract class that lets you convert a Date to a printable String with fields in the way you want (for example, dd/mm/yy or dd.MMM.yyyy).

  • The class SimpleDateFormat is the only concrete subclass of DateFormat in the jdk. It takes a format String and either parses a String to produce a date or takes a date and produces a String.

  • The class TimeZone is an abstract class that represents a time zone offset and also calculates daylight savings time adjustments.

  • The class SimpleTimeZone is the only concrete subclass of TimeZone in the JDK. The class defines an ordinary time zone with a simple daylight savings and daylight savings time period.

Not only was date and time support poorly designed, it was poorly implemented and full of bugs. The good news is that many of the bugs were corrected in 1.1.4 and 1.1.6. In JDK 1.2, the most common problems were corrected. This part of the JDK has been maintained by IBM.

You can instantiate Date with no arguments to represent the current moment.

Date now = new Date();

In the past, you could provide arguments (year, month, day, hour, and so on) to “build me a Date that represents this date/time.” That use is now deprecated and you should use the class GregorianCalendar instead.

Java uses a 64-bit long to represent an instant in time. The value is interpreted as “milliseconds since Jan 1 00:00:00, 1970.” The scheme is sufficient to represent dates from 292,269,053 B.C. to A.D. 292,272,993 (64 bits covers minus 9,223,372,036,854,775,808 to plus 9,223,372,036,854,775,807 milliseconds), which seems like a lot, but is really only about 12% of the age of the planet, or 6% if you only count the portion in the past. Note that prior to JDK 1.2, a GregorianCalendar did not accept values earlier than 4716 B.C. In addition to all its other sins, the class Date was misnamed; it should be thought of as “Instant” or “Timestamp.”

Calendar and Gregorian calendar

The class Calendar translates between an instant in time and individual fields like year, month, day, hour, and so on. Date used to do this, but it did it in a way that didn't properly internationalize, so those methods have been deprecated.

Calendar also knows about time zones, and therefore, about things like summertime. The time zone information has a class of its own: TimeZone. DateFormat class provides elementary Date formatting.

Calendar is an abstract base class, which is meant to be overridden by a subclass that implements a specific calendar system. It's a dumb approach; it makes the common case of simple date processing not obvious. Most of the world uses the Gregorian calendar (named after the Pope who established it in 1582). Excessive generality in a design is as bad or worse than excessive rigidity.

The class java.util.GregorianCalendar extends Calendar and provides more methods. Since Calendar is an abstract class, and the parent of GregorianCalendar, I recommend that you simply use GregorianCalendar all the time. The following example shows how you would get a date of a particular value:

GregorianCalendar g = new GregorianCalendar(61,7,13);

That represents the day the Berlin wall was constructed (August 13, 1961) in the European central time (ECT) zone. A better way to construct that date is to first set the correct time zone, and then set the date.

TimeZone z_ect = TimeZone.getTimeZone("ECT");
GregorianCalendar g = new GregorianCalendar(z_ect);
g.set(61,7,13);

Note that (incredibly stupidly) months are in the range 0 to 11, and years are represented by the four-digit year less 1900. If you don't specify a time zone, GregorianCalendar defaults to the time zone in place on the OS where the program is running. For example, for a program running in Japan, the OS default is probably Japanese standard time (JST). A list of all time zones can be found by looking in the source for java.util.TimeZone.java.

You can retrieve the individual values out of a date by following this example:

int year = g.get(Calendar.YEAR);
int month = g.get(Calendar.MONTH);
int date = g.get(Calendar.DATE);
int day = g.get(Calendar.DAY_OF_WEEK);

You can also check if one date is before or after another date. There is no simple way to get the amount of time between two dates. There are two “helper” classes: TimeZone and SimpleTimeZone. Again, SimpleTimeZone is a concrete subclass of TimeZone, and can be used exclusively. You can create a time zone object for any time zone you want, and then pass it to GregorianCalendar so it will work with values in that time zone.

TimeZone z_ect = TimeZone.getTimeZone("ECT");
GregorianCalendar g2 = new GregorianCalendar(z_ect);
g2.set(89, 10, 9, 19, 0); // Berlin Wall Down  Nov 9 1989 7pm
g2.set(89, Calendar.NOVEMBER, 9, 19, 0); // better

You can do simple date and time formatting with static methods from the class java.text.DateFormat, as shown in the following example:

public static void main( String[] args ) {
     Date d = new Date();
     String s1 = DateFormat.getDateInstance().format( d );
     String s2 = DateFormat.getTimeInstance().format( d );
     String s3 = DateFormat.getDateTimeInstance().format( d );

     System.out.println("Date is " + s1 );
     System.out.println("Time is " + s2 );
     System.out.println("DateTime is " + s3 );
}

The program fragment runs to produce the following result:

Date is Nov 10, 2003
Time is 7:55:23 PM
DateTime is Nov 10, 2003 7:55:23 PM

You can also parse or convert a String into a DateFormat using that class. With methods from java.text.SimpleDateFormat, more flexible parsing and formatting is available. You provide a format String argument to the constructor in which different letters represent different fields of a date (day, hour, year, A.M., P.M., and so on) and the style in which you want to see them. Then you call the format() method with your date as the argument, and it passes it back as a String of the requested form.

import java.text.*;
import java.util.*;
public class df {

     public static void main( String[] args ) {
          SimpleDateFormat df1 =
           new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.S");
          SimpleDateFormat df2 = new SimpleDateFormat("dd-MMM-yy");
          String startdatetime = "2003-11-10 19:23:27.0";
          try {
               Date d = df1.parse(startdatetime);
               String s = df2.format( d );
               System.out.println("Date is " + s );
          } catch (ParseException pe) {
               System.out.println("ParseException " + pe );
          }
     }
}

When you run that code, a String is parsed to get a Date, and then the Date is parsed to get a String in a different format. Following is the output:

Date is 10-Nov-03

The number of times a pattern letter is repeated determines whether the short or long form of a text field is used. If at least four pattern letters are used (for example, “EEEE”), the long form of “Tuesday” is used. Otherwise, the short form (if there is one) will be used. For a number field (for example, “SSSSS”), the field will be zero-padded to that amount. Year is handled specially; a field of “yy” indicates that the year should be truncated to two digits.

The class SimpleDateFormat is in the java.text package, rather than java.util because it is primarily concerned with internationalized and localized ways of formatting the date.

The database crowd fixed Date a little in java.sql.Date by overriding java.util.Date, and making it deal only with dates and not times. That's another possibility for you to use.

Table 19-5. SimpleDateFormat

Symbol

Meaning

Presentation

Example

G

Era designator

(Text)

AD

y

Year

(Number)

1996

M

Month in year

(Text & Number)

July & 07

d

Day in month

(Number)

10

h

Hour in A.M./P.M. (1-12)

(Number)

12

H

Hour in day (0-23)

(Number)

0

m

Minute in hour

(Number)

30

s

Second in minute

(Number)

55

S

Millisecond

(Number)

978

E

Day in week

(Text)

Tuesday

D

Day in year

(Number)

189

F

Day of week in month

(Number)

2 (2nd Wed in July)

w

Week in year

(Number)

27

W

Week in month

(Number)

2

a

A.M./P.M. marker

(Text)

PM

k

Hour in day (1-24)

(Number)

24

K

Hour in A.M./P.M. (0-11)

(Number)

0

z

Time zone

(Text)

Pacific Standard Time

'

Escape for text

(Delimiter)

''

Single quote

(Literal)

'

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.168.203