home *** CD-ROM | disk | FTP | other *** search
- {$R+,S+,I+,D+,T+,F-,V+,B-,N-,L+ }
- UNIT Julian; {version 2.00 of 04/10/88}
- {
- This conversion by Carley Phillips (76630,3312) is placed in the PUBLIC DOMAIN.
-
- This Turbo Pascal 4.0 unit provides the most general Gregorian calendar
- procedures I've seen. A LongInt Julian day number is produced for any valid
- Gregorian calendar date without using tables of any kind. And, of course,
- a reverse conversion is provided. The mathematically valid range is
- 03-01-0000 through 12-31-65535. See discussion below of when the Gregorian
- system actually was put into use.
-
- The number of procedures provided here is deliberately restricted to a set of
- two time-tested critical calculations. In fact, every routine in the package
- is based on the calculations in either MDYtoJul or JulToMDY. The intent is
- partly to illustrate that these two procedures can then become the basis for
- more comprehensive set of procedures to determine the day of the week, test for
- a leap year, convert to/from ASCII, validate keyboard input, etc. Another part
- of the concept behind these routines is that of isolating the hard stuff into
- only two places.
-
- To summarize what is here:
- primary procedures:
- JulToMDY - convert Julian day to month, day, year
- MDYtoJul - convert month, day, year to Julian day
-
- useful functions:
- ValidJulToMDY - boolean function result plus above
- ValidMDYtoJul - boolean function result plus above
- DOWofJul - day of week returned from Julian day
- IsLeapYear - true if year specified is leap year
-
- if an application can use a 179-year range of dates, here's what's needed:
- IntToMDY - integer day to month, day, year (user-selected base point)
- MDYtoInt - month, day, year to integer day (user-selected base point)
- DOWofInt - day of week returned from integer day
-
- and if you really need the serial day (1-366) for a year:
- MDYtoSD - convert month, day for specified year to serial day number
- SDYtoMD - convert serial day number and year to month, day
-
- the following procedures are provided in the form of comments FIY
- IsLeapYearQ - this package doesn't use it, but here is what it takes
- ValidMDYQ - an alternate way to validate dates (Scott Bussinger)
- JulToMDYQ - an alternate way to convert without using IF statements
- MDYtoJulQ - an alternate way to convert without using IF statements
- ZellerQ - day of week using Zeller's technique
-
- The basic algorithms are based on those contained in the COLLECTED ALGORITHMS
- from Communications of the ACM, algorithm number 199, originally submitted
- by Robert G. Tantzen in the August, 1963 issue (Volume 6, Number 8). Note
- that these algorithms do not take into account that years divisible by 4000
- are NOT leap years. Therefore the calculations are only valid until
- 02-28-4000. I would be interested in any references to refereed updates to
- Tantzen's formulas to support higher dates.
-
- I have upgraded Tantzen's work on my own to include the years up to 65535.
- This upgrading is part of the reason for NOT using a mixture of methods. By
- using the two upgraded routines for leap year, day of week, and all other
- derivative calculations, then at least any errors can only be in a small
- number of places. By the way, I do NOT believe we will still be using the
- Gregorian calendar in the year 65535 or even in 4000.
-
- The main part of Tantzen's original algorithm depends on treating January and
- February as the last months of the preceding year. Then, one can look at a
- series of four years (for example, 3-1-84 through 2-29-88) in which the last
- day will be either the 1460th or the 1461st day depending on whether the 4-year
- series ended in a leap day. If you're curious what years are leap years, see
- the commented function IsLeapYearQ. However, Tantzen's formula and my additions
- to it avoid using this function directly. In fact, the leap year function
- actually compiled here is based on simply testing if 2-29 is a valid day for
- the year in question by using the modified Tantzen formula.
-
- An astronomers' Julian day number is a calendar system which is useful over
- a very large span of time. (January 1, 1988 A.D. is 2,447,162 in this system.)
- The mathematics of these procedures originally restricted the valid range to
- March 1, 0000 through February 28, 4000. The update in version 2.0 changes the
- valid end date to December 31, 65535. Note that the Julian day number is not
- the same as the serial day number (1-366) which is sometimes (erroneously)
- called a Julian date. Separate procedures are provided for the serial day.
-
- The Julian day can be biased by a constant to produce any kind of sequential
- day number imaginable. For example, the DOS date is based on 0 = 01-01-1980.
- If you subtract 2444240 from a Julian day, then you will get a number which is
- -32767 for 04-15-1890, 0 for 01-01-1980, and 32767 for 09-17-2069. This means
- that, for many applications where a date range of 179 years is sufficient,
- you may put a shell around MTDtoJul to return integer dates (perhaps reserving
- -32768 to indicate an invalid or null date) rather than LongInts.
-
- Such a routine is included here, but note that you must change the constant
- JulianInt from 2444240 to some other number if you want an integer range of
- dates different than that which DOS uses (that is, a range different from
- 04-15-1890 thru 09-17-2069).
-
- From (among others) Ted Lassagne (70325,206) of Cor Communications comes the
- following historical information. The Gregorian calendar was not in effect
- until 10-15-1582. Great Britain did not change to the Gregorian system until
- 1752, Russia until 1918, and Turkey until 1928.
-
- I found it interesting that the Gregorian-to-Julian and the Julian-to-Gregorian
- conversions can be done with no "if" tests at all. Robert B. Wooster
- (72415,1602) had some routines in the Turbo 3 library which he thought
- required an 8087 chip, but are here converted to Turbo 4 integers with no
- problems. He did not provide sufficient references to trace the code's
- history, but did make reference to being able to do the entire Gregorian
- to Julian conversion in a single assignment statement. I've put it back in
- that form but left the range checking wrapped around the conversion statement.
- In any case, the implementation without "if"s requires more calculations, so
- they are included here in commented form just for the curious to peruse. Note
- this algorithm has the same problem as Tantzen's (which it is apparently
- derived from) of not being valid past 02-28-4000.
-
- There is a method attributed to Zeller which calculates the day of the week
- with relatively few calculations. It is included here in a form I converted
- from ExDate by Ted Lassagne. Note that (at least Lassagne's version of)
- Zeller's method does not work past 02-28-4000.
-
- A check of BProgA DL 2 (Turbo Pascal 4) and DL 4 (other Turbo Pascals) on
- April 1, 1988, turned up the following files related to date conversions:
-
- Zeller.Inc - restricted to 1901-2099 (Zeller = DOW for restricted date range)
- ExDate.Arc - 1-3999, but no validity checking (origin of ZellerQ)
- Date.Arc - restricted to 1900-2078 (origin of ValidMDYQ)
- Calndr.Arc - Pascal demo program for Basic programmers, not general conversion
- NewJ1.Pas - restricted to 1900 - 2079
- Julian.Pas - 1-3999, reals, no checks, no IFs (origin of JulToMDYQ & MDYtoJulQ)
- JDate.Pas - restricted to 1900-2079, real arithmetic
- DD.Arc - specialized routines with no error checking
- ReadSt.Arc - restricted to 1901 - 2099
- Day.Pas - not conversion routines
- DayLib.Plb - restricted to 1888-2067, uses tables
-
- Revision History:
- 2.00 (04-05-88)
- a. Correction to Tantzen's original formula to correct for the fact that
- years which are a multiple of 4000 are NOT leap years. This allowed
- expanding the valid range to 12-31-65535 in case anybody cares.
- b. Major additions to initial comments.
- c. Change in range of valid dates.
- d. Change in method of some computations.
- e. Addition of leap year test function.
- f. Addition of Gregorian-to-integer, integer-to-Gregorian, and DOWofInt.
- g. Addition of serial day conversion procedures.
- h. Addition (as comments) of interesting no-if-statement conversions.
- i. Addition (as comments) of other possibly interesting routines.
- 1.00 (original version)
-
- When sufficient time has passed for comments, etc., the next planned step
- is to convert the two primary routines to inline since constructs such as
- (a div b) followed by (a mod b) are somewhat wasteful of processing time.
-
- Comments, suggestions, bug reports, etc. should be sent on Compuserve (via
- EasyPlex since I'm not necessarily on every few days) to
-
- Carley Phillips, 76630,3312.
- }
-
- {*****************************************************************************}
- INTERFACE
- {*****************************************************************************}
-
- const
- {Do not change these constants}
- JulianNull = -1; {Constant to indicate an invalid or null Julian day.}
- IntDateNull = -32768;{Constant to indicate an invalid or null integer day.}
- SerialDayNull= 0; {Constatn to indicate an invalid or null serial day.}
-
- type
- t_JulDay = longint; {the basic Julian day type}
- t_DOW = (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday,
- InvalidDOW);
-
- const
- {This constant is the Julian day which is to correspond to an integer day=0}
- {If you are using full 4-byte Julian day numbers, ignore this constant.}
- {Do not set this value below 1,753,887 or above 25,624,808.}
- JulianInt = 2444240; {This is initially 01-01-1980 to match DOS.}
-
- {
- A couple of useful string constants. Note that, handily, common
- abbreviations for both day and month names can be obtained with
- Copy (nameString[x], 1, 3);
- }
- DOWString : array [t_DOW] of string[10] =
- ('Sunday', 'Monday', 'Tuesday', 'Wednesday',
- 'Thursday', 'Friday', 'Saturday', 'InvalidDOW');
- MonthString : array [1..12] of string[9] =
- ('January', 'February', 'March', 'April', 'May', 'June',
- 'July', 'August', 'September', 'October', 'November', 'December');
-
- {-----------------------------------------------------------------------------}
- procedure JulToMDY ( JDay : t_JulDay; {valid Julian day number}
- var month : word; {Gregorian month returned}
- var day : word; {Gregorian day returned}
- var year : word); {Gregorian year returned}
- {--Converts an astronomer's Julian day to Gregorian month, day, and year.}
- {--If you're not sure JDay is valid, then use ValidJulToMDY.}
-
- {-----------------------------------------------------------------------------}
- procedure MDYtoJul ( month : word; {Gregorian calendar month}
- day : word; {Gregorian calendar day}
- year : word; {Gregorian calendar year}
- var JDay : t_JulDay); {Julian day number returned}
- {--Converts Gregorian month, day, year to a Julian day number.}
- {--If you're not sure month, day, year are valid then use ValidMDYtoJul.}
-
- {-----------------------------------------------------------------------------}
- function ValidJulToMDY (JDay : t_JulDay; {a Julian day number}
- var month : word; {Gregorian month returned}
- var day : word; {Gregorian day returned}
- var year : word {Gregorian year returned}
- ) : boolean; {true if the JDay is valid}
- {--Returns true and the month, day, year if the Julian day is valid.}
-
- {-----------------------------------------------------------------------------}
- function ValidMDYtoJul ( month : word; {Gregorian calendar month}
- day : word; {Gregorian calendar day}
- year : word; {Gregorian calendar year}
- var JDay : t_JulDay {Julian day number returned}
- ) : boolean; {true if month,day,year is valid}
- {--Returns true and the Julian day number if month, day, year are valid.}
-
- {-----------------------------------------------------------------------------}
- function DOWofJul ( JDay : t_JulDay {valid Julian day number}
- ) : t_DOW; {0 thru 6 for Sun thru Sat, 7=invalid}
- {--Returns the day of the week (as an integer) of a valid Julian day number}
-
- {-----------------------------------------------------------------------------}
- function IsLeapYear (year : word {the year to be tested}
- ) : boolean; {true if year is a leap year}
- {--Returns true if the year specified is a leap year}
-
- {-----------------------------------------------------------------------------}
- procedure IntToMDY ( IDay : integer; {valid integer day number}
- var month : word; {Gregorian month returned}
- var day : word; {Gregorian day returned}
- var year : word); {Gregorian year returned}
- {--Converts an integer day to Gregorian month, day, and year.}
-
- {-----------------------------------------------------------------------------}
- procedure MDYtoInt ( month : word; {Gregorian calendar month}
- day : word; {Gregorian calendar day}
- year : word; {Gregorian calendar year}
- var IDay : integer); {Integer day number returned}
- {--Converts Gregorian month, day, year to a integer day number.}
- {--Valid range is + or - 32767 from JulianInt constant. If this constant}
- {--is 2444240, then positive values of IDay will match DOS day number.}
-
- {-----------------------------------------------------------------------------}
- function DOWofInt ( IDay : integer {valid integer day number}
- ) : t_DOW; {0 thru 6 for Sun thru Sat, 7=invalid}
- {--Returns the day of the week (as an integer) of a valid integer day number}
-
- {-----------------------------------------------------------------------------}
- procedure SDYToMD ( SDay : integer; {valid serial day number}
- year : word; {valid year}
- var month : word; {Gregorian month returned}
- var day : word); {Gregorian day returned}
- {--Converts a valid serial day and year to month and day.}
-
- {-----------------------------------------------------------------------------}
- procedure MDYtoSD ( month : word; {Gregorian calendar month}
- day : word; {Gregorian calendar day}
- year : word; {Gregorian calendar year}
- var SDay : word); {Serial day number returned}
- {--Converts Gregorian month, day, year to 0 or a serial day number 1-366.}
-
- (*
- {-----------------------------------------------------------------------------}
- {Note that these routines are commented out. Interface was here for testing. }
- {-----------------------------------------------------------------------------}
- function IsLeapYearQ (year : word {the year to be tested}
- ) : boolean; {true if year is a leap year}
- {--Returns true if the year specified is a leap year}
-
- {-----------------------------------------------------------------------------}
- function ValidMDYQ ( month : word; {Gregorian calendar month}
- day : word; {Gregorian calendar day}
- year : word {Gregorian calendar year}
- ) : boolean; {true if month, day, year is valid}
- {--Returns true if month, day, year are valid for use with MDYtoJul.}
-
- {-----------------------------------------------------------------------------}
- procedure JulToMDYQ ( JDay : t_JulDay; {valid Julian day number}
- var month : word; {Gregorian month returned}
- var day : word; {Gregorian day returned}
- var year : word); {Gregorian year returned}
- {--Converts an astronomer's Julian day to Gregorian month, day, and year.}
-
- {-----------------------------------------------------------------------------}
- procedure MDYtoJulQ ( month : word; {Gregorian calendar month}
- day : word; {Gregorian calendar day}
- year : word; {Gregorian calendar year}
- var JDay : t_JulDay); {Julian day number returned}
- {--Converts Gregorian month, day, year to a Julian day number.}
-
- {-----------------------------------------------------------------------------}
- function ZellerQ (month : word;
- day : word;
- year : word
- ) : t_DOW;
- {--Return day of week of month, day, year using Zeller's method}
- *)
- {*****************************************************************************}
- IMPLEMENTATION
- {*****************************************************************************}
-
- const
- JulianConstant = 1721119; {constant for Julian day for 02-28-0000}
- {numbers outside the following range can not be converted back to Gregorian}
- JulianMin = 1721120; {constant for Julian day for 03-01-0000}
- JulianMax = 25657575; {constant for Julian day for 12-31-65535}
-
- {*****************************************************************************}
- procedure JulToMDY ( JDay : t_JulDay; {valid Julian day number}
- var month : word; {Gregorian month returned}
- var day : word; {Gregorian day returned}
- var year : word); {Gregorian year returned}
- {--Converts an astronomer's Julian day to Gregorian month, day, and year.}
- {--If you're not sure JDay is valid, then use ValidJulToMDY.}
- var
- tmp1 : longint;
- tmp2 : longint;
- begin {JulToMDY}
- if (JulianMin <= JDay) and (JDay <= JulianMax) then
- begin
- tmp1 := JDay - JulianConstant; {will be at least 1}
- year := ((tmp1-1) div 1460969) * 4000;
- tmp1 := ((tmp1-1) mod 1460969) + 1;
- tmp1 := (4 * tmp1) - 1;
- tmp2 := (4 * ((tmp1 mod 146097) div 4)) + 3;
- year := (100 * (tmp1 div 146097)) + (tmp2 div 1461) + year;
- tmp1 := (5 * (((tmp2 mod 1461) + 4) div 4)) - 3;
- month := tmp1 div 153;
- day := ((tmp1 mod 153) + 5) div 5;
- if (month < 10) then
- month := month + 3
- else
- begin
- month := month - 9;
- year := year + 1;
- end {else}
- end {if}
- else
- begin
- month := 0;
- day := 0;
- year := 0;
- end; {else}
- end; {JulToMDY}
-
- {*****************************************************************************}
- procedure MDYtoJul ( month : word; {Gregorian calendar month}
- day : word; {Gregorian calendar day}
- year : word; {Gregorian calendar year}
- var JDay : t_JulDay); {Julian day number returned}
- {--Converts Gregorian month, day, year to a Julian day number.}
- {--If you're not sure month, day, year are valid then use ValidMDYtoJul.}
- var
- tMon : longint;
- tYear : longint;
- begin {MDYtoJul}
- if (month > 2) then
- begin
- tMon := month - 3;
- tYear := year;
- end {if}
- else
- begin
- tMon := month + 9;
- tYear := longint(year) - 1;
- end; {else}
- JDay := (tYear div 4000) * 1460969;
- tYear := (tYear mod 4000);
- JDay := JDay +
- (((tYear div 100) * 146097) div 4) +
- (((tYear mod 100) * 1461) div 4) +
- (((153 * tMon) + 2) div 5) +
- day +
- JulianConstant;
- if (JDay < JulianMin) or (JulianMax < JDay) then
- JDay := JulianNull;
- end; {MDYtoJul}
-
- {*****************************************************************************}
- function ValidJulToMDY (JDay : t_JulDay; {a Julian day number}
- var month : word; {Gregorian month returned}
- var day : word; {Gregorian day returned}
- var year : word {Gregorian year returned}
- ) : boolean; {true if the JDay is valid}
- {--Returns true and the month, day, year if the Julian day is valid.}
- begin {ValidJulToMDY}
- JulToMDY (JDay, month, day, year);
- ValidJulToMDY := (month <> 0);
- end; {ValidJulToMDY}
-
- {*****************************************************************************}
- function ValidMDYtoJul ( month : word; {Gregorian calendar month}
- day : word; {Gregorian calendar day}
- year : word; {Gregorian calendar year}
- var JDay : t_JulDay {Julian day number returned}
- ) : boolean; {true if month,day,year is valid}
- {--Returns true and the Julian day number if month, day, year are valid.}
- var
- tmon : word;
- tday : word;
- tyear : word;
- begin {ValidMDYtoJul}
- MDYtoJul (month, day, year, JDay);
- JultoMDY (JDay, tmon, tday, tyear);
- ValidMDYtoJul := (tmon=month) and (tday=day) and (tyear=year);
- end; {ValidMDYtoJul}
-
- {*****************************************************************************}
- function DOWofJul ( JDay : t_JulDay {valid Julian day number}
- ) : t_DOW; {0 thru 6 for Sun thru Sat, 7=invalid}
- {--Returns the day of the week (as an integer) of a valid Julian day number}
- begin {DOWofJul}
- if (JulianMin <= JDay) and (JDay <= JulianMax) then
- DOWofJul := t_DOW (succ(JDay) mod 7) {use DOS standard of 0=Sunday}
- else
- DOWofJul := InvalidDOW;
- end; {DOWofJul}
-
- {*****************************************************************************}
- function IsLeapYear (year : word {the year to be tested}
- ) : boolean; {true if year is a leap year}
- {--Returns true if the year specified is a leap year}
- var
- tJul : t_JulDay;
- begin {IsLeapYear}
- IsLeapYear := ValidMDYtoJul (2, 29, year, tJul);
- end; {IsLeapYear}
-
- {*****************************************************************************}
- procedure IntToMDY ( IDay : integer; {valid integer day number}
- var month : word; {Gregorian month returned}
- var day : word; {Gregorian day returned}
- var year : word); {Gregorian year returned}
- {--Converts an integer day to Gregorian month, day, and year.}
- begin {IntToMDY}
- if IDay = IntDateNull then
- JulToMDY (JulianNull, month, day, year) {use to set m,d,y to 0}
- else
- JulToMDY (IDay+JulianInt, month, day, year);
- end; {IntToMDY}
-
- {*****************************************************************************}
- procedure MDYtoInt ( month : word; {Gregorian calendar month}
- day : word; {Gregorian calendar day}
- year : word; {Gregorian calendar year}
- var IDay : integer); {Integer day number returned}
- {--Converts Gregorian month, day, year to a integer day number.}
- {--Valid range is + or - 32767 from JulianInt constant. If this constant}
- {--is 2444240, then positive values of IDay will match DOS day number.}
- var
- tJul : t_JulDay;
- begin {MDYtoInt}
- IDay := IntDateNull;
- if not ValidMDYtoJul (month, day, year, tJul) then
- exit;
- tJul := tJul - JulianInt;
- if (-32767 <= tJul) and (tJul <= 32767) then
- IDay := tJul;
- end; {MDYtoInt}
-
- {*****************************************************************************}
- function DOWofInt ( IDay : integer {valid integer day number}
- ) : t_DOW; {0 thru 6 for Sun thru Sat, 7=invalid}
- {--Returns the day of the week (as an integer) of a valid integer day number}
- begin {DOWofInt}
- if (IDay <> IntDateNull) then
- DOWofInt := t_DOW ((IDay + JulianInt + 1) mod 7)
- else
- DOWofInt := InvalidDOW;
- end; {DOWofInt}
-
- {*****************************************************************************}
- procedure SDYToMD ( SDay : integer; {valid serial day number}
- year : word; {valid year}
- var month : word; {Gregorian month returned}
- var day : word); {Gregorian day returned}
- {--Converts a valid serial day and year to month and day.}
- var
- tJul : t_JulDay;
- tYear : word;
- begin {IntToMDY}
- {
- As long as nobody mucks with SerialDayNull=0, then this is caught below.
- if SDay = SerialDayNull then begin month := 0; day := 0; exit; end;
- }
- {We want 60-0 to 365-0 to work, so just treat 0 as 1 (neither are leap)}
- if year = 0 then
- inc(year); {local copy only!}
- MDYtoJul (1,1,year,tJul); {what is January 1?}
- JulToMDY (pred(tJul+SDay), month, day, tyear);
- if tyear <> year then {serial day number was 0 or too large for year}
- begin
- month := 0;
- day := 0;
- end;
- end; {IntToMDY}
-
- {*****************************************************************************}
- procedure MDYtoSD ( month : word; {Gregorian calendar month}
- day : word; {Gregorian calendar day}
- year : word; {Gregorian calendar year}
- var SDay : word); {Serial day number returned}
- {--Converts Gregorian month, day, year to 0 or a serial day number 1-366.}
- var
- tJul1 : t_JulDay;
- tJul2 : t_JulDay;
- begin {MDYtoSD}
- SDay := SerialDayNull;
- {We want 3-1-0 to 12-31-0 to work, so just treat 0 as 1 (neither are leap)}
- if year = 0 then
- inc(year); {local copy only!}
- if not ValidMDYtoJul (month, day, year, tJul1) then
- exit;
- MDYtoJul (1,1,year,tJul2); {what is January 1?}
- SDay := succ(tJul1-tJul2);
- end; {MDYtoSD}
-
- (*
- {*****************************************************************************}
- {NOTE THAT ALL OF THE 5 ROUTINES BELOW ARE COMMENTS FOR YOUR INFORMATION }
- { THEY MUST USE A JULIANMAXQ = 3,182,088 TO FUNCTION PROPERLY! }
- {*****************************************************************************}
- const
- JulianMaxQ = 3182088; {constant for Julian day for 02-28-4000}
-
- {*****************************************************************************}
- {
- This is the logical way of figuring this out with little math.
- }
- function IsLeapYearQ (year : word {the year to be tested}
- ) : boolean; {true if year is a leap year}
- {--Returns true if the year specified is a leap year}
- begin {IsLeapYearQ}
- IsLeapYearQ := ((year mod 4) = 0) and ((year mod 4000) <> 0) and
- (((year mod 100) <> 0) or ((year mod 400) = 0));
- end; {IsLeapYearQ}
-
- {*****************************************************************************}
- {
- Converted from a routine by Scott Bussinger. Included here as comments
- simply to allow curious readers to see a different way to accomplish
- validation without actually getting a Julian day number and converting back.
- The code has been compiled and tested. It produces the same results as
- ValidMDYtoJul over the same range except that a Julian day is not returned.
- Since Scott's version was for a 179 year or so range, so some tests were
- modified to get the range up to (almost) 65536 years.
- }
- function ValidMDYQ ( month : word; {Gregorian calendar month}
- day : word; {Gregorian calendar day}
- year : word {Gregorian calendar year}
- ) : boolean; {true if month, day, year is valid}
- {--Returns true if month, day, year are valid for use with MDYtoJul.}
- var
- tmon : word;
- tday : word;
- tyear : word;
- begin {ValidMDYQ}
- if (Day=0) or (Month=0) or (Month>12) or ((Year=0) and (Month<3)) then
- ValidMDYQ := false
- else
- case Month of
- 2: ValidMDYQ := Day <= 28 + ord(IsLeapYearQ(year));
- 4,6,9,11: ValidMDYQ := Day <= 30;
- else ValidMDYQ := Day <= 31;
- end;
- end; {ValidMDYQ}
-
- {*****************************************************************************}
- {
- Converted from a routine by Robert B. Wooster. Included here as comments
- simply to allow curious readers to see a conversion without using "IF".
- The code has been compiled and tested. It produces the same results as
- JulToJDY over the range from 03-01-0000 through 02-28-4000 but does not
- account for every 4000 years being a non-leap year.
- }
- procedure JulToMDYQ ( JDay : t_JulDay; {valid Julian day number}
- var month : word; {Gregorian month returned}
- var day : word; {Gregorian day returned}
- var year : word); {Gregorian year returned}
- {--Converts an astronomer's Julian day to Gregorian month, day, and year.}
- var
- tmp1 : longint;
- tmp2 : longint;
- tmp3 : longint;
- tmp4 : longint;
- begin {JulToMDYQ}
- if (JulianMin <= JDay) and (JDay <= JulianMaxQ) then
- begin
- tmp1 := JDay + 68569;
- tmp2 := 4 * tmp1 div 146097;
- tmp1 := tmp1 - ((146097 * tmp2 + 3) div 4);
- tmp3 := 4000 * (tmp1+1) div 1461001;
- tmp1 := tmp1 - (1461*tmp3 div 4) + 31;
- tmp4 := 80 * tmp1 div 2447;
- day := tmp1 - (2447 * tmp4 div 80);
- tmp1 := tmp4 div 11;
- month := tmp4 + 2 -12 * tmp1;
- year := 100*(tmp2 - 49) + tmp3 + tmp1;
- end {if}
- else
- begin
- month := 0;
- day := 0;
- year := 0;
- end; {else}
- end; {JulToMDYQ}
-
- {*****************************************************************************}
- {
- Converted from a routine by Robert B. Wooster. Included here as comments
- simply to allow curious readers to see a conversion without using "IF".
- The code has been compiled and tested. It produces the same results as
- MDYtoJul over the range from 03-01-0000 through 02-28-4000 but does not
- account for every 4000 years being a non-leap year. Wooster attributed
- the technique to a Fortran one-assignment statement conversion from a place
- which he did not specify. The two-statement version here is simply to
- avoid repeating a division 3 extra times.
- }
- procedure MDYtoJulQ ( month : word; {Gregorian calendar month}
- day : word; {Gregorian calendar day}
- year : word; {Gregorian calendar year}
- var JDay : t_JulDay); {Julian day number returned}
- {--Converts Gregorian month, day, year to a Julian day number.}
- var
- tmp : longint;
- begin {MDYtoJulQ}
- tmp := (longint(month) - 14) div 12;
- JDay := longint(day) - 32075 +
- (1461 * ( longint(year) + 4800 + tmp ) div 4 ) +
- ( 367 * ( longint(month) - 2 - tmp * 12 ) div 12) -
- ( 3 * ((longint(year) + 4900 + tmp) div 100) div 4);
- if (JDay < JulianMin) or (JulianMaxQ < JDay) then
- JDay := JulianNull;
- end; {MDYtoJulQ}
-
- {*****************************************************************************}
- {
- Converted from a routine by Ted Lassagne. Included here as comments simply
- to allow curious readers to see Zeller's technique for obtaining the day of
- the week by a different method. The code has been compiled and tested. It
- produces the same results as JulToDOW over the range from year 1 through
- year 3999 but does not account for every 4000 years being a non-leap year.
- }
- function ZellerQ (month : word;
- day : word;
- year : word
- ) : t_DOW;
- {--Return day of week of month, day, year using Zeller's method}
- var
- tyear : longint;
- tmonth : integer;
- cen : integer;
- dow : integer;
- begin {ZellerQ}
- if (year >= 4000) then
- begin
- ZellerQ := InvalidDOW;
- exit;
- end;
- if month < 3 then
- begin
- tmonth := month + 10;
- tyear := longint(year) -1
- end
- else
- begin
- tmonth := month - 2;
- tyear := year;
- end;
- cen := tyear div 100;
- tyear := tyear mod 100;
- dow := ((cen div 4) -
- (2*cen) +
- tyear +
- (tyear div 4) +
- ((26*tmonth - 2) div 10) +
- day) mod 7;
- ZellerQ := t_DOW((dow + 7) mod 7);
- end; {ZellerQ}
-
- {*****************************************************************************}
- {NOTE THAT ALL OF THE ABOVE 5 ROUTINES ARE COMMENTS FOR YOUR INFORMATION }
- {*****************************************************************************}
- *)
-
- end.