This program prints a calendar for any user-specified month and year, calculating the correct starting day of the week using Zeller’s congruence-style formula. It handles leap years with a three-condition check: divisible by 4 but not 100 (line 270), or divisible by 400 (line 280). Month names are stored in a 12-by-9 character array, and the 42-element numeric array A() maps days across a six-week grid of seven columns. The display uses TAB-based column positioning at four-character intervals to align the SUN through SAT header with the day numbers below it.
Program Structure
The program is organized into four logical phases:
- Input (lines 5–40): Clear screen, set border, prompt for month and year.
- Setup (lines 60–210): Initialize variables and populate the month-name string array.
- Calculation (lines 220–380): Determine the number of days in the month, compute the starting day of the week, and fill the day-number grid array.
- Display & Loop (lines 390–590): Render the calendar, then offer a repeat prompt.
Month and Day Storage
Line 90 declares A$(12,9), a two-dimensional string array with 12 rows of 9 characters — exactly enough to hold the longest month name, “SEPTEMBER”. Each month name is padded with trailing spaces so all entries are exactly 9 characters wide, making indexed access uniform. A separate numeric array A(42) (line 220) represents a six-week by seven-day grid; only positions from START to the last day are filled, leaving earlier slots at their default value of 0.
Day-of-Week Calculation
The core algorithm at lines 310–360 uses a variant of Zeller’s congruence. Lines 310–320 adjust January and February to be treated as months 13 and 14 of the previous year, a standard preprocessing step. Line 330 computes the raw remainder R using the formula:
R = D + 2*M + 2 + INT((3*M+3)/5) + INT(Y/4) + Y - INT(Y/100) + INT(Y/400)
Line 340 extracts the fractional part of R/7 and multiplies by 7 to get a value in [0,7), and line 350 rounds it to the nearest integer with INT(NUM+.5). Line 370 maps a result of 0 to 7, making Sunday position 1 through Saturday position 7 consistent with the SUN–SAT header printed at line 460.
Leap Year Logic
Three lines handle leap year detection:
- Line 270: divisible by 4 but not by 100 → leap year
- Line 280: divisible by 400 → leap year (overrides the century exclusion)
- Line 300: if February and leap year, set
END=29
Note that line 270 uses the original Y value, but by the time it executes, Y may be modified by line 320 for January/February inputs. However, lines 260–300 execute before lines 310–320, so the leap-year check correctly uses the original year.
Calendar Rendering
Lines 470–560 iterate over six rows (R=0 to 5) and seven columns (C), using TAB(4*CC) to position each value at 4-character intervals aligned with the header ” SUN MON TUE WED THU FRI SAT”. Cells where A(C)=0 (before the first day) or A(C)>END (after the last day) print a blank space instead of a number. The GO TO 550 statements at lines 510 and 530 skip the day-printing step, acting as an early-continue since BASIC lacks a structured CONTINUE statement.
Variable Naming and Reuse
The program uses descriptive multi-character variable names: MON, YEAR, LEAP, START, END, NUM, DAY. Notably, R is reused as both the Zeller formula accumulator (line 330) and the outer loop variable for row iteration (line 470). This is safe because R‘s computed value is consumed before the display loop begins, but it reduces readability.
Notable Anomalies
- Line 250 sets
END=28unconditionally for February before the leap year check at line 300 can correct it to 29 — this ordering is intentional and correct. - The
BORDER 1call at line 6 sets the screen border color, relevant to color-capable configurations. - The
NEXT Rat line 560 reuses the loop variableRthat was previously used for the day formula, which could cause confusion during manual tracing but causes no runtime error. - The display loop runs all six rows unconditionally, even if the month fits in five rows — the sixth row simply prints blanks for any cells where
A(C)>END. - The REM at line 1 spells “CALENDER” rather than “CALENDAR”, though the program title uses the correct spelling.
Content
Source Code
1 REM CALENDER
2 REM THIS PROGRAM WILL PRINT ANY MONTH IN ANY YEAR.
3 REM TRY TO FIND OUT WHAT DAY OF THE WEEK A FAMOUS HISTORICAL EVENT OCCURED
5 CLS
6 BORDER 1
10 PRINT "ENTER MONTH (1 TO 12)"
20 INPUT M
30 PRINT "ENTER YEAR"
40 INPUT Y
60 LET D=1
70 LET MON=M
80 LET YEAR=Y
90 DIM A$(12,9)
100 LET A$(1)="JANUARY "
110 LET A$(2)="FEBRUARY "
120 LET A$(3)="MARCH "
130 LET A$(4)="APRIL "
140 LET A$(5)="MAY "
150 LET A$(6)="JUNE "
160 LET A$(7)="JULY "
170 LET A$(8)="AUGUST "
180 LET A$(9)="SEPTEMBER"
190 LET A$(10)="OCTOBER "
200 LET A$(11)="NOVEMBER "
210 LET A$(12)="DECEMBER "
220 DIM A(42)
230 LET END=30
240 IF M=1 OR M=3 OR M=5 OR M=7 OR M=8 OR M=10 OR M=12 THEN LET END=31
250 IF M=2 THEN LET END=28
260 LET LEAP=0
270 IF Y/4= INT (Y/4) AND Y/100 <> INT (Y/100) THEN LET LEAP=1
280 IF Y/400= INT (Y/400) THEN LET LEAP=1
300 IF M=2 AND LEAP=1 THEN LET END=29
310 IF M=1 OR M=2 THEN LET M=M+12
320 IF M=13 OR M=14 THEN LET Y=Y-1
330 LET R=D+2*M+2+ INT ((3*M+3)/5)+ INT (Y/4)+Y- INT (Y/100)+ INT (Y/400)
340 LET NUM=(R/7- INT (R/7))*7
350 LET NUM= INT (NUM+.5)
360 LET START=NUM
370 IF NUM=0 THEN LET START=7
380 LET DAY=1
390 FOR P=START TO 42
400 LET A(P)=DAY
410 LET DAY=DAY+1
420 NEXT P
430 CLS
440 PRINT TAB 10;A$(MON);" ";YEAR
450 PRINT
460 PRINT " SUN MON TUE WED THU FRI SAT"
470 FOR R=0 TO 5
480 FOR C=1+R*7 TO 7+R*7
490 LET CC=C-R*7
500 IF A(C)=0 THEN PRINT TAB (4*CC);" ";
510 IF A(C)=0 THEN GO TO 550
520 IF A(C)>END THEN PRINT TAB (4*CC);" ";
530 IF A(C)>END THEN GO TO 550
540 PRINT TAB (4*CC);A(C);
550 NEXT C
560 NEXT R
570 PRINT AT 15,1;"WOULD YOU LIKE TO TRY AGAIN?(Y OR N)"
580 INPUT B$
590 IF B$="Y" THEN GO TO 5
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
