|
Calendars can be fun. When I realized that my HP-48SX display had enough lines and was wide enough to display a one month calendar, I wrote one. My first try was annoyingly slow, and I determined that the problem was with the code to actually draw the calendar. Going through each day and telling it "draw this number here" was just not efficient enough. I switched to a string based approach. Here is what it would look like in Python. This draws a cal-style calendar or a month given the day of the week of the first day of the month (Sunday == 0, Monday == 1, ...) and the number of days in the month: def print_cal(first_day, num_days):
hdr_str = "Su Mo Tu We Th Fr Sa "
cal_str = " 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 30 31 "
offset = 3*(6-first_day)
cal_flat = cal_str[offset:18+3*num_days]
cal_flat += " "
print(hdr_str)
print(cal_flat[0:21])
print(cal_flat[21:42])
print(cal_flat[42:63])
print(cal_flat[63:84])
print(cal_flat[84:105])
All the string operations were primitives in the calculator's slow interpreted language, implemented in fast assembly language, so this was very fast.Calculating the first day and number of days for a year/month was in the slow interpreted language, but that isn't much computation so it wasn't noticeable. In Python, it would be something like this: def first_and_length(year, month):
# Correction for centuries 16, 17, 18, 19
# Repeats every 4 centuries.
century_table = [2, 0, 5, 3]
# Correction for each month for years that are not leap years.
# For leap years, need to subtract 1 for January and February.
month_table = [4, 0, 0, 3, 5, 1, 3, 6, 2, 4, 0, 2]
month_length = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
num_days = month_length[month-1]
first_day_on = 1
first_day_on += century_table[(year//100)%4]
first_day_on += year%100 + (year%100)//4
first_day_on += month_table[month-1]
if month <= 2 and year%4 == 0:
if year%400 == 0 or year%100 != 0:
first_day_on -= 1
if month == 2: num_days += 1
return first_day_on%7, num_days
|