IDI Software Component Library
© 1999 Information Disciplines, Inc., Chicago

Date and Calendar package (Java Class Definitions)


Conrad Weisert, Information Disciplines, Inc., Chicago


Bug Report

If you downloaded before 21 September 2003, you should download a fresh copy. The dayno() function was off-by-one for some leap-year dates. Thanks to Ed Ward, London Bridge Software, Ltd., for his exhaustive unit testing and for diagnosing and reporting the error.

Most business applications and many scientific applications need to manipulate dates. Unfortunately, Java's amateurish "standard" library classes are unsuited to serious application programming, because:

On the other hand this easy-to-use package provides in a natural way the date functionality that typical business and scientific applications need. It allows applications to avoid the ugly Java classes.


Three classes

The package consists of three classes.

Follow the above links for detailed usage documentation on each class.

Deploying the package

Download the three class-definition source-code files:

Place them in a directory called ididates. (If you choose a different name, you'll have to change the package statements at the beginning of each source-code file.) Compile them to create the .class files.

To use the classes the client program must import the package:

    import ididates, *;

Clarification, March 22, 2009

Because Date and Days are mutually dependent (they refer to each other) you can't just compile either one independently. Although they belong to the same package, the Java compiler will complain about references to the other class.

Fortunately, the compiler provides an elegant way of compiling mutually dependent classes in the same package. Just compile any program outside the package that contains the import statement for the package. The compiler will automatically perform the subsidiary compilations and will allow the mutual dependencies.

You can then instantiate Date and Days objects and invoke the various public methods in all three classes.

What about the C++ versions? Usage documentation reminder
Of course IDI has C++ versions of the Java classes described here. In fact, they're even better, because the language allows more natural operator expressions. The reason we don't post freeware versions here is that they depend, in turn, on other IDI library components, and are therefore a little more complicated to download and install. Call or E-mail for information. We've explained why we avoid the JAVADOC style of usage documentation.

Date class


We usually disapprove of giving a class the same name as a Java standard library class. We make an exception here, because the Java library Date class is such an abomination that we advise clients and students never to use it in an application.

   Date(int yyyy, int mm, int dd) // Year, month, day
   Date(int yyyy, int ddd)        // Year and day number
   Date(final Date x)             // Copy constructor
   Date()                         // (undefined default value)
   Date(final String yymmdd)      // See note #1

Note 1: The fifth constructor, using the one-time ANSI "standard" 6-character representation, uses the windowing parameter in the CalendarInfo class to determine the century.

Accessor functions

   short d.weekday()      //  Day of week (0=Sunday, 6=Saturday)

For efficiency, the following four functions decompose a date into its Gregorian components and cache those components for later retrieval by the other functions. (Warning: This caching logic has not been exhaustively validated for multithreaded invocation.)

    int   d.year()
    int   d.month()       //  1=January, 12=December
    int         //  Day of the month
    int   d.dayno()       //  Day number within year

Arithmetic and relational operator functions

These pseudo-operators follow the design pattern for point classes and are named in accord with IDI's Java operator naming conventions. In the examples d1 and d2 are Date objects and n is either a Days object or an int.
corresponding C++ expression Java function syntax result type if new object
d1 = d2d1.set(d2) -
d1 += nd1.addSet(n) -
d1 -= nd1.subSet(n) -
d1 - d2d1.sub(d2)Days
d1 + n d1.add(n)Date
d1 - n d1.sub(n)Date
d1 == d2d1.equals(n)boolean
d1 < d2d1.lessThan(d2)boolean
d1 > d2d1.greaterThan(d2)boolean

String-valued conversion/formatting functions

Thus if d is July 4, 1776, then d.toString() yields "1776-07-04" and d.toEnglish() yields "4 July, 1776".

Users who prefer some other external representation can easily build their own conversion function using the tables and functions in the CalendarInfo pseudo class.

Current day function

The static function returns the current date. Note:


Space consumed by Date object = 4 bytes

Speed: As usual, the compound assignment operators are much faster than the corresponding simple arithmetic operators, because they avoid allocating a new object. For example you can expect d.addSet(7) to be much faster than either d.set(d.add(7)) or d = d.add(7).

Range is approximately 2 million B.C. to 2 million A.D. Since this far exceeds the validity of the Gregorian calendar, the external representation conversions may not be meaningful, but all date calculations will be valid through the entire range.

Return to Date and Calendar package

Days class

This class complements the Date class as the corresponding extent in time or relative date. It arises naturally and inevitably from the subtraction of one date from another. Programmers who need a finer-grained duration class are invited to call us at 1-773 736-9661.


    Days(int n)
    Days()                     //  Default value = 0
    Days(final Days x)         //  Copy constructor

Arithmetic and relational operator functions

These pseudo operators follow the design pattern for extent classes and are named in accord with IDI's Java operator naming convention. (dx and dz are Days objects, k is an int, and n is either a Days object or an int.
corresponding C++ expression Java function syntax result type if new object
dy = dzdy.set(dy) -
dy += ndy.addSet(n) -
dy -= ndy.subSet(n) -
dy *= kdy.mpySet(k) -
dy /= kdy.divSet(k) -
dy %= ndy.modSet(n) -
dy + ndy.add(n)Days
dy - ndy.sub(n)Days
dy * kdy.mpy(k)Days
dy / kdy.div(k)Days
dy / dzdy.div(dz)int
dy % ndy.mod(n)Days
dy == dzdy.mpy(n)boolean
dy < dzdy.lessThan(dz)boolean
dy > dzdy.greaterThan(dz)boolean

String-valued conversion/formatting functions

dy.toString() yields the number followed by the unit name in English, e.g. "1 day", "-3 days". The English singular unit name ("day") is available from the static function unitName().

Return to Date and Calendar package

CalendarInfo class

The static data and functions in this class are used by various methods in the Date class and by some client programs. This class has no knowledge of the Date class or of the internal representation of Date objects.

Constants and tables

Integer constants for calendar computations


Integer tables (for non leap years)

     DAYS_IN_MONTH[]      // See note #2
     DAYS_BEFORE_MONTH[]  //  See note #2 

String-valued language-specific (English) name tables

     MONTH_NAME[]  // See note #2
     DAY_NAME      // 0=Sunday, 6=Saturday

Note 2: Month tables are subscripted by the number of the month, 1-12. (The 0-elements are unused.) Thus DAYS_BEFORE_MONTH[9] is 243 and MONTH_NAME[9] is "September".

User-overridable "windowing" parameter

This parameter defines the interpretation of two-digit (modulo 100) years. It is used by one of the Date class constructors and by some client programs.

  short centuryBreak // default=20
yy > centuryBreak means 19yy, yy <= centuryBreak means 20yy,

Static functions

These functions provide Gregorian calendar logic:

   boolean  isLeapYear(int yyyy)
   boolean  isLegalYMD(int yyyy, int mm, int dd)
   short    dayNumber (int yyyy, int mm, int dd)    //  Day number within the year

Return to Date and Calendar package

Return to Freeware directory
Return to IDI home page

Last modified March, 2003