A = | INT(2.6*M - 0.01) + D + Y + INT(Y/4) + INT(C/4) | |
-2*C | ||
X = | A MOD 7 |
0 : Sunday
1 : Monday
2 : Tuesday
3 : Wednesday
4 : Thursday
5 : Friday
6 : Saturday
The numbers D, M, Y and C are defined as:
D : the day of the month.
M : the number of the month - but not the standard number. January and February are numbers 11 and 12 of the preceding year (affecting Y and possibly C described below). March is number 1, April is 2, May is 3, . . ., and December is number 10.
Y : the year in the century.
C : the number of hundreds in the year, in other words, the first two digits in the year number.
For instance, if the date is 26th August 1983 then the standard way of expressing this is 26/08/1983. For Zeller's formula we use D = 26, M = 6, Y = 83 and C = 19.
Substituting these values into Zeller's formula gives:
A = INT(2.6*6 - 0.1) + 26 + 83 + INT(83/4) + INT(19/4)
- 2*19
= INT(15.6 - 0.1) + 26 + 83 + INT(20.75) + INT(4.75) - 38
= 15 + 26 + 83 + 20 + 4 - 38
= 110
and
X = 110 MOD 7
= 110 - 7*INT(110/7)
= 110 - 7*15
= 5
Thus we conclude that the day of the week of 26th August 1983 was Friday.
Here are some examples showing the standard date format and the value that Zeller's formula uses.
STANDARD NOTATION | ZELLER'S FORMULA NOTATION | |||
D | M | C | Y | |
03/03/1947 | 3 | 1 | 19 | 47 |
01/01/2000 | 1 | 11 | 19 | 99 |
26/02/1983 | 26 | 12 | 19 | 82 |
29/11/1984 | 29 | 9 | 19 | 84 |
Listing 7.1
LIST
10 REM Day of week 20 MODE 1:COLOUR 3:PRINT ' TAB(14);"D ay of week"':@%=10 30 PRINT "This program calculates the day of the week for any date specified ."; 40 DIM A%(12),A$(12):FOR I=1 TO 12:RE AD A%(I),A$(I):NEXT 50 DIM B$(6):FOR I=0 TO 6:READ B$(I): NEXT 60 VDU 19,1,5,0,0,0 70 REPEAT 80 COLOUR 1:PRINT ''"Type in the dat e:" 90 REPEAT 100 A%(2)=29:TEST=-1 110 INPUT '" Enter day, 1 to 31: "; D 120 IF D<1 OR D>31 OR D<>INT(D) THEN COLOUR 3:PRINT '"An integer between 1 a nd 31 please.":COLOUR 1:TEST=0 130 IF TEST THEN PROCMonth 140 IF TEST:IF D>A%(M) THEN COLOUR 3 :PRINT '"Not enough days in ";A$(M);".": COLOUR 1:TEST=0 150 IF TEST THEN PROCYear 160 IF TEST:IF M=2 AND D>A%(2) THEN COLOUR 3:PRINT '"There are 28 days in Fe bruary.":COLOUR 1:TEST=0 170 UNTIL TEST 180 COLOUR 2:PRINT '; D;" ";A$(M);" " ;Y;" is/was a "; 190 REM Change format of input detail s 200 M=M-2:IF M<1 THEN M=M+12:Y=Y-1 210 C=INT(Y/100):Y=Y-C*100 220 REM Zeller's congruence 230 DAY=INT(2.6*M-0.1)+D+Y+INT(C/4)+I NT(Y/4)-2*C 240 DAY=DAY MOD 7 250 PRINT ;B$(DAY);"day." 260 COLOUR 3:PRINT CHR$(7) ' TAB(10); "Another go? Y or N "; 270 REPEAT:G$=GET$:UNTIL G$="Y" OR G$ ="N" 280 UNTIL G$="N" 290 CLS:PRINT '"Bye for now.":END 300 DEF PROCMonth 310 REPEAT 320 INPUT '"Enter month, 1 to 12: ";M 330 IF M<1 OR M>12 OR M<>INT(M) THEN COLOUR 3:PRINT '"An integer between 1 an d 12!":COLOUR 1 340 UNTIL M>0 AND M<13 AND M=INT(M) 350 ENDPROC 400 DEF PROCYear 410 REPEAT 420 INPUT '" Enter year, in full: ";Y 430 IF Y<1582 OR Y>4902 THEN COLOUR 3 :PRINT '"Year is not in range.":COLOUR 1 440 IF Y<>INT(Y) THEN COLOUR 3:PRINT '"Not a year - try again.":COLOUR 1 450 UNTIL Y=INT(Y) AND Y>1582 AND Y<49 03 460 REM Check for leap year 470 L=0:IF INT(Y/4)*4=Y THEN L=-1 480 IF L AND INT(Y/100)*100=Y THEN L=0 :IF INT(Y/400)*400=Y THEN L=-1 490 A%(2)=28-L:IF L THEN PRINT '"The y ear is/was a leap year." 500 ENDPROC 600 REM Data 610 DATA 31,January,29,February,31,Mar ch,30,April 620 DATA 31,May,30,June,31,July,31,Aug ust 630 DATA 30,September,31,October,30,No vember,31,December 640 DATA Sun,Mon,Tues,Wednes,Thurs,Fri ,Satur
RUN
Day of week This program calculates the day of the week for any date specified. Type in the date: Enter day, 1 to 31: ?25 Enter month, 1 to 12: ?12 Enter year, in full: ?1983 25 December 1983 is/was a Sunday. Another go? Y or N
Note: You may have come across Zeller's formula before and possibly noticed that the formula used here is slightly different. Often the first term INT(2.6*M - 0.1) is written as INT(2.6*M - 0.2) instead. This latter form is not used here because of the way the BBC and Electron calculate the INTegral part of numbers. Try M = 7, then
INT(2.6*7 - 0.2) = INT(18.2 - 0.2)
= INT(18)
= 18
However, you'll find that your computer returns the value of INT(2.6*7 - 0.2) as 17, even though if you ask it to print 2.6*7 - 0.2 it prints 18 correctly.
Listing 7.2
LIST
10 REM Calendar 20 MODE 1:COLOUR 3:PRINT ' TAB(16);"C alendar"':@%=10 30 PRINT "This program prints a calen dar for any month of any year specified ."; 40 DIM A%(12),A$(12):FOR I=1 TO 12:RE AD A%(I),A$(I):NEXT 50 REPEAT 60 VDU 19,1,5,0,0,0 70 COLOUR 1:PRINT ''"Type in the mon th and year:" 80 PROCMonth 90 PROCYear 100 A$=A$(M)+" "+STR$(Y):MM=A%(M) 110 REM Change format of input detail s 120 M=M-2:IF M<1 THEN M=M+12:Y=Y-1 130 C=INT(Y/100):Y=Y-C*100 140 REM Zeller's congruence 150 DAY=INT(2.6*M-0.1)+1+Y+INT(C/4)+I NT(Y/4)-2*C 160 DAY=DAY MOD 7 170 REM Print Calendar 180 CLS:VDU 19,1,6,0,0,0:PRINT '' TAB (20-LEN(A$)/2);A$ 190 COLOUR 1:PRINT '" Sun Mon Tue Wed Thu Fri Sat"':COLOUR 2 200 FOR I=1 TO MM 210 DAY=DAY+1 220 PRINT TAB(DAY*5-1+(I>9));I; 230 IF DAY>6 THEN DAY=0:PRINT '' 240 NEXT 250 COLOUR 3:PRINT CHR$(7) ''' TAB(10 );"Another go? Y or N "; 260 REPEAT:G$=GET$:UNTIL G$="Y" OR G$ ="N" 270 UNTIL G$="N" 280 CLS:PRINT '"Bye for now.":END 300 DEF PROCMonth 310 REPEAT 320 INPUT '"Enter month, 1 to 12: "; M 330 IF M<1 OR M>12 OR M<>INT(M) THEN COLOUR 3:PRINT '"An integer between 1 an d 12!":COLOUR 1 340 UNTIL M>0 AND M<13 AND M=INT(M) 350 ENDPROC 400 DEF PROCYear 410 REPEAT 420 INPUT '" Enter year, in full: ";Y 430 IF Y<1752 OR Y>4902 THEN COLOUR 3 :PRINT '"Year is not in range.":COLOUR 1 440 IF Y<>INT(Y) THEN COLOUR 3:PRINT '"Not a year - try again.":COLOUR 1 450 UNTIL Y=INT(Y) AND Y>1581 AND Y<49 03 460 REM Check for leap year 470 L=0:IF INT(Y/4)*4=Y THEN L=-1 480 IF L AND INT(Y/100)*100=Y THEN L=0 :IF INT(Y/400)*400=Y THEN L=-1 490 A%(2)=28-L:IF L THEN PRINT '"The y ear is/was a leap year." 500 ENDPROC 600 REM Data 610 DATA 31,January,29,February,31,Mar ch,30,April 620 DATA 31,May,30,June,31,July,31,Aug ust 630 DATA 30,September,31,October,30,No vember,31,December
RUN
Calendar This program prints a calendar for any month of any year specified. Type in the month and year: Enter month, 1 to 12: ?2 Enter year, in full: ?1984 The year is/was a leap year. February 1984 Sun Mon Tue Wed Thu Fri Sat 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 Another go? Y or N
X = INT(30.57*M) + INT(395.25) + D
IF M > 2 and Y is a leap year then subtract 1 from X.
If M > 2 and Y is not a leap year then subtract 2 from X.
For example, let's calculate the pseudo-Julian date of 26th August 1983. The values of D, M and Y are given by D = 26, M = 8, Y = 1983. Substituting these values into the formula gives the following:
X = INT(30.57*8) + INT(365.25*1983 - 395.25) + 26
= INT(244.56) + INT(723895.5) + 26
= 244 + 723895 + 26
= 724165
However, since the month number M is greater than 2 and 1983 is not a leap year we subtract 2 from X to give a pseudo-Julian date of 724163.
To calculate the date from the pseudo-Julian date proceed as follows, where X is the pseudo-Julian date.
The first approximation to the year is given by:
Y = INT(X/365.26) + 1
The day within the year is given by:
D = X - INT(365.25*Y - 395.25)
A leap year adjustment is made:
D1 = 2, if it is a leap year then D1 = 1
If D>91 - D1 then add D1 to D
Calculate the month and day:
M = INT(D/30.57)
D = D - INT(30.57*M)
Adjust month and year if necessary:
If M > 12 then set M to 1 and add 1 to Y.
For example, let's calculate the date corresponding to a pseudo-Julian
Y = INT(724164/365.26) + 1
= INT(1982.5987) + 1
= 1983
D = 724164 - INT(365.25*1983 - 395.25)
= 724164 - INT(724290.75 - 395.25)
= 724164 - INT(723895.5)
= 269
The year 1983 is not a leap year so that D1 is 2. The value of D is greater than 91 - D1 and so we add D1 to D. Thus the value of D is now given by
D = 271
M = INT(271/30.57)
= INT(8.86490023)
= 8
D = 271 - INT(30.57*8)
= 271 - INT(244.56)
= 271 - 244
= 27
The value of M is not greater than 12 and so we are finished, with values of D = 27, M = 8 and Y = 1983. Thus the date corresponding to the pseudo-Julian date of 724164 is 27th August 1983.
The next program performs all the above sorts of calculations quickly and provides a listing of dates that are a specified number of days apart. For convenience the program only works for dates in the 20th century. You should be able to make any changes necessary for another century quite easily.
Warning. Dates are entered in the form DD/MM/YY, for example 12th March 1984 would be entered as 12/03/84 or 12/ 3/84 but not as 12/3/84. Not too many checks have been made for the date entered, and you could, for instance, enter 30/02/83. The program would think of this date as 2nd March 1983 (can you see why?).
Listing 7.3
LIST
10 REM Date management 20 MODE 1:COLOUR 3:PRINT ' TAB(12);"D ate management"':@%=10 30 PRINT "This program provides the l isting of dates that are a specified number of days apart."' 40 REM Enter start date, not many che cks are made! 50 COLOUR 1:PRINT '"Type in date as D D/MM/YY, eg 15/02/84" 60 REPEAT 70 INPUT '"Enter start date: ";S$ 80 TEST=-1 90 IF LEN(S$)<>8 THEN COLOUR 3:PRINT '"In the form DD/MM/YY please.":COLOUR 1:TEST=0 100 IF TEST:IF MID$(S$,3,1)+MID$(S$,6 ,1)<>"//" THEN COLOUR 3:PRINT '"Use / / please.":COLOUR 1:TEST=0 110 IF TEST:D=VAL(MID$(S$,1,2)):M=VAL (MID$(S$,4,2)):Y=VAL(MID$(S$,7,2))+1900 120 IF TEST:IF D<1 OR D>31 OR M<0 OR M>12 THEN COLOUR 3:PRINT '"Day, Month er ror.":COLOUR 1:TEST=0 130 UNTIL TEST 140 REM Date form is in a reasonably c orrect form 150 REM Calculate the pseudo-Julian da y 160 X=INT(30.57*M)+INT(365.25*Y-395.25 )+D 170 REM Adjust for leap year 180 IF M>2 THEN X=X-2:IF INT(Y/4)*4=Y THEN X=X+1 190 REM Enter interval of days 200 PRINT '"Enter interval in days bet ween dates." 210 REPEAT 220 INPUT '"Interval: ";P 230 IF P<1 OR INT(P)<>P THEN COLOUR 3 :PRINT '"A positive integer please.":COL OUR 1 240 UNTIL P>0 AND INT(P)=P 250 PRINT '"Enter the number of times interval is required." 260 REPEAT 270 INPUT '"Number: ";N 280 IF INT(N)<>N THEN COLOUR 3:PRINT '"A whole number please.":COLOUR 1 290 IF N<1 OR N>100 THEN COLOUR 3:PRI NT '"Be reasonable.":COLOUR 1 300 UNTIL N>0 AND N<101 AND N=INT(N) 310 COLOUR 2:PRINT '' 320 FOR I=1 TO N 330 Y=INT(X/365.26)+1 : REM Year 340 D=X-INT(365.25*Y-395.25) 350 REM Leap year adjustment 360 D1=2:IF INT(Y/4)*4=Y THEN D1=1 370 IF D>91-D1 THEN D=D+D1 380 M=INT(D/30.57) : REM Month 390 D=D-INT(30.57*M) : REM Day 400 IF M>12 THEN M=1:Y=Y+1 : REM Year adjustment 410 Y=Y-1900 420 REM Output to display 430 PROCForm(D):D$=Z$+"/" 440 PROCForm(M):D$=D$+Z$+"/" 450 PROCForm(Y):D$=D$+Z$+" " 460 PRINT D$; 470 X=X+P : REM Interval added 480 NEXT 490 COLOUR 3:PRINT CHR$(7) ''' TAB(10) ;"Another go? Y or N "; 500 REPEAT:G$=GET$:UNTIL G$="Y" OR G$= "N" 510 IF G$="Y" THEN RUN 520 CLS:PRINT '"Bye for now.":END 530 DEF PROCForm(Z) 540 Z$=STR$(Z):IF LEN(Z$)<2 THEN Z$="0 "+Z$ 550 ENDPROC
RUN
Date management This program provides the listing of dates that are a specified number of days apart. Type in date as DD/MM/YY, eg 15/02/84 Enter start date: ?01/01/84 Enter interval in days between dates. Interval: ?7 Enter the number of times interval is required. Number: ?32 01/01/84 08/01/84 15/01/84 22/01/84 29/01/84 05/02/84 12/02/84 19/02/84 26/02/84 04/03/84 11/03/84 18/03/84 25/03/84 01/04/84 08/04/84 15/04/84 22/04/84 29/04/84 06/05/84 13/05/84 20/05/84 27/05/84 03/06/84 10/06/84 17/06/84 24/06/84 01/07/84 08/07/84 15/07/84 22/07/84 29/07/84 05/08/84 Another go? Y or N