                                                                        Managing
                                                                           Dates





         "The brain is a wonderful organ; it starts the minute you get up in the
         morning and does not stop until you get to the office."

                                                                    Robert Frost







         Date manipulation has always been a problem for computer programmers.
         If only there were ten days in a week, ten weeks in a year, and ten
         years in a century! Date mathematics is just plain clumsy when you
         think of dates in days, months and years. Try computing the date one
         hundred days after February 20, 1956! Not so easy.

         Date mathematics is greatly simplified when you convert dates into
         their Julian form. Over the centuries, many mathematicians have devised
         methods of accurately computing dates. Most modern computer systems
         (including this Toolkit!) use the Julian system. The Julian period was
         devised in 1582 by Joseph Scaliger, and was named after his father
         Julias (not after the Julian calendar). The Julian system assigns each
         day its own unique number. Day 1 began at noon, January 1, 4713 B.C.
         Every day since that time has its own sequential number, and February
         11, 1991 is Julian period 2448299.

         The totDATE unit provides a variety of functions for converting dates
         to and from Julian format. To compute the date one hundred days after
         February 20, 1956, you would convert the date to Julian, add one
         hundred to it, and convert it back to a string. This can be achieved
         with the following compound statement using Toolkit functions.

                  FancyDateStr(GregToJul(2,20,1956)+100,true,true);

         This uses the function GregToJul to convert Month/Day/Year to a Julian
         period. A hundred is then added to it, and this value is passed to the
         function FancyDateStr, which returns a text string showing the day and
         date represented by the Julian period. In this example, the following
         date would be returned:

                  Wednesday May 30, 1956

         The Toolkit supports dates in eight different formats. Using M, D and Y
         to represent months, days and years respectively, the supported formats
         are:

                                  MMDDYY
                                  MMDDYYYY
                                  MMYY
                                  MMYYYY
                                  DDMMYY

13-2                                                                User's Guide

--------------------------------------------------------------------------------

                                  DDMMYYYY
                                  YYMMDD
                                  YYYYMMDD

         Many of the totDATE functions need to know in which format the date
         strings are, and so the unit includes the enumerated type tDate, which
         (not surprisingly) has the following members: MMDDYY, MMDDYYYY, MMYY,
         MMYYYY, DDMMYY, DDMMYYYY, YYMMDD and YYYYMMDD.




           Note: if you plan to delve into ancient history with your date
           calculations, you need to be aware of some strange facts. For
           example, different countries decided to drop certain days to
           adjust for inaccuracies in the lunar calendar. In 1752, the Brit-
           ish decreed that the day following September 2 would be September
           14. Further back in 1582, Pope Gregory XIII (of Gregorian calendar
           fame!) decreed that October 4 would become October 15. In 1793 the
           French .... well, you get the idea. For a good summary of these
           calendar aberrations, refer to any copy of The World Almanac and
           Book of Facts.




Using DateTOT

         The totDATE unit includes the object DateOBJ, and a global instance of
         this object, DateTOT. This instance is used to control two of the
         default date configurations. The following two methods control these
         defaults:


         SetLastYearNextCentury(yr:byte);

         When a year is specified with only two digits, the Toolkit has to
         decide to which century the year refers. This method is used to set the
         largest year, which will be interpreted as falling in the next century.
         For example, if this method is passed a value of 50, then the two digit
         year 50 will be assumed to be 2050, and the two digit year 51 will be
         assumed to be 1951. By default, this year is set to 20.


         SetSeparator(Sep:char);

         When dates are displayed in their numeric form, a character is used to
         separate the days from the months from the years, e.g. 12-01-1990. This
         default is used to control which character will be used as the separa-
         tor. By default, the character is a slash, i.e. '/'.



         The following two function methods return the current settings:



Managing Dates                                                              13-3

--------------------------------------------------------------------------------

         GetLastYearNextCentury: byte;
         GetSeparator: char;



         Another purpose of the DateOBJ object is to control how the days of the
         week and months are spelled. This feature is provided for international
         users who want to use a different language. The following DateOBJ meth-
         ods are supported:


         SetMonths(M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12: StrShort);

         This method defines how the months will be spelled. The method is
         passed twelve strings representing the months January through December.


         SetDays(D0,D1,D2,D3,D4,D5,D6:StrShort);

         This method defines how the days will be spelled. The method is passed
         seven strings representing the days Sunday through Saturday.


         GetMonth(Mth:byte):string;

         This function method returns a string representing a specific month.
         The method is passed a byte parameter, with a value between one and
         twelve, to indicate which month you want returned.


         GetDay(Day:byte):string;

         This function method returns a string representing a specific day. The
         method is passed a byte parameter, with a value between zero and six,
         to indicate which month you want returned. Day zero represents Sunday.



