The following article appeared in Enterprise magazine in the US and in several international IT publications.

"COBOL Rescues The Millennium"

by Jerome Garfunkel

For as many years as I can remember, COBOL programmers have been writing programs which calculated dates for various business operations: the age of consumer debt, the annuity on an investment, the monthly payments on a mortgage, the exact date "nnn" days (weeks, months years) from now, etc,. For just as many years, programmers have known that a "time bomb" has been planted in many of these business applications. This is so because in the year 2000, the final year of the current millennium, many of these programs will incorrectly calculate these date operations. The problem has arisen because of a general misunderstanding about the rules regarding which years are Leap years, and which years are not. To state the rule succinctly, leap years are divisible by 4 but not divisible by 100 unless divisible by 400. This makes the year 2000 a leap year; it is divisible by 4 and it is divisible by 400. Many of the COBOL programmers I spoke to during the 60's and 70's, had little concern for this problem because a) they believed they themselves would not be around in the nineties to have to worry about it or b) their COBOL programs (and perhaps the COBOL language itself) would not be around in the nineties for them to have to worry about it or c) someone would invent a magical solution to this problem. Well, just short of the calamity that everyone anticipated, the problem has in deed been solved. Those who believed in some magical solution (choice "c" above) turned out to be right. The COBOL language has been modified this year to include 6 new functions for programmers to manipulate and calculate dates.

Calendar Functions Illustrated

Forty-two new intrinsic functions have been added to the official American National Standard (ANS) COBOL 85 language. Six of these functions specifically deal with calendar and date operations. These new calendar functions are among the most useful for COBOL programmers. They will clearly save many hours of programming and debugging time. In fact, estimates range up to 25% for increased programmer productivity. The six new Calendar functions are:

CURRENT-DATE

WHEN-COMPILED

INTEGER-OF-DATE

INTEGER-OF-DAY

DATE-OF-INTEGER

DAY-OF-INTEGER

 

The CURRENT-DATE function returns current date and time information from the operating system to the program. This function expands upon the ACCEPT...FROM capability already in the COBOL 85 language as illustrated in the following statements:

ACCEPT todays-date FROM DATE

ACCEPT todays-julian FROM DAY

ACCEPT todays-time FROM TIME

ACCEPT weekday FROM DAY-OF-WEEK

In each of the statements above, the operating system returns a value, in a specific format, to the data name specified. The FROM DATE clause returns the Gregorian calendar date in 6 positions of (display) data in the format Y Y M M D D. The FROM DAY clause returns the date in Julian format, Y Y D D D. The FROM TIME clause returns the current operating system time in the format H H M M S S h h.11 Note the COBOL language committees were rather short sighted when they provide only two digits to represent the year. This is one reason (among others) why date operations in COBOL were not easily solvable. . For instance, the year 2000 would algebraically be considered less than the year 1999 (i.e. 00 is less than 99). This makes date arithmetic across century dates more difficult. As we approach the twenty-first century, this problem has become much more visible.

The new CURRENT-TIME intrinsic function returns all of the above information (and more) or at least provides the means to derive this information. Furthermore this problem of two-digit years is now a thing of the past.

 

Given the following data items, we will illustrate how to use the various Calendar functions:

01 purchase-date.

05 purchase-year PICTURE 9999.

05 purchase-month PICTURE 99.

05 purchase-day PICTURE 99.

01 julian-date-of-purchase.

05 purchase-julian-year PICTURE 9999.

05 purchase-julian-day PICTURE 999.

01 current-date-and-time.

03 todays-date.

05 current-year PICTURE 9999.

05 current-month PICTURE 99.

05 current-day PICTURE 99.

03 todays-time.

05 current-hour PICTURE 99.

05 current-minute PICTURE 99.

05 current-seconds PICTURE 99.

05 current-hundreths PICTURE 99.

05 current-offset PICTURE X.

05 current-offset-hr PICTURE 99.

05 current-offset-min PICTURE 99.

To simply access all the date and time information from the operating system we might include a statement such as:

MOVE FUNCTION CURRENT-DATE TO current-date-and-time.

