夜光序言:
知道雪为什么是白色的吗?因为它忘记了自己曾经的颜色。那年你站在樱花下冲着我淡淡的微笑,还记得曾经纯真的你吗?
正文:
案例 2 我的万年日历
2.1 需求分析
日历时我们日常生活中常用的,我们常常要知道某一年的日历,还要知道历史上任何一个日期是星期几,这个程序的功能就能满足这些要求。
2.1.1 系统概述
程序的功能:
(1) 计算历史上某一天是星期几
(2) 打印任何一年的日历
2.1.2 系统运行环境
一、硬件环境【皮一下~~】
处理器:i7或更高
内存:32GB
硬盘空间:10TB
显卡:液晶 显示适配器
二、软件环境
操作系统:Windows 10/8/2000/XP+Python3.7
2.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
天(闰年),设计 months 列表:
months=[0,31,28,31,30,31,30,31,31,30,31,30,31]
其中 months[0]是没有意义的,默认为 0,months[1]是 1 月的最大天数 31 天。
3.某日期是星期几
要知道 y 年 m 月 d 日是星期几,根据日历历法的规则可以知道计算方法,我们必须先知道这一天是该年的第几天,这个函数设计为 countDays,它计算 y 年 m 月 d 日是该年第几天:
months=[0,31,28,31,30,31,30,31,31,30,31,30,31]
def isLeap(y):
return (y%400==0 or y%4==0 and y%100!=0)
def countDays(y,m,d):
global months
days=d
if isLeap(y):
months[2] = 29
else:
months[2] = 28
for n in range(1,m):
days+=months[n]
return days
其中判断 m 是在哪个月,把之前的整数月的天数全部累加,再加上日期 d 就是该年第几天了。例如m=5,那么前面 m>=2, m>=3, m>=4, m>=5 的条件都成了,于是累加 1、2、3、4 月的天数,即 31+(28 or29)+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 年 m 月 d 日是星期几:
def countWeek(y,m,d):
days=countDays(y,m,d)
y=y-1
w=y+y//4+y//400-y//100+days
w=w%7
return w
2. 打印一个月的日历
设每个日期占输出宽度是 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 的倍数时就换行,打印下一个星期。
2.3 程序代码
months=[0,31,28,31,30,31,30,31,31,30,31,30,31]
# 夜光
def isLeap(y):
return (y%400==0 or y%4==0 and y%100!=0)
def countDays(y,m,d):
global months
days=d
if isLeap(y):
months[2] = 29
else:
months[2] = 28
for n in range(1,m):
days+=months[n]
return days
def countWeek(y,m,d):
days=countDays(y,m,d)
y=y-1
w=y+y//4+y//400-y//100+days
w=w%7
return w
def printWeek():
global months
s=input("yyyy-mm-dd:")
s=s.split("-")
if len(s)==3:
try:
y=int(s[0])
m=int(s[1])
d=int(s[2])
if y<0:
raise Exception("无效的年份")
if m<0 or m>12:
raise Exception("无效的月份")
if isLeap(y):
months[2] = 29
else:
months[2] = 28
if d<1 or d>months[m]:
raise Exception("无效的日期")
w=countWeek(y,m,d)
week = ["日", "一", "二", "三", "四", "五", "六"]
print(y, m, d, "星期" + week[w])
except Exception as e:
print(e)
else:
print("无效日期")
def printMonth(y, m):
global months
w = countWeek(y, m, 1)
if isLeap(y):
months[2] = 29
else:
months[2] = 28
md = months[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()
def printCalandar():
try:
y = input("输入年份:")
y = int(y)
for m in range(1, 13):
print()
print("-------------", y, "年", m, "月 -------------")
printMonth(y, m)
print()
except Exception as e:
print(e)
while True:
print()
print("1.计算某天星期几")
print("2.打印某年的日历")
print("2.退出")
s = input("请选择(1,2,3)")
if s == "1":
printWeek()
elif s == "2":
printCalandar()
elif s == "3":
break
2.4 程序测试
1.计算某天星期几
2.打印某年的日历
2.退出
请选择(1,2,3)1
yyyy-mm-dd:2019-5-16
2019 5 16 星期四
1.计算某天星期几
2.打印某年的日历
2.退出
请选择(1,2,3)2
输入年份:2019