home *** CD-ROM | disk | FTP | other *** search
- { Full source within a sample program, containing the following
- routines:
- n:=ymd2n(y,m,d); returns integer relative to Sep 19, 1989. The allowable
- date range is 1900 thru 2078.
- n2ymd(0,y,m,d); reverse of above. 0 results in 1989,9,19 for y,m,d.
- w:=n2dow(n) and w:=ymd2dow(y,m,d); returns 1=mon,2=tue,...7=sun
- dys:=nn2d(n1,n2) or dys:=dif(y1,m1,d1,y2,m2,d2); returns days between dates
- wkdys:=nn2w(n1,n2) or wkdys:=wdif(y1,m1,d1,y2,m2,d2); returns weekdays in range
- dys:=dim(y,m); returns days in the specified year/month.
- If ymdok(y,m,d) then... returns true if date in range and all fields valid.
- s:=n2s(n) or n:=ymd2s(y,m,d); returns date as string in format:
- "Saturday, the 24th of April, 1948"
- n:=newn(n,adj) or newymd(adj,y,m,d); adjusts given date forward or backward
- n:=n2w(n,5) or ymd2w(5,y,m,d); if not already friday, date is moved forward
- n:=n2pw(n,1) or ymd2pw(1,y,m,d); if not already monday, moved back in time
-
- Take care that you don't exceed maxint in the routines where 2 days are given.
- In other words, dif(1910,1,1,2045,12,31) returns a negative number. As long as
- dates are less than 90 years apart, you're fine. If you don't like the range
- 1900..2078, then change then the BaseYear const to other than 1900. The ymd2n
- routine is derived from a julian date algortihm posted by Bob Brown in
- soft.eng/algortihm, of which he is a moderator.
- If you change the BaseYear, you should also change the range checking in
- ymdok. You might also want to change the 'adjust' const to line up the dates
- for your new range. Lastly, you'll have to 'tweak' the 'n2dow' routine unless
- you happen to be lucky!
- Any feedback/corrections/suggestions are appreciated, thanks! - Jim Keohane
- }
- Program tdates;
- var y,m,d,y2,m2,d2:integer;
- type anystring=string[255];
- const baseyear=1980; adjust=-100;
-
- Function ymd2n(y,m,d:integer):integer;
- {returns day number relative to Sep 19, 1989}
- begin
- ymd2n := 367*(y-baseyear)
- -7*(y+(m+9) div 12) div 4
- -3*((y+(m-9) div 7) div 100+1) div 4
- +275*m div 9
- +d
- +adjust
- end;
-
- Function dim(y,m:integer):integer;
- {returns days in given month}
- begin
- if m=12 then dim:=ymd2n(y+1,1,1)-ymd2n(y,m,1)
- else dim:=ymd2n(y,m+1,1)-ymd2n(y,m,1)
- end;
-
- Procedure n2ymd(n:integer;var y,m,d:integer);
- {given relative day, returns y,m,d}
- var i:integer;
- begin
- y:=1989 + n div 365; m:=1; d:=1; {quick guess at year}
- i:=ymd2n(y,m,d);
- while i>n do
- begin
- y:=y-1;
- i:=ymd2n(y,m,d)
- end;
- m:=1+(n-i) div 31; {quick guess at month}
- while m>12 do begin y:=y+1; m:=m-12 end;
- i:=ymd2n(y,m,d);
- while dim(y,m) < n-i+1 do
- begin
- m:=m+1;
- if m>12 then begin y:=y+1; m:=1 end;
- i:=ymd2n(y,m,d)
- end;
- d:=1+n-i;
- end;
-
- Function n2dow(n:integer):integer;
- {returns day of week 1=mon...6=sat,7=sun}
- begin
- n2dow:=1+(n mod 7+8) mod 7;
- end;
-
- Function ymd2dow(y,m,d:integer):integer;
- begin
- ymd2dow:=n2dow(ymd2n(y,m,d))
- end;
-
- Function ymdok(y,m,d:integer):boolean;
- {returns true if valid date}
- begin
- if (y<1900) or (y>2078) or (m<1) or (m>12) or (d<1) then
- ymdok:=false else ymdok:=d<=dim(y,m)
- end;
-
- Function ymd2s(y,m,d:integer):anystring;
- {returns date string "Saturday, the 21st of April, 1979"}
- var s:anystring;
- day,year,th:string[4];
- const days:array[1..7] of string[6]=
- ('Mon','Tues','Wednes','Thurs','Fri','Satur','Sun');
- months:array[1..12] of string[9]=
- ('January','February','March','April','May','June',
- 'July','August','September','October','November','December');
- begin
- if d in [1,21,31] then th:='st' else
- if d in [2,22] then th:='nd' else
- if d in [3,23] then th:='rd' else th:='th';
- str(d,day);
- str(y,year);
- ymd2s:=days[ymd2dow(y,m,d)]+'day, the '+day+th+' of '+months[m]+', '+year
- end;
-
- Function nn2d(n1,n2:integer):integer;
- {returns signed difference in days of n2-n1}
- begin
- nn2d:=n2-n1
- end;
-
- Function dif(y1,m1,d1,y2,m2,d2:integer):integer;
- {returns signed difference in days of ymd2-ymd1}
- begin
- dif:=nn2d( ymd2n(y1,m1,d1) , ymd2n(y2,m2,d2) )
- end;
-
- Function newn(oldn,adj:integer):integer;
- {returns oldn adjusted by adj days}
- begin
- newn:=oldn+adj
- end;
-
- Procedure newymd(adj:integer;var y,m,d:integer);
- {adjusts y,m,d by adj days}
- begin
- n2ymd ( newn( ymd2n(y,m,d) , adj) , y, m, d )
- end;
-
- Function n2w(n,w:integer):integer;
- {given desired weekday (w=1,2...7) returns n, moved forward, if neccessary}
- begin
- n2w:=newn(n, (w-n2dow(n)+7) mod 7)
- end;
-
- Function n2pw(n,w:integer):integer;
- {same as n2w, only movement is backwards, if neccessary}
- begin
- n2pw:= newn( n, ((w-n2dow(n)+7) mod 7 - 7) mod 7)
- end;
-
- Procedure ymd2w(w:integer;var y,m,d:integer);
- {if not desired weekday (w), moves ymd forward}
- begin
- n2ymd ( n2w( ymd2n(y,m,d) , w ) , y, m, d )
- end;
-
- Procedure ymd2pw(w:integer;var y,m,d:integer);
- {if not desired weekday (w), moves ymd backward}
- begin
- n2ymd ( n2pw( ymd2n(y,m,d) , w ) , y, m, d )
- end;
-
- Procedure MondaySince(var y,m,d:integer);
- {returns 1st monday since ymd}
- begin
- ymd2w(1,y,m,d)
- end;
-
- Procedure LatestFriday(var y,m,d:integer);
- {returns latest friday before (and including) ymd}
- begin
- ymd2pw(5,y,m,d)
- end;
-
- Function n2s(n:integer):anystring;
- var y,m,d:integer;
- begin
- n2ymd(n,y,m,d);
- n2s:=ymd2s(y,m,d)
- end;
-
- Function nn2w(n1,n2:integer):integer;
- {returns the number of business days (signed) in the inclusive range}
- var i,j,k:integer;
- begin
- if n1>n2 then nn2w:=-nn2w(n2,n1) else
- begin
- i:=n2dow(n1);
- if i>5 then {sat or sun}
- begin
- n1:=n1+8-i;
- i:=1 {make it a monday}
- end;
- j:=n2dow(n2);
- if j>5 then {sat or sun}
- begin
- n2:=n2+5-j; {make it friday}
- j:=5
- end;
- if n2<n1 then nn2w:=0 else
- begin
- k:=5 * ( (n2-n1) div 7 ) + j - i + 1;
- if i>j then nn2w:=k+5 else nn2w:=k
- end
- end
- end;
-
- Function wdif(y1,m1,d1,y2,m2,d2:integer):integer;
- {same as nn2w, but for ymd type dates}
- begin
- wdif:=nn2w( ymd2n(y1,m1,d1) , ymd2n(y2,m2,d2) )
- end;
-
- begin
- write('2 dates < y1 m1 d1 y2 m2 d2>...');readln(y,m,d,y2,m2,d2);
- if not ymdok(y,m,d) then writeln('1st date invalid ',y,' ',m,' ',d) else
- if not ymdok(y2,m2,d2) then writeln('2nd date invalid ',y2,' ',m2,' ',d2)
- else
- begin
- writeln('first date is ',ymd2s(y,m,d));
- writeln(' and has ',dim(y,m),' days in the given month');
- writeln('second date is ',ymd2s(y2,m2,d2));
- writeln(' and has ',dim(y2,m2),' days in the given month');
- writeln('There is a difference of ',dif(y,m,d,y2,m2,d2), ' day(s)');
- writeln('There are ',wdif(y,m,d,y2,m2,d2),' weekday(s) in the range');
- MondaySince(y,m,d);
- writeln('most recent monday since 1st is ',ymd2s(y,m,d));
- LatestFriday(y2,m2,d2);
- writeln('latest friday including 2nd is ',ymd2s(y2,m2,d2));
- end;
- end.
-