Date Functions

         Listed below are the functions used to manipulate date numbers and
         strings:

GregToJul

         GregToJul(M,D,Y:longint): longint;

         Returns the Julian value of a Gregorian date. The function is passed
         three parameters of type byte, shortint, integer, word or longint; the
         first parameter is the month, the second is the day, and the third is
         the four-digit year. For example:

                  MyJul := GregToJul(3,21,1957);

         Assigns the value 1741959 to MyJul.


13-4                                                                User's Guide

--------------------------------------------------------------------------------

JulToGreg

         JulToGreg(Jul:longint; var M,D,Y:longint);

         This procedure converts a Julian date to Gregorian. The function is
         passed four parameters; the first is the source Julian date, and the
         remaining three parameters must be variables of type longint. The ini-
         tial values of these three variables are ignored, and they are updated
         with the month, day and year equivalent of the Julian value. For
         example:

                  var
                     Day,Mon,Yr: longint;
                  {...}
                  JulToGreg(2447654,Mon,Day,Yr);

         Assigns the values 5, 7 and 1989 to Mon, Day and Yr, respectively.



GregToStr

         GregToStr(M,D,Y:longint; Format:tDate):string;

         Returns a string representing the Gregorian date specified. The func-
         tion is passed four parameters; the first three parameters may be of
         type byte, shortint, word, integer or longint, representing the month,
         day and year. The fourth parameter is a member of the enumerated type
         tDate representing the desired string format. For example:

                  DStr := GregToStr(2,11,1991,DDMMYY);

         Assigns the value '11/02/91' to DStr.



JulToStr

         JulToStr(Jul:longint;Format:tDate):string;

         Returns a string representing a Julian date. The function is passed two
         parameters; the Julian date, and the date format. For example:

                  DStr := JulToStr(2448299,YYYYMMDD);

         Assigns the value '1991/02/11' to DStr.

DOWJul

         DOWJul(Jul:longint):byte;

         Returns a byte representing the day of the week for a Julian date. The
         function is passed one parameter; the Julian date. Zero represents
         Sunday, and six represents Saturday, all other days falling in between
         these two. For example:

Managing Dates                                                              13-5

--------------------------------------------------------------------------------

                  TheDay := DOWJul(2448299);

         Assigns the value 1 to TheDay, i.e. Monday.



DOWStr

         DOWStr(DStr:string; Format:tDate):byte;

         This function is similar to DOWJul in as much as it returns the day of
         the week for a specified date. In this case, however, the date is
         specified in string form. The function is passed two parameters; the
         date in string form, and the date format. For example:

                  TheDay := DOWStr('02/11/91',MMDDYY);

         Assigns the value 1 to TheDay.



Day

         Day(DStr:string; Format:tDate): word;

         This function returns the day represented by a date string. The func-
         tion is passed two parameters; the date in string form, and the date
         format. For example:

                  TheDay := Day('05/30/1956',MMDDYYYY);

         Assigns the value 30 to TheDay.


Month

         Month(DStr:string; Format:tDate): word;

         This function returns the month represented by a date string. The func-
         tion is passed two parameters; the date in string form, and the date
         format. For example:

                  TheMon := Month('30/05/1956',DDMMYYYY);

         Assigns the value 5 to TheMon.


Year

         Year(DStr:string; Format:tDate): word;

         This function returns the year represented by a date string. The func-
         tion is passed two parameters; the date in string form, and the date
         format. For example:

                  TheYr := Year('1956/05/30',YYYYMMDD);

13-6                                                                User's Guide

--------------------------------------------------------------------------------

         Assigns the value 1956 to TheYr.


ValidDate

         ValidDate(M,D,Y:longint):boolean;

         This function returns true if the Gregorian date specified is valid,
         i.e. the month is between one and twelve, and the day is valid for the
         specified month. The function is passed three parameters of type byte,
         shortint, word, integer or longint, representing the month, day and
         year, respectively. For example:

                  OK := ValidDate(2,31,1991);

         Assigns the value false to OK.


