home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 18 REXX
/
18-REXX.zip
/
fdater.zip
/
TRUEDATE.TXT
< prev
Wrap
Text File
|
1995-04-29
|
7KB
|
148 lines
======================================================================
TRUEDATE: A Portable Routine for Date Arithmetic
by Stephen Ferg
Copyright Stephen Ferg, 1994
======================================================================
AUTHOR: Stephen Ferg
608 N. Harrison Street
Arlington, VA 22203-1416
USA
telephone (voice, not FAX): (703) 525-2241
CompuServe ID : 73377,1157
Internet : ferg_s@bls.gov
Internet : 73377.1157@compuserve.com
=====================================================================
It's not hard to find a date arithmetic routine when you need one.
They are available in journal articles, in books, and on electronic
bulletin boards such as CompuServe. But if you are building a business
application, the chances that you will find a routine that you can
actually use are slim.
Most date arithmetic routines are direct or indirect descendants of a
FORTRAN algorithm published in 1968 by two astronomers: Henry F.
Fliegel of the Georgetown University Observatory, and Thomas C. Van
Flandern or the U.S. Naval Observatory.\1\ Consequently, their
fundamental concepts are drawn from astronomy, not business. For these
routines, a day is the time it takes for the earth to make one complete
rotation on its axis; a year is the time it takes for the earth to make
one complete revolution around the sun. For such routines, the number
of days in a year is not built into the concept year, but is something
to be discovered through scientific investigation. As we all know,
astronomers have discovered that a year is equal to approximately
365.25 days.
Astronomy-based routines typically depend on hard-coded "magic
numbers": a year is 365.2425 days, for example. A month is 367/12
days, or 30.6001 days, and so on. They also involve a lot of
back-and-forth multiplication/division operations. The purpose of the
repeated multiplication and division operations is to force truncation
of numbers that are stored internally in a particular format. You
might find, for example, a number being multiplied by 12 and then
immediately divided by 12, then multiplied by another number, and then
multiplied by 12 and divided by 12 again. The "magic numbers" truly
are magic, for they were carefully selected to interact with the
internal storage format of the numbers and the multiplication/division
cycles to produce the desired result.
These routines have two major drawbacks: (1) they are not portable, and
(2) they are not maintainable. Because they depend on numbers being
stored internally in a format determined by a particular language as
implemented by a particular compiler for a particular hardware
platform, such routines are usually not portable to another language or
another machine. (I've personally dealt with a COBOL version of the
Fliegel/Van Flandern algorithm that worked correctly on an IBM
mainframe but broke when ported to the MicroFocus COBOL compiler on a
PC.)
Second, they are unmaintainable because their magic numbers and
algorithms are derived primarily from the behavior of the platform they
were designed to run on, not from problem-domain concepts such as year
and leap year. Because the problem-domain basis of the algorithms is
so obscure, the algorithms are incomprehensible and unmodifiable. The
main problem you will have in using one of these routines is that you
will not be able to modify its leapyear scheme- the algorithm for
determining which years are leap years and which are not- if you need
to.
In order to overcome these problems, I developed a date routine called
TRUEDATE that is designed to be both portable and modifiable.
TRUEDATE is portable because its algorithms are independent of any
particular language, compiler, or hardware platform. It requires support only
for an integer data type of at least seven significant digits and normal
arithmetic operations on integers: addition, subtraction, multiplication,
integer division, and division remainder (modulo).
TRUEDATE is maintainable because its algorithms are based on the
application-domain logic of date concepts. For TRUEDATE:
* An ordinary year is a year that contains 365 days; in an ordinary year
February contains 28 days.
* A leap year is a year that contains 366 days; in a leap year February
contains 29 days.
* The leapyear scheme is clearly represented in TRUEDATE's source code.
In designing TRUEDATE, there were several possible leapyear schemes to
choose from, since several different leapyear schemes are in common use, or
have been proposed. Leapyear scheme #1 is:
Every year is an ordinary year
EXCEPT THAT every year evenly divisible by 4 is a leap year.
Scheme #2 adds the following exception to scheme #1:
EXCEPT THAT every year evenly divisible by 100 is not a leap year.
Scheme #3 adds the following exception to scheme #2:
EXCEPT THAT every year evenly divisible by 400 is a leap year.
Scheme #4\2\ adds the following exception to scheme #3:
EXCEPT THAT every year evenly divisible by 4000 is not a leap year.
TRUEDATE uses leapyear scheme #3. According to it:
1983 is nota leap year
1984 is a leap year
1900 is nota leap year
2000 is a leap year
The [REXX] source code for TRUEDATE is shown in [FDATER.REX]. Some
obvious opportunities for optimization have been ignored in order to
leave the pattern of the algorithm clear.
TRUEDATE is intended for business applications, not historical ones. It
knows nothing about historical changes in the calendar such as the 10-day jump
that occurred when Britain moved from the Julian to the Gregorian calendar in
the 18th century. As far as TRUEDATE is concerned, the calendar has followed
the same pattern, unchanged, since January 1, 0001.
Central to all date arithmetic routines is the concept of an "absolute" or
"true Julian" date: a date expressed as the number of days from some day in
the distant past. The apparently arbitrary base date for the Fliegel/Van
Flandern algorithm- January 1, 4713 BCE- reflects its basis in implementation,
rather than application-domain, considerations. TRUEDATE's base date is
January 1, 0001 (i.e. day 1 of month 1 of year 1). For this base, the absolute
date for January 1, 1992 is 727198.
The heart of TRUEDATE is two routines that, respectively, convert a calendar
date to and from an absolute date. With such routines available, doing date
arithmetic is easy. To determine, for example, an invoice date that is 60 days
in the future, one simply translates today's calendar date into an absolute
date, adds 60 to the absolute date, and translates the resulting absolute date
back into a calendar date. When absolute dates are available, day-of-week
determination is similarly easy. Dividing an absolute date by 7 will produce a
remainder in the range 0..6 that will tell you the number of the day of the
week.
REFERENCES
1. "A Machine Algorithm for Processing Calendar Dates", by Henry F.
Fliegel and Thomas C. Van Flandern, Communications of the ACM, Volume
11, Number 10, October 1968.
2. "The Dating Game" (Bit By Bit column), Stan Kelly-Bootle, Computer
Language, July, 1989.