Calendar (ZX Computing)

Developer(s): George Chambers
Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Calendar

Shows a calendar for a whole year, one month per screen starting with January, or for a single chosen month, for any year from 1649 to 9999. It also finds the day of the week for any date, and the date of Easter Sunday for any year, with Julian-calendar corrections for years before 1753. Choose from the menu with C (year), M (month), D (day of week) or E (Easter); press I on the title screen to get an information page first.

The REMs say the program was taken from the Aug/Sept and Nov/Dec issues of ZX Computing and the Aug and Oct 1982 issues of Computing Today, then “improved and adapted for the Timex 2068 by G.F. Chambers”. Chambers’ notes for the calendar disk add that most of its calendar programs came from the TTSUC 2068 tape library. The zip includes those notes, which list every calendar program on the disk.

Program Analysis

Program Structure

Lines 100–460 show the title, wait briefly for the I key and then display the menu. The year and month options share the routine at lines 640–1060, which pulls each month’s name and length out of the packed string M$="JANUARY:31FEBRUARY:28..." by scanning for the colons. The day-of-week option is at lines 1190–1540, Easter at 2030–2570, and the information page at 4000.

Calendar Calculation

The subroutine at line 1550 finds the weekday of 1 January from W=S-2001 using the full Gregorian leap-year rule (W+INT (W/4)-INT (W/100)+INT (W/400)). After each month, lines 1030–1050 move the starting day on by the month’s length mod 7. February gets 29 days by the same full rule at line 740. In single-month mode the variable R holds the chosen month, and the earlier months are worked through without being displayed. The day-of-week option adds a fixed offset for each month (lines 1630–1750) and looks the result up in a packed string of nine-character day names.

Easter Calculation

The Easter routine finds the golden number by repeated subtraction of 19, then works out the century corrections X and Z and the epact E. It applies the usual adjustments for epacts 24 and 25 and returns a date in March or April. For years before 1753, lines 2240 and 2400 add Julian-calendar offsets, which is why the information page says the Easter dates hold from 800 A.D.

Notable Techniques

  • Month names and lengths packed into one string separated by colons and read with a character scan.
  • POKE 23658,8 turns on caps lock so the single-letter menu keys match.
  • Lines 910–920 send 1 January, 1 July and 25–26 December through a separate print path, a hook for marking holidays, though the output is the same as for other dates.
  • PAUSE 4E4 as a long wait for the next-month key.
  • Out-of-range input leads to light-hearted messages (“AW,COME ON: YOURE PULLING MY LEG”) and, on leaving, “HERE’S TO TIME FOR ALL THINGS”.

Potential Issues

  • In the day-of-week option, line 1310 rejects every 29 February before the leap-year test at line 1370 is reached. Its month offset (line 1700) also uses only S/4, not the century rule.
  • A year above 9999 in the day-of-week option jumps to the year-calendar input at line 550.
  • The weekday variable Q is also used as the flag for the information page. Returning to the menu through line 350 when Q happens to be 1 shows the information page again.
  • Chambers’ disk notes say the program calculates the number of days between two dates. The listing has no such option.

It comes from a Larken disk in the TS User Group’s collection (disk l-23). For this release it was converted to load and run from tape on a stock TS2068: the LKDOS PRINT USR 100 prefix on the SAVE line was removed. It was tested in ZEsarUX.

Related Content

Image Gallery