ValidDateStr

         ValidDateStr(DStr:string;Format:tDate):boolean;

         This function is similar to ValidDate, except that it validates a
         string date. The function is passed two parameters; the date in string
         form, and the date format. For example:

                  OK := ValidDateStr('02/28/1991',MMDDYYYY);

         Assigns the value true to OK.


TodayInJul

         TodayInJul:longint;

         This function calls a DOS interrupt, and returns the system's date in
         Julian form. It is passed no parameters. For example:

                  writeln(JulToStr(TodayInJul,DDMMYY));

         Writes the value of the system's date in string form.


StartOfYear

         StartOfYear(Jul:longint):longint;

         Returns the Julian date of January 1 of the year in which the passed
         date falls. The function is passed one parameter; the Julian date of
         the year to be returned. For example:

                  JanJul := StartOfYear(2448299);

         Assigns the value 2448258, representing the date Jan 1 1991, to JanJul.

Managing Dates                                                              13-7

--------------------------------------------------------------------------------

EndOfYear

         EndOfYear(Jul:longint):longint;

         Returns the Julian date of December 31 of the year in which the passed
         date falls. The function is passed one parameter; the Julian date of
         the year to be returned. For example:

                  DecJul := EndOfYear(2448299);

         Assigns the value 2448622, representing the date Dec 31 1991, to Dec-
         Jul.



RelativeDate

         RelativeDate(DStr:string; Format:tDate; Delta:longint):string;

         Returns a string representing a date, which is a specified number of
         days before or after a base date. The function is passed three parame-
         ters; the base date in string form, the date format, and the number of
         days from the base date. The last parameter may be positive or
         negative, depending on whether you want a date after or before the base
         date. For example:

                  DatStr := RelativeDate('04/05/91',MMDDYY,-7);

         Assigns the value '03/29/91' to DatStr.



StripDateStr

         StripDateStr(DStr:string; Format:tDate):string;

         This function returns a date string with the date separator removed.
         The function is passed two parameters; the date in string form, and the
         date format. For example:

                  SlimStr := StripDateStr('02/11/91',MMDDYY);

         Assigns the value '021191' to SlimStr.



FancyDateStr

         FancyDateStr(Jul:longint; Long,day:boolean): string;

         This function returns an attractively formatted string date. The func-
         tion is passed three parameters; the Julian date, and two boolean
         parameters to indicate the desired format. The first boolean parameter
         should be set to true if the month and day of week should be spelled
         out in their long form, or false to use the three character abbrevi-


13-8                                                                User's Guide

--------------------------------------------------------------------------------

         ation. The second boolean parameter should be set to true if the day of
         the week is to be included, or false if it is not required. For
         example:

                  FStr := FancyDateStr(2448299,true,true);

         Assigns the value 'Monday February 11, 1991' to FStr.



DateFormat

         DateFormat(Format:tDate):string;

         This function is passed a date format, and returns the string represen-
         tation of that format. For example:

                  MyStr := DateFormat(MMDDYYYY);

         Assigns the value 'MMDDYYYY' to MyStr.



Example

         Listed below is the demo program DEMDT2.PAS, followed by figure 13.1
         showing an example of the generated output.

         program DemoDateTwo;
         {DEMDT2 - example date statements}

         uses DOS,CRT, totDATE;

         var
          M,D,Y:longint;

         begin
            ClrScr;
            writeln(TodayInJul);
            writeln(JultoStr(TodayInJul,DDMMYYYY));
            writeln(FancyDateStr(TodayInJul,false,false));
            writeln(FancyDateStr(TodayInJul,true,false));
            writeln(FancyDateStr(TodayInJul,false,true));
            writeln(FancyDateStr(TodayInJul,true,true));
            writeln;
            writeln(RelativeDate('02/20/56',MMDDYY,90));
            writeln;
            writeln(JulToStr(StartOfYear(StrTo-
         Jul('30/06/1990',DDMMYY)),DDMMYY));
            writeln(JulToStr(EndOfYear(StrToJul('30/06/1990',DDMMYY)),DDMMYY));
            writeln;
            writeln(ValidDateStr('02/29/90',MMDDYY));
            writeln(ValidDate(2,29,90));
            writeln(DateFormat(MMDDYY));
         end.


Managing Dates                                                              13-9

--------------------------------------------------------------------------------

Figure 13.1                                                             [SCREEN]
Date
Functions



