夜光序言:
Do not worry about smiling, my mouth hardly ever smiles, but it doesn’t mean I’m not smiling in my brain. 别为微笑而忧虑,我也很少在表面上微笑,但这并不表示我没在心里微笑。
正文:
3.7 实践项目 打印万年日历
3.7.1 项目目标
日历程序可以打印出任何一年的日历,程序运行后输入一个年份,例如 2019 年,打印出全年的日历,图 3-7-1 是 1 月的日历部分。
图 3-7-1
3.7.2 项目设计
1.闰年的判断
判断一年 y 是否是闰年,只要下面的两个条件之一成立:
(1) y 可以被 4 整除,同时不能被 100 整除;
(2) y 可以被 400 整除;
因此可以编写一个判断闰年的函数 IsLeap 如下:
def isLeap(y):
return y%400==0 or y%4==0 and y%100!=0
2.某月最大天数
不同的月份最大天数不同,1、3、5、7、8、10、12 月为 31 天,2 月要么是 28 天(平年)要么是 29 天(闰年),设计 maxDays 函数返回 y 年 m 月最大天数:
def maxDays(y,m):
d=30
if m==1 or m==3 or m==5 or m==7 or m==8 or m==10 or m==12:
d=31
elif m==2:
d=29 if isLeap(y) else 28
return d
3.某月 1 日是星期几
要打印 y 年 m 月的日历,必须知道 y 年 m 月 1 日是星期几,根据日历历法的规则可~~
以知道计算方法,我们必须先知道这一天是该年的第几天,这个函数设计为 countDays,它计算 y 年 m 月 d 日是该年第几天:
def countDays(y,m,d):
days=d
if m>=2:
days+=31
if m>=3:
days+=29 if isLeap(y) else 28
if m>=4:
days+=31
if m>=5:
days+=30
if m>=6:
days+=31
if m>=7:
days+=30
if m>=8:
days+=31
if m>=9:
days+=31
if m>=10:
days+=30
if m>=11:
days+=31
if m>=12:
days+=30
return days
其中判断 m 是在哪个月,把之前的整数月的天数全部累加,再加上日期 d 就是该年第几天了。例如 m=5,那么前面 m>=2, m>=3, m>=4, m>=5 的条件都成了,于是累加 1、2、3、4 月的天数,即 31+(28 or 29)+31+30,其中 2 月加 28(平年)或者 29(闰年)。
再根据下面的历法公式计算这一天是星期几:
((y-1)+ (y-1)//400+(y-1)//4-(y-1)//100+countDays(y,m,1))%7
该计算值为 0、1、2、3、4、5、6 分别对应星期日、一、二、三、四、五、六,编写下面的 countWeek 函数计算 y 年的元旦是星期几:
def countWeek(y,m):
w=(y-1)+(y-1)//400+(y-1)//4-(y-1)//100+countDays(y,m,1)
return w%7
4. 打印一个月的日历
设每个日期占输出宽度是 6 个字符,一个单元 6 个位置,则 7 个日期占 42 的字符宽度, 计算 y 年 m 月 1 日是星期 w,然后通过:
for i in range(w):
print("%-6s" % " ",end="")
显示 w 个空单元,然后使用:
for d in range(1,md+1):
print("%-6d" % d,end="")
w=w+1
if w%7==0:
print()
打印这个月的日历,当 w 是 7 的倍数时就换行,打印下一个星期。
3.7.3 项目实践
# 夜光:打印日历
def isLeap(y):
return y%400==0 or y%4==0 and y%100!=0
def maxDays(y,m):
d=30
if m==1 or m==3 or m==5 or m==7 or m==8 or m==10 or m==12:
d=31
elif m==2:
d=29 if isLeap(y) else 28
return d
def countDays(y,m,d):
days=d
if m>=2:
days+=31
if m>=3:
days+=29 if isLeap(y) else 28
if m>=4:
days+=31
if m>=5:
days+=30
if m>=6:
days+=31
if m>=7:
days+=30
if m>=8:
days+=31
if m>=9:
days+=31
if m>=10:
days+=30
if m>=11:
days+=31
if m>=12:
days+=30
return days
def countWeek(y,m):
w=(y-1)+(y-1)//400+(y-1)//4-(y-1)//100+countDays(y,m,1)
return w%7
def printMonth(y,m):
w=countWeek(y,m)
md=maxDays(y,m)
print("%-6s%-6s%-6s%-6s%-6s%-6s%-6s" %("Sun","Mon","Tue","Wed","Thu","Fri","Sat")
)
for i in range(w):
print("%-6s" % " ",end="")
for d in range(1,md+1):
print("%-6d" % d,end="")
w=w+1
if w%7==0:
print()
y=input("输入年份:")
y=int(y)
for m in range(1,13):
print()
print("-------------",y,"年",m,"月 -------------")
printMonth(y,m)
print()