The alphanumeric function, CURRENT-DATE (one of two that has no arguments) returns 21 positions of (display) data, as outlined in the data description above for current-date-and-time. Notice the value of the year is given as 4 positions; the current time is given as 13 positions, 5 of which are for Time-zone offsets from Greenwich mean time. The reader may be surprised to know (as I was when I learned it) that not all time zones are "integer hours" off from Greenwich mean time. There are some places on the globe where the time zone is 30 minutes or 15 minutes ahead/behind the time zones immediately adjacent. One such example is Iraq and Iran. While Turkey and Iraq share the same time zone, Iran is 30 minutes ahead of their time. Another such instance is the Chatham Islands just a few miles east of New Zealand. The time on the Chatham Islands is 15 minutes ahead of New Zealand. Hence the need for a "current-offset-minutes" field. (See the map in the Appendix.)

 

Two new functions are provided for doing arithmetic with dates. These are the INTEGER-OF-DATE and INTERGER-OF-DAY functions. Both of these functions return an integer value which represents the number of days elapsed between the date provided in the argument and the arbitrary date of January 1, 1601. In the case of INTEGER-OF-DATE, the argument date is provided in calendar format (Y Y Y Y M M D D); for the INTEGER-OF-DAY function, the argument date is provided in Julian format (Y Y Y Y D D D). The arbitrary "base" date of January 1, 1601 was chosen among other reasons because day number one fell on a Monday. This is consistent with the DAY-OF-WEEK clause of the ACCEPT statement which considers Monday to be the first day of the week. So long as that base date is consistent, "integer dates" provide us with a means to use dates in calculations. That is, they can now be used in any arithmetic expression requiring a numeric value. For instance, we can find the number of days elapsed between two different dates simply by converting both dates to integer values and then using these values in a simple arithmetic statement as illustrated here:

COMPUTE age-of-debt

= FUNCTION INTEGER-OF-DATE (todays-date)

- FUNCTION INTEGER-OF-DATE (purchase-date)

It makes no difference whether these dates are in different centuries, or incorporate leap years in their range. As long as the purchase date is after January 1, 1601, this calculation will work. (If by chance the purchase date is prior to 1/1/1601, this will have to handled manually.)

Two new functions, DATE-OF-INTEGER, and DAY-OF-INTEGER, give us the "reverse" functionality we have just seen. For instance, if we provide an integer value as an argument, the function will return the date (either in Gregorian or Julian format) corresponding to that integer.

 

A very popular procedure in many COBOL programs is the conversion of dates from one format to another, i.e. from Julian format to calendar format or visa-versa. We now have a very easy means of doing this as illustrated in the following example:

COMPUTE julian-date

= FUNCTION DAY-OF-INTEGER

(FUNCTION INTEGER-OF-DATE (purchase-date))

Notice in this example above the argument of the DAY-OF-INTEGER function is another function identifier, FUNCTION INTEGER-OF-DATE (purchase-date). This is allowed since the DAY-OF-INTEGER function requires an integer value as an argument; the INTEGER-OF-DATE function returns an integer value and therefore is acceptable to be used as an argument for the DAY-OF-INTEGER function. Of course we could have reversed this operation and converted a Julian date to calendar format just as easily using the DATE-OF-INTEGER function:

COMPUTE purchase-date

= FUNCTION DATE-OF-INTEGER

(FUNCTION INTEGER-OF-DAY (julian-date-of-purchase))

The WHEN-COMPILED function is the other new intrinsic function which has no argument associated with it. It simply returns 21 positions of display data representing the date and time (in calendar format) that the current executing object program was compiled. The exact format of the information returned is identical to the format of the returned value of the CURRENT-DATE function, which also returns 21 positions of (display) data. This is a handy function to use when developing an application. As the source (and object) program goes through numerous revisions and as each revision is tested, it is convenient to have a means of identifying (stamping) the test output with the particular version of the application program that produced it. One might use the following statement as a means of identifying the output:

MOVE FUNCTION WHEN-COMPILED INTO report-header

In a subsequent paper, I will discuss some of the other 38 new intrinsic functions which deal with: character and string manipulation, numerical analysis, mathematical and statistical calculations, business operations, and trigonometric functions. For a complete description of all the new intrinsic functions in the COBOL 85 language, see "COBOL Functions Illustrated," by Jerome Garfunkel, published by Micro Focus.