在后台回复【阅读书籍】
即可获取python相关电子书~
Hi,我是山月。
2022年已经过去一周了,现在山月已经习惯把年份写成2022啦。也正是这个习惯,把我从2021年已经过去了的恍惚感中拉了出来。
好啦,下面就跟着山月一起用Python做份日历吧。
现在,先想想你一般用的日历是什么样子的?有哪些元素?
这是山月根据日常用的日历制作的2022年1月的日历:
想得到完整代码的在后台回复【2022年日历】即可哦~
01
准备工作
1、用到的几个库:datetime, calendar, xlwt,borax。
其中xlwt和borax需要安装,直接用pip进行安装就可以了。
2、2022年放假安排
查看地址:http://www.gov.cn/zhengce/content/2021-10/25/content_5644835.htm
根据放假安排,我们可以做出三个字典:festival_dict(节日信息),holidays_dict(节假日信息),switch_dict(调班信息)。
#2022年节日
festival_dict = {
datetime.date(year=2022, month=1, day=1) : "元旦",
datetime.date(year=2022, month=1, day=31) : "除夕",
datetime.date(year=2022, month=2, day=1) : "春节",
datetime.date(year=2022, month=4, day=5) : "清明节",
datetime.date(year=2022, month=5, day=1) : "劳动节",
datetime.date(year=2022, month=6, day=3) : "端午节",
datetime.date(year=2022, month=9, day=10) : "中秋节",
datetime.date(year=2022, month=10, day=1) : "国庆节",
}
#2022年节假日
holidays_dict = {
datetime.date(year=2022, month=1, day=1) : '元旦' ,
datetime.date(year=2022, month=1, day=2) : '元旦' ,
datetime.date(year=2022, month=1, day=3) : '元旦' ,
datetime.date(year=2022, month=1, day=31): '春节',
datetime.date(year=2022, month=2, day=1): '春节',
datetime.date(year=2022, month=2, day=2): '春节',
datetime.date(year=2022, month=2, day=3): '春节',
datetime.date(year=2022, month=2, day=4): '春节',
datetime.date(year=2022, month=2, day=5): '春节',
datetime.date(year=2022, month=2, day=6): '春节',
datetime.date(year=2022, month=4, day=3): '清明节',
datetime.date(year=2022, month=4, day=4): '清明节',
datetime.date(year=2022, month=4, day=5): '清明节',
datetime.date(year=2022, month=4, day=30): '劳动节',
datetime.date(year=2022, month=5, day=1): '劳动节',
datetime.date(year=2022, month=5, day=2): '劳动节',
datetime.date(year=2022, month=5, day=3): '劳动节',
datetime.date(year=2022, month=5, day=4): '劳动节',
datetime.date(year=2022, month=6, day=3): '端午节',
datetime.date(year=2022, month=6, day=4): '端午节',
datetime.date(year=2022, month=6, day=5): '端午节',
datetime.date(year=2022, month=9, day=10) : '中秋节',
datetime.date(year=2022, month=9, day=11) : '中秋节',
datetime.date(year=2022, month=9, day=12) : '中秋节',
datetime.date(year=2022, month=10, day=1): '国庆节',
datetime.date(year=2022, month=10, day=2): '国庆节',
datetime.date(year=2022, month=10, day=3): '国庆节',
datetime.date(year=2022, month=10, day=4): '国庆节',
datetime.date(year=2022, month=10, day=5): '国庆节',
datetime.date(year=2022, month=10, day=6): '国庆节',
datetime.date(year=2022, month=10, day=7): '国庆节',
}
# 2022年调班
switch_dict = {
datetime.date(year=2022, month=1, day=29): '春节',
datetime.date(year=2022, month=1, day=30): '春节',
datetime.date(year=2022, month=4, day=2): '清明节',
datetime.date(year=2022, month=4, day=24): '劳动节',
datetime.date(year=2022, month=5, day=7): '劳动节',
datetime.date(year=2022, month=10, day=8): '国庆节' ,
datetime.date(year=2022, month=10, day=9): '国庆节' ,
}
# 获取三个字典中的所有键
all_festival_days = list(festival_dict.keys())
all_holidays_days = list(holidays_dict.keys())
all_switch_days = list(switch_dict.keys())
02
实现目标
1、得到2022年1月的日历
import calendar
# 2022年1月
calendar_year = 2022
calendar_month = 1
# 得出2022年1月的日历
calendar.setfirstweekday(firstweekday=0) #将星期一设置为一周第一天
list_date = calendar.monthcalendar(calendar_year, calendar_month)
print(list_date)
运行结果:
[[0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0]]
可以看出,monthcalendar(year, month)返回的是按周划分的一个月中天数的列表,不是当前月份的天数为0。
其中返回的列表里是由6个列表组成的,这6个列表是由7个元素组成的,代表了周一到周末的7天。
2、得出日期对应的农历
from borax.calendars import LunarDate
# 2022年1月2日
calendar_year = 2022
calendar_month = 1
date = 2
#得出2022年1月2日的农历日期,格式只显示日期
lunar_date = LunarDate.from_solar_date(calendar_year, calendar_month, date)
lunar_day = lunar_date.strftime('%D')
print(lunar_day)
运行结果:
三十
我们翻看日历,可以发现2022年1月2日的农历是十一月三十。
那如果这个日期是节日,我们不想显示农历日期,而改用节日怎么办呢?
把我们准备的字典festival_dict(节日信息)用起来吧。
比如2022年1月31日是除夕:
import datetime
# 2022年1月31日
calendar_year = 2022
calendar_month = 1
date = 31
date_day = datetime.date(year=calendar_year, month=calendar_month, day=date)
festival_dict = {
datetime.date(year=2022, month=1, day=1) : "元旦",
...
'''为了更直观,这里把字典的内容省去了,详情可以看上面'''
}
all_festival_days = list(festival_dict.keys())
if date_day in all_festival_days:
print(festival_dict[date_day])
运行结果:
除夕
这个时候就得到了节日啦。
3、节假日放假休息与调班
继续运用准备好的字典holidays_dict(节假日信息),switch_dict(调班信息)。
1)节假日休息
比如我们知道2022.1.3是元旦的最后一天,这一天应该要显示个【休】~
import datetime
# 2022年1月3日
calendar_year = 2022
calendar_month = 1
date = 3
date_day = datetime.date(year=calendar_year, month=calendar_month, day=date)
holidays_dict = {
datetime.date(year=2022, month=1, day=1) : '元旦' ,
...
'''为了更直观,这里把字典的内容省去了,详情可以看上面'''
}
all_holidays_days = list(holidays_dict.keys())
if date_day in all_holidays_days:
print('休')
else:
print('休息啥,搬砖去')
运行结果:
休
让人非常高兴的一个字~
2)节假日调班
对于单休的人来说,最怕调班周末,这意味着要连续上两个星期的班。
2022年1月的29和30需要为春节调班。以29号为例,我们来看看怎么实现吧。
import datetime
# 2022年1月29日
calendar_year = 2022
calendar_month = 1
date = 29
date_day = datetime.date(year=calendar_year, month=calendar_month, day=date)
switch_dict = {
datetime.date(year=2022, month=1, day=29): '春节',
...
'''为了更直观,这里把字典的内容省去了,详情可以看上面'''
}
all_switch_days = list(switch_dict.keys())
if date_day in all_switch_days:
print('班')
else:
print('休息啥,搬砖去')
运行结果:
班
bingo~
当然,在制作日历的过程里,我们要判断:如果是休息,则写个【休】;如果是调班,则写个【班】;否则就空白。
其实这样也很简单,用if...elif...else来判断就行啦。同学们可以自己想想,也可以看山月提供的完整代码。
4、日历显示
这里山月选择用excel把它呈现出来。用到的库是xlwt,关于xlwt的基础知识,山月之前已经分享过了,忘记了的同学请看
Python自动化办公:xlwt万字教程
Python自动化办公:xlwt教程(二)
对于我们的日历设计:
第2行显示日历的年月
第3行显示星期一到星期日
每个日期由2行2列组成,比如D4:E5组成了日期1号。其中D4显示日期;E4显示【休】or【班】or空白;D5:E5是个合并单元格,显示对应的农历日期/节日。
为了美观,进行一些格式设置
03
完成日历
下面就是整合啦~
同样为了直观,山月把三个字典的内容省略了,自己实际运行的时候记得在上面复制噢,或者选择在后台回复【2022年日历】找山月要。
import datetime, calendar, xlwt
from borax.calendars import LunarDate
#2022年节日
festival_dict = {
datetime.date(year=2022, month=1, day=1) : "元旦",
'''为了更直观,这里把字典的内容省去了,详情可以看上面'''
}
#2022年节假日
holidays_dict = {
datetime.date(year=2022, month=1, day=1) : '元旦' ,
'''为了更直观,这里把字典的内容省去了,详情可以看上面'''
}
# 2022年调班
switch_dict = {
datetime.date(year=2022, month=1, day=29): '春节',
'''为了更直观,这里把字典的内容省去了,详情可以看上面'''
}
# 获取三个字典中的所有键
all_festival_days = list(festival_dict.keys())
all_holidays_days = list(holidays_dict.keys())
all_switch_days = list(switch_dict.keys())
# 2022年*月
calendar_year = 2022
calendar_month = 1
# 得出2022年*月的日历
calendar.setfirstweekday(firstweekday=0) #将星期一设置为一周第一天
list_date = calendar.monthcalendar(calendar_year, calendar_month)
# 创建一个新的工作薄及工作表
wb = xlwt.Workbook(encoding='utf-8',style_compression=0)
ws = wb.add_sheet('日历',cell_overwrite_ok=True)
ws.set_show_grid(0) #工作表隐藏网格线
#设置写入格式
style_month = xlwt.easyxf('font: bold True, height 320 ; alignment: horz center, vert center; borders: left thin, right thin, top thin, bottom thin ')
style_week = xlwt.easyxf('font: bold True ; alignment: horz center, vert center; borders: left thin, right thin, top thin, bottom thin ')
style_date = xlwt.easyxf('font: height 280 ; alignment: horz right, vert center; borders: left thin , top thin')
style_lunar_date = xlwt.easyxf('font: height 160 ; alignment: horz center, vert top; borders: left thin, right thin, bottom thin ')
style_holiday = xlwt.easyxf('font: height 160, colour_index red ; alignment: horz left, vert center ; borders: right thin ')
# 设置行高
style_550 = xlwt.easyxf('font:height 550;')
style_400 = xlwt.easyxf('font:height 400;')
style_350 = xlwt.easyxf('font:height 350;')
row_2 = ws.row(1)
row_3 = ws.row(2)
row_2.set_style(style_550)
row_3.set_style(style_400)
for row_num in [3,5,7,9,11,13]:
row_height = ws.row(row_num)
row_height.set_style(style_350)
#写抬头说明是2022年某月
calendar_text = '2022年' + str(calendar_month) + '月'
ws.write_merge(1, 1, 1, 14, calendar_text, style_month)
#写抬头显示星期几
week_list = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日']
row_start = -1
row_end = 0
for i in range(7):
row_start += 2
row_end += 2
ws.write_merge(2, 2, row_start, row_end, week_list[i], style_week)
#绘写日历
row_date_list = [3, 5, 7, 9, 11, 13]
col_date_list = [1, 3, 5 , 7 , 9, 11, 13]
for row, week_list in enumerate(list_date):
for col, date in enumerate(week_list):
if date != 0:
#写日期
ws.write(row_date_list[row], col_date_list[col], date, style_date)
date_day = datetime.date(year=calendar_year, month=calendar_month, day=date)
#写农历,如果是节日写节日
if date_day in all_festival_days:
ws.write_merge(row_date_list[row]+1, row_date_list[row]+1, col_date_list[col], col_date_list[col]+1, festival_dict[date_day], style_lunar_date)
else:
# 将公历日期转化为农历日期
lunar_date = LunarDate.from_solar_date(calendar_year, calendar_month, date)
lunar_day = lunar_date.strftime('%D')
ws.write_merge(row_date_list[row]+1, row_date_list[row]+1, col_date_list[col], col_date_list[col]+1, lunar_day, style_lunar_date)
#写节假日休息
if date_day in all_holidays_days:
ws.write(row_date_list[row], col_date_list[col]+1, '休', style_holiday)
#写节假日调班
elif date_day in all_switch_days:
ws.write(row_date_list[row], col_date_list[col]+1, '班', style_holiday)
else:
ws.write(row_date_list[row], col_date_list[col]+1, ' ', style_holiday)
else:
ws.write(row_date_list[row], col_date_list[col], ' ', style_date)
ws.write_merge(row_date_list[row]+1, row_date_list[row]+1, col_date_list[col], col_date_list[col]+1, ' ', style_lunar_date)
ws.write(row_date_list[row], col_date_list[col]+1, ' ', style_holiday)
wb.save('2022年1月日历.xls') #保存excel
完成~
当然,这是2022年某个月的日历代码,如果是要一整年的,可以用循环~这个就交给大家去尝试啦。
最后,也许有小伙伴会说每年还要做字典?这样不效率啊。
其实我们有一个节假日的库:chinesecalendar。
官网:https://pypi.org/project/chinesecalendar/
github:https://github.com/LKI/chinese-calendar
它目前最新版本已经更新到了2022年。
其实它的内核也是把一个个节假日日期整理成一个"wheel车轮",这样下次可以就直接使用了。
有兴趣的同学可以去看看。也希望这一点能给正在学习python的你一些感想。
已经到底啦~(≧▽≦*)/~
年会将近?赶紧学学如何用Python做个抽奖界面
2022-01-02
用Python写份【幸运】的元旦祝福
2021-12-31
Python自动化办公:xlwt万字教程
2021-12-20
Python自动化办公:xlwt教程(二)
2021-12-23
您的“点赞”、“在看”和 “分享”是我们产出的动力。