Source Code

   15 REM          CALENDAR
   20 REM          ''''''''''''''''
   25 REM         A  PROGRAM
   30 REM       TAKEN FROM THE
   35 REM    AUG/SEPT AND NOV/DEC
   40 REM       "ZX COMPUTING"
   42 REM          MAGAZINE
   45 REM 
   46 REM          AND FROM
   48 REM      "COMPUTING TODAY"               AUG AND OCT 1982.
   50 REM 
   55 REM        ============
   60 REM 
   62 REM 
   65 REM   IMPROVED AND ADAPTED
   70 REM    FOR THE TIMEX 2068
   72 REM 
   75 REM     BY G.F. CHAMBERS
   80 REM 
   85 REM 
  100 CLS 
  110 LET Q=0
  200 PRINT AT 9,12;"CALENDAR": PRINT AT 11,8;"BY G.F. CHAMBERS"
  210 PRINT AT 17,1;"PRESS ""I"" KEY FOR INFORMATION"
  325 POKE 23658,8
  330 FOR N=1 TO 500
  334 IF INKEY$="I" THEN LET Q=1: LET N=500
  340 NEXT N
  360 IF Q=1 THEN GO SUB 4000
  370 CLS 
  375 PRINT TAB 10;"CALENDAR"
  380 PRINT TAB 10;"''''''''''''''''"
  390 PRINT ,,"FOR A YEARS CALENDAR PRESS ""C"",",,,"FOR JUST ONE MONTH PRESS ""M"",",,,"TO FIND DAY OF WEEK PRESS ""D"",",,,"TO FIND AN EASTER DATE PRESS ""E"""
  394 LET Q=0
  395 PRINT : IF Q=1 THEN PRINT ,,"   PRESS ""C"",""M"",""D"",OR ""E"" KEYS"
  400 LET S=1982
  420 IF INKEY$="" THEN GO TO 420
  430 IF INKEY$="C" THEN GO TO 500
  440 IF INKEY$="M" THEN GO TO 1760
  450 IF INKEY$="D" THEN GO TO 1190
  455 IF INKEY$="E" THEN GO TO 2000
  460 IF INKEY$<>"y" OR INKEY$<>"m" OR INKEY$<>"d" OR INKEY$<>"e" THEN GO TO 420
  500 CLS : IF INKEY$<>"" THEN GO TO 500
  510 PRINT ,,"YEAR OF CALENDAR?"
  520 PRINT "''''''''''''''''''''''''''''''''''"
  530 PRINT ,,"ENTER AS A 4-DIGIT NUMBER--";
  540 LET R=0
  550 INPUT S
  560 IF S<1649 THEN GO TO 1960
  570 IF S>9999 THEN GO TO 550
  575 IF INT S<>S THEN GO TO 550
  580 PRINT S
  600 GO SUB 1550
  610 FOR N=1 TO 20
  620 NEXT N
  630 
  640 LET M$="JANUARY:31FEBRUARY:28MARCH:31APRIL:30MAY:31JUNE:30JULY:31AUGUST:31SEPTEMBER:30OCTOBER:31NOVEMBER:30DECEMBER:31"
  650 LET J=0
  660 FOR P=1 TO 12
  670 LET N$=""
  680 LET J=J+1
  690 IF M$(J)=":" THEN GO TO 720
  700 LET N$=N$+M$(J)
  710 GO TO 680
  720 LET O=VAL (M$(J+1 TO J+2))
  730 LET J=J+2
  740 IF P=2 AND S/4=INT (S/4) AND (NOT S/100=INT (S/100) OR S/400=INT (S/400)) THEN LET O=29
  750 LET W$="M"
  760 IF W$="M" AND P<R THEN GO TO 1030
  770 CLS 
  780 PRINT "             ";S
  790 GO SUB 1600
  800 PRINT AT 2,16-(INT (LEN N$/2))-1;N$
  810 GO SUB 1600
  820 PRINT "   S   M   T   W   T   F   S"
  830 PRINT 
  840 LET D=0
  850 LET B=8-(Q-1)
  860 IF B=7 THEN LET B=0
  870 IF B=8 THEN LET B=1
  880 PRINT TAB (4*B+1);
  890 PRINT "  ";
  900 LET D=D+1
  910 IF (P=7 OR P=1) AND D=1 THEN GO TO 1110
  920 IF P=12 AND (D=25 OR D=26) THEN GO TO 1090
  930 PRINT D;
  940 LET C=D-(Q-1)+1
  950 IF C/7=INT (C/7) THEN GO SUB 1600
  960 IF D<9 THEN PRINT " ";
  970 IF D<O THEN GO TO 890
  980 IF P<>12 THEN PRINT AT 19,7;"PRESS ANY KEY FOR              THE FOLLOWING MONTH"
  990 PRINT AT 21,0;"**PRESS ""Q"" TO RETURN TO MENU**"
  995 PLOT 10,30: DRAW 225,0: DRAW 0,110: DRAW -225,0: DRAW 0,-110
 1000 PAUSE 4E4
 1010 IF INKEY$="Q" THEN GO TO 350
 1020 IF P=12 THEN GO TO 350
 1030 LET W=(35+Q-O)/7
 1040 LET Q=INT (W*7-(INT W)*7+.1)
 1050 IF Q=0 THEN LET Q=7
 1060 NEXT P
 1070 
 1080 GO TO 1930
 1090 IF D=25 THEN PRINT "25";
 1100 IF D=26 THEN PRINT "26";
 1110 IF D=1 THEN PRINT "1";
 1120 GO TO 940
 1130 CLS 
 1140 PRINT AT 10,0;"AW,COME ON: YOURE PULLING MY LEG"
 1150 PRINT "''''''''''''''''''''''"
 1160 FOR N=1 TO 50
 1170 NEXT N
 1180 GO TO 350
 1190 CLS : IF INKEY$<>"" THEN GO TO 1190
 1195 PRINT AT 1,12;"DATE"
 1200 PRINT AT 2,12;"''''''''"
 1210 PRINT ,,"ENTER THE DAY OF THE MONTH----";
 1220 INPUT U
 1225 IF U>31 THEN GO TO 1130
 1230 IF INT U<>U THEN GO TO 1220
 1240 PRINT U
 1250 PRINT ,,"NOW ENTER THE MONTH?(NUMBER)--";
 1260 INPUT P
 1270 IF INT P<>P THEN GO TO 1260
 1280 PRINT P
 1290 IF P<1 OR P>12 OR U<1 OR U>31 OR P<>INT P THEN GO TO 1130
 1300 IF U=31 AND (P=4 OR P=6 OR P=9 OR P=11) THEN GO TO 1130
 1310 IF U>=29 AND P=2 THEN GO TO 1130
 1320 PRINT ,,"ENTER THE YEAR AS 4 DIGITS--";
 1330 INPUT S
 1340 IF S<1649 THEN GO TO 1960
 1350 IF S>9999 THEN GO TO 550
 1360 PRINT S
 1370 IF U=29 AND P=2 AND NOT (S/4=INT (S/4) AND (NOT S/100=INT (S/100) OR S/400=INT (S/400))) THEN GO TO 1130
 1380 GO SUB 1550
 1390 GO SUB 1630
 1400 LET T=U+8-Q
 1410 LET Y=INT (T-7*INT (T/7)+.1)
 1420 LET M$="SUNDAY   MONDAY   TUESDAY  WEDNESDAYTHURSDAY FRIDAY   SATURDAY "
 1430 LET A=9*Y+1
 1440 LET Z$=M$(A TO A+8)
 1450 GO SUB 1600
 1460 PRINT "    ";U;"-";P;"-";S;" WAS A ";Z$
 1470 GO SUB 1600
 1480 PRINT "ANY MORE? PRESS ""Y"" OR ""N"" KEYS"
 1490 PRINT AT 21,2;"PRESS ""Q"" TO RETURN TO MENU"
 1500 IF INKEY$="" THEN GO TO 1500
 1510 IF INKEY$="Y" THEN GO TO 1190
 1520 IF INKEY$="Q" THEN GO TO 100
 1530 IF INKEY$<>"N" THEN GO TO 8000
 1540 GO TO 8000
 1550 LET W=S-2001
 1560 LET X=8-(W+INT (W/4)-INT (W/100)+INT (W/400))
 1570 LET Q=INT (X-7*INT (X/7)+.1)
 1580 IF Q=0 THEN LET Q=7
 1590 RETURN 
 1600 PRINT : PRINT 
 1620 RETURN 
 1630 IF P<3 THEN GO TO 1710
 1640 IF P=3 OR P=11 THEN LET Q=Q+4
 1650 IF P=4 OR P=7 THEN LET Q=Q+1
 1660 IF P=5 THEN LET Q=Q+6
 1670 IF P=6 THEN LET Q=Q+3
 1680 IF P=8 THEN LET Q=Q+5
 1690 IF P=9 OR P=12 THEN LET Q=Q+2
 1700 IF S/4=INT (S/4) THEN GO TO 1740
 1710 IF P=2 THEN LET Q=Q+4
 1720 IF Q>7 THEN LET Q=Q-7
 1730 RETURN 
 1740 LET Q=Q-1
 1750 GO TO 1720
 1760 CLS : IF INKEY$<>"" THEN GO TO 1760
 1770 PRINT AT 4,0;"MONTH TO BE PRINTED(NUMBER)?"
 1780 PRINT "''''''''''''''''''''''''''''''''''''''''''''''''''''''''"
 1790 INPUT P
 1800 IF P<1 OR P>12 OR P<>INT P THEN GO TO 1770
 1810 PRINT AT 4,30;P
 1820 PRINT AT 6,5;"FOR WHICH YEAR?  ";
 1830 INPUT S
 1840 IF S<1649 THEN GO TO 1960
 1850 IF S>9999 THEN GO TO 1830
 1860 PRINT S
 1880 FOR N=1 TO 20
 1890 NEXT N
 1900 GO SUB 1550
 1910 LET R=P
 1920 GO TO 630
 1960 CLS 
 1970 PRINT AT 9,0;" THE PROGRAM IS ASSURED ACCURATEONLY FOR YEARS AFTER 1648,S0RRY."
 1980 PRINT ,," PRESS ANY KEY TO RETURN TO MENU"
 1990 IF INKEY$="" THEN GO TO 1990
 1995 GO TO 350
 2030 CLS 
 2040 PRINT AT 5,8;" EASTER DATE "
 2050 PRINT 
 2060 PRINT 
 2070 PRINT "YEAR FOR WHICH EASTER IS WANTED"
 2080 PRINT 
 2090 PRINT "PLEASE ENTER THE YEAR AND PRESS THE  ENTER (I.E. NEWLINE) KEY."
 2100 INPUT Y
 2110 PRINT 
 2120 PRINT 
 2130 PRINT "WAIT, COMPUTER IS WORKING ON IT."
 2140 LET G=Y
 2150 IF G<19 THEN GO TO 2180
 2160 LET G=G-19
 2170 GO TO 2150
 2180 LET G=G+1
 2190 LET C=INT (Y/100)+1
 2200 LET X=INT (3*C/4)-12
 2210 LET Z=INT ((8*C+5)/25)-5
 2220 LET D=INT (5*Y/4)-X-10
 2230 LET E=11*G+20+Z-X
 2240 IF Y<1753 THEN LET E=E+9
 2250 IF E<0 THEN LET E=E+30
 2260 IF E<30 THEN GO TO 2290
 2270 LET E=E-30
 2280 GO TO 2260
 2290 IF E=24 THEN GO TO 2310
 2300 IF (E=25) AND (G>11) THEN GO TO 2320
 2310 GO TO 2330
 2320 LET E=E+1
 2330 LET N=44-E
 2340 IF (N<21) THEN LET N=N+30
 2350 LET B=D+N
 2360 IF B<7 THEN GO TO 2390
 2370 LET B=B-7
 2380 GO TO 2360
 2390 LET N=N+7-B
 2400 IF Y<1753 THEN LET N=N+4
 2410 IF N>31 THEN GO TO 2460
 2420 CLS 
 2430 PRINT AT 6,10;"IN ";Y
 2440 PRINT AT 10,3;"EASTER SUNDAY IS  MARCH ";N
 2450 GO TO 2500
 2460 CLS 
 2470 PRINT AT 6,10;"IN ";Y
 2480 PRINT AT 10,3;"EASTER SUNDAY IS APRIL ";N-31
 2490 REM GO TO 2000
 2500 PAUSE 200
 2505 REM CLS 
 2510 PRINT AT 17,0;"DO YOU WANT ANOTHER EASTER DATE?"
 2520 PRINT ,,"      PRESS  ""Y""  OR  ""N"" "
 2530 LET I$=INKEY$
 2540 IF I$<>"Y" AND I$<>"N" THEN GO TO 2530
 2550 IF I$="N" THEN GO TO 100
 2560 CLS 
 2570 GO TO 2000
 4000 CLS 
 4003 PRINT ,,"THIS PROGRAM WILL DISPLAY:",,,"(A) THE MONTHS OF ANY CHOSEN        YEAR STARTING WITH JANUARY",,,"(B) A SELECTED MONTH OF ANY YEAR",,"(C) THE DAY OF THE WEEK THAT ANY    SELECTED DATE FALLS ON"
 4005 PRINT ,,"(D) THE DATE OF EASTER SUNDAY       FOR ANY SELECTED YEAR."
 4010 PRINT ,,"  THIS CALENDAR IS ACCURATE FROMTHE YEAR 1649, WHEN THE GREGOR- IAN CALENDAR CAME INTO  GENERAL USE IN ENGLAND. ";
 4020 PRINT "THE EASTER DATES ARE VALID FROM 800 A.D."
 4030 FLASH 1: PRINT AT 21,3;"**PRESS ANY KEY FOR MENU**"
 4040 IF INKEY$="" THEN GO TO 4040
 4055 FLASH 0: CLS 
 4056 IF INKEY$<>"" THEN GO TO 4056
 4060 RETURN 
 8000 CLS : PRINT AT 12,1;"HERE'S TO TIME FOR ALL THINGS": GO TO 9999
 9000 PRINT USR 100: SAVE "calend.B1" LINE 100
 9999 STOP

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.