home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
mod201j.zip
/
modula2.exe
/
os2src
/
datefunc.mod
< prev
next >
Wrap
Text File
|
1996-01-31
|
7KB
|
259 lines
(* PROGRAM NAME : Date functions
* AUTHOR : Johan terryn
* COPYRIGHT (C) 1995 BY XINIX
* ────────────────────────────────────────────────────────────────────────────
* CREATED : 28/12/1995 *)
IMPLEMENTATION MODULE DateFunctions;
FROM OS2DEF IMPORT APIRET;
FROM DOSDATETIME IMPORT DATETIME, DosGetDateTime;
(*
TYPE DATE = RECORD
day, month, year : CARDINAL;
END;
DateFormat = (EURO, US, ANSI, ISO);
*)
(*$XL+*)
CONST dom : ARRAY OF CARDINAL = [31,29,31,30,31,30,31,31,30,31,30,31];
CONST Leap = 4; (* Leap years every 4 years *)
Century = 100; (* Years in a century *)
QuadCentury = 400; (* Years in four centuries *)
NormalYear = 365; (* Days in a non-leap year *)
FirstYear = 1583; (* Our first year *)
DaysIn4Years = 1461; (* Including leap day *)
VAR Dateformat : DateFormat;
PROCEDURE SetDateFormat(NewFormat: DateFormat) : DateFormat;
(*****************)
VAR OldFormat : DateFormat;
BEGIN
OldFormat := Dateformat;
Dateformat := NewFormat;
RETURN OldFormat
END SetDateFormat;
PROCEDURE Leapyear(year : CARDINAL) : BOOLEAN;
(*****************)
(* OK 28/12/1995 *)
BEGIN
RETURN ((year MOD 4 = 0) AND (year MOD 100 > 0)) OR (year MOD 400 = 0);
END Leapyear;
PROCEDURE ToDay(): DATE;
(******************)
VAR DateTime : DATETIME;
rc : APIRET;
Date : DATE;
BEGIN
rc := DosGetDateTime (DateTime);
Date.year := DateTime.year;
Date.month := DateTime.month;
Date.day := DateTime.day;
RETURN (Date);
END ToDay;
PROCEDURE ValidDate(date : DATE) : BOOLEAN;
(*****************)
(* 25/12/1995 verified, tested and OK *)
BEGIN
IF date.year >= FirstYear THEN
IF date.month IN {1,2,3,4,5,6,7,8,9,10,11,12} THEN
IF (date.day > 0) AND (date.day <= dom[date.month-1]) THEN
IF (date.day = 29) AND (date.month = 2) AND NOT Leapyear(date.year) THEN
RETURN FALSE
ELSE
RETURN TRUE
END (* if *)
END (* if *)
END (* if *)
END (* if *);
done := FALSE;
RETURN FALSE
END ValidDate;
PROCEDURE LeapDays(FromYear,ToYear: CARDINAL):CARDINAL;
(*****************)
(* tested 31/12/1995 *)
VAR days,i :CARDINAL;
BEGIN
days := 0;
FOR i := FromYear TO ToYear DO
IF Leapyear(i) THEN
INC(days)
END
END;
RETURN days
END LeapDays;
PROCEDURE Date2Num(date: DATE):LONGCARD;
(*****************)
(* tested 31/12/1995 *)
VAR month : CARDINAL;
yeardays, days: LONGCARD;
BEGIN
IF ValidDate(date) THEN
days := date.day;
yeardays := LONGCARD( date.year - FirstYear ) * NormalYear + LONGCARD( LeapDays(FirstYear,date.year-1) );
IF (date.month > 2) AND NOT Leapyear(date.year) THEN
DEC(days)
END; (* if *)
FOR month := 1 TO date.month-1 DO
INC(days,dom[month-1]);
END; (* while *)
done := TRUE;
RETURN days + yeardays
ELSE
done := FALSE;
RETURN 0
END (* if *)
END Date2Num;
PROCEDURE Num2Date(num : LONGCARD):DATE;
(*****************)
(* tested 31/12/1995 *)
VAR Dom : ARRAY [0..12] OF CARDINAL;
i : CARDINAL;
Refdate,Date : DATE;
leapdays : CARDINAL;
BEGIN
FOR i := 0 TO HIGH(Dom)-1 DO
Dom[i] := dom[i];
END;
IF (num = 0) THEN
Date.year := FirstYear - 1;
Date.month := 12;
Date.day := dom[Date.month-1];
ELSE
Date.year := CARDINAL (((Leap * (LONGINT (num) - 1)) DIV DaysIn4Years) + FirstYear);
Date.month := 1;
Refdate.year := Date.year;
Refdate.month := 1;
Refdate.day := 1;
Date.day := CARDINAL (LONGINT (num) - LONGINT (Date2Num(Refdate)-1));
IF NOT Leapyear(Date.year) THEN
Dom[1] := 28
END;
WHILE Date.day > Dom[Date.month-1] DO
DEC (Date.day, Dom[Date.month-1]);
INC(Date.month)
END;
IF Date.month > 12 THEN
Date.month := Date.month - 12;
INC(Date.year)
END
END;
RETURN Date
END Num2Date;
PROCEDURE DayOfWeek(date : DATE) : CARDINAL;
(*****************)
(*25/12/1995 returns day of the week as a number, ISO (monday = 1, sunday = 7) verified , tested and OK valid from 01/01/1583*)
BEGIN
RETURN CARDINAL((Date2Num(date) -3) MOD 7)+1
END DayOfWeek;
PROCEDURE Easter(Year : CARDINAL) : DATE;
(***************)
(* tested and OK *)
(*Easter : Spencer Jones in General Astronomy (pg 73-74) Ed 1922
* Journal of the British Astronomical Association Vol. 88, pg. 91 (dec 1977)
* From original dated 1876 Butcher's Eclesiastical Calendar.
* No exceptions, valid from 1583 *)
VAR a,b,c,d,e,f,g,h,i,k,l,m,n,p : CARDINAL;
Date : DATE;
BEGIN
IF Year >= FirstYear THEN
a := Year MOD 19; (* Lunar cycle = 19 years, Full moon on January 1st AD 0000*)
b := Year DIV 100;
c := Year MOD 100;
d := b DIV 4;
e := b MOD 4;
f := (b + 8) DIV 25;
g := (b - f + 1)DIV 3;
h := (19 * a + b - d - g + 15) MOD 30;
i := c DIV 4;
k := c MOD 4;
l := (32 + 2 * e + 2 * i - h - k) MOD 7;
m := (a + 11 * h + 22 * l) DIV 451;
n := (h + l - 7 * m + 114) DIV 31 ;
p := (h + l - 7 * m + 114) MOD 31;
IF (p = 0) THEN INC(p); DEC(n) END;
Date.day := p;
Date.month := n;
Date.year := Year;
AddDays(Date,1);
RETURN Date
ELSE
done := FALSE;
RETURN Date
END
END Easter;
PROCEDURE DiffDates(date1, date2 : DATE):LONGINT;
(******************)
BEGIN
RETURN LONGINT(Date2Num(date1)) - LONGINT(Date2Num(date2));
END DiffDates;
PROCEDURE AddDays(VAR date:DATE; days : LONGINT);
(****************)
BEGIN
IF ValidDate(date) THEN
IF ((days + LONGINT(date.day)) < LONGINT(dom[date.month-1])) AND
((days + LONGINT(date.day)) > 0) THEN
date.day := CARDINAL(LONGINT(date.day)+days)
ELSE
date := Num2Date(LONGCARD(LONGINT(Date2Num(date))+days))
END (* if *)
END; (* if *)
done := ValidDate(date)
END AddDays;
PROCEDURE Date2String(Date :DATE; VAR Datum : ARRAY OF CHAR);
(********************)
VAR DayPos,MonthPos,YearPos : CARDINAL;
BEGIN
IF (HIGH(Datum) >= 10) AND (ValidDate(Date)) THEN
CASE Dateformat OF
| EURO .. ISO : DayPos := 0;
Datum[2] := '/';
MonthPos := 3;
Datum[5] := '/';
YearPos := 6;
Datum[10]:= CHR(0);
| US : MonthPos := 0;
Datum[2] := '-';
DayPos := 3;
Datum[5] := '-';
YearPos := 6;
Datum[10]:= CHR(0);
| ANSI : YearPos := 0;
Datum[4] := '-';
MonthPos := 5;
Datum[7] := '-';
DayPos := 8;
Datum[10]:= CHR(0);
END (* Case *);
Datum[DayPos] := CHR((Date.day DIV 10) + 48);
Datum[DayPos+1] := CHR((Date.day MOD 10) + 48);
Datum[MonthPos] := CHR((Date.month DIV 10) + 48);
Datum[MonthPos+1] := CHR((Date.month MOD 10) + 48);
Datum[YearPos] := CHR((Date.year DIV 1000)+ 48);
Date.year := Date.year MOD 1000;
Datum[YearPos+1] := CHR((Date.year DIV 100) + 48);
Date.year := Date.year MOD 100;
Datum[YearPos+2] := CHR((Date.year DIV 10) + 48);
Datum[YearPos+3] := CHR((Date.year MOD 10) + 48);
done := TRUE;
ELSE
Datum[0] := CHR(0);
done := FALSE;
END
END Date2String;
BEGIN
Dateformat := EURO;
END DateFunctions.