2022年 11月 3日

如何用Python做日历?

19c8a0a8b06ed96b5ec2f8e222417672.gif

在后台回复【阅读书籍】

即可获取python相关电子书~

Hi,我是山月。

2022年已经过去一周了,现在山月已经习惯把年份写成2022啦。也正是这个习惯,把我从2021年已经过去了的恍惚感中拉了出来。

希望新的一年,我们都能变的更优秀一点~b6a08507706c5231606282590ef96288.png6ded77aedea017121d6d8c8196d8bfc5.png1a8f97bf9970630b7c4b1e5a64a03359.png

好啦,下面就跟着山月一起用Python做份日历吧。

现在,先想想你一般用的日历是什么样子的?有哪些元素?

这是山月根据日常用的日历制作的2022年1月的日历:

cc62f0ea75db9bef82081b56ddaa1bb2.png

想得到完整代码的在后台回复【2022年日历】即可哦~

01

准备工作

1、用到的几个库:datetime, calendar, xlwt,borax。

其中xlwt和borax需要安装,直接用pip进行安装就可以了。

2、2022年放假安排

查看地址:http://www.gov.cn/zhengce/content/2021-10/25/content_5644835.htm

f61a0120f5cd47cfd8b3600a6ba8aa16.png

根据放假安排,我们可以做出三个字典:festival_dict(节日信息),holidays_dict(节假日信息),switch_dict(调班信息)。

  1. #2022年节日
  2. festival_dict = {
  3.     datetime.date(year=2022, month=1, day=1) : "元旦",
  4.     datetime.date(year=2022, month=1, day=31) :  "除夕",
  5.     datetime.date(year=2022, month=2, day=1) : "春节",
  6.     datetime.date(year=2022, month=4, day=5) : "清明节",
  7.     datetime.date(year=2022, month=5, day=1) : "劳动节",
  8.     datetime.date(year=2022, month=6, day=3) : "端午节",
  9.     datetime.date(year=2022, month=9, day=10) : "中秋节",
  10.     datetime.date(year=2022, month=10, day=1) : "国庆节",
  11. }
  12. #2022年节假日
  13. holidays_dict = {
  14.     datetime.date(year=2022, month=1, day=1) : '元旦' , 
  15.     datetime.date(year=2022, month=1, day=2) : '元旦' , 
  16.     datetime.date(year=2022, month=1, day=3) : '元旦' ,
  17.     datetime.date(year=2022, month=1, day=31): '春节',
  18.     datetime.date(year=2022, month=2, day=1): '春节',
  19.     datetime.date(year=2022, month=2, day=2): '春节',
  20.     datetime.date(year=2022, month=2, day=3): '春节',
  21.     datetime.date(year=2022, month=2, day=4): '春节',
  22.     datetime.date(year=2022, month=2, day=5): '春节',
  23.     datetime.date(year=2022, month=2, day=6): '春节',
  24.     datetime.date(year=2022, month=4, day=3): '清明节',
  25.     datetime.date(year=2022, month=4, day=4): '清明节',
  26.     datetime.date(year=2022, month=4, day=5): '清明节',
  27.     datetime.date(year=2022, month=4, day=30): '劳动节',
  28.     datetime.date(year=2022, month=5, day=1): '劳动节',
  29.     datetime.date(year=2022, month=5, day=2): '劳动节',
  30.     datetime.date(year=2022, month=5, day=3): '劳动节',
  31.     datetime.date(year=2022, month=5, day=4): '劳动节',
  32.     datetime.date(year=2022, month=6, day=3): '端午节',
  33.     datetime.date(year=2022, month=6, day=4): '端午节',
  34.     datetime.date(year=2022, month=6, day=5): '端午节',
  35.     datetime.date(year=2022, month=9, day=10) : '中秋节',
  36.     datetime.date(year=2022, month=9, day=11) : '中秋节',
  37.     datetime.date(year=2022, month=9, day=12) : '中秋节',
  38.     datetime.date(year=2022, month=10, day=1): '国庆节',
  39.     datetime.date(year=2022, month=10, day=2): '国庆节',
  40.     datetime.date(year=2022, month=10, day=3): '国庆节',
  41.     datetime.date(year=2022, month=10, day=4): '国庆节',
  42.     datetime.date(year=2022, month=10, day=5): '国庆节',
  43.     datetime.date(year=2022, month=10, day=6): '国庆节',
  44.     datetime.date(year=2022, month=10, day=7): '国庆节',
  45. }
  46. 2022年调班
  47. switch_dict = {
  48.     datetime.date(year=2022, month=1, day=29): '春节',
  49.     datetime.date(year=2022, month=1, day=30): '春节',
  50.     datetime.date(year=2022, month=4, day=2): '清明节',
  51.     datetime.date(year=2022, month=4, day=24): '劳动节',
  52.     datetime.date(year=2022, month=5, day=7): '劳动节',
  53.     datetime.date(year=2022, month=10, day=8): '国庆节' ,
  54.     datetime.date(year=2022, month=10, day=9): '国庆节' ,
  55. }
  56. # 获取三个字典中的所有键
  57. all_festival_days = list(festival_dict.keys())
  58. all_holidays_days = list(holidays_dict.keys())
  59. all_switch_days = list(switch_dict.keys())

02

实现目标

1、得到2022年1月的日历

  1. import calendar
  2. 20221
  3. calendar_year = 2022
  4. calendar_month = 1
  5. # 得出20221月的日历
  6. calendar.setfirstweekday(firstweekday=0) #将星期一设置为一周第一天
  7. list_date = calendar.monthcalendar(calendar_year, calendar_month)
  8. 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、得出日期对应的农历

  1. from borax.calendars import LunarDate
  2. 202212
  3. calendar_year = 2022
  4. calendar_month = 1
  5. date = 2
  6. #得出202212日的农历日期,格式只显示日期
  7. lunar_date = LunarDate.from_solar_date(calendar_year, calendar_month, date)
  8. lunar_day = lunar_date.strftime('%D'
  9. print(lunar_day)

运行结果:

三十

我们翻看日历,可以发现2022年1月2日的农历是十一月三十。

那如果这个日期是节日,我们不想显示农历日期,而改用节日怎么办呢?

把我们准备的字典festival_dict(节日信息)用起来吧。

比如2022年1月31日是除夕:

  1. import datetime
  2. 2022131
  3. calendar_year = 2022
  4. calendar_month = 1
  5. date = 31
  6. date_day = datetime.date(year=calendar_year, month=calendar_month, day=date)
  7. festival_dict = {
  8.     datetime.date(year=2022, month=1, day=1) : "元旦",
  9.     ...
  10.     
  11.     '''为了更直观,这里把字典的内容省去了,详情可以看上面'''
  12. }
  13. all_festival_days = list(festival_dict.keys())
  14. if date_day in all_festival_days:
  15.     print(festival_dict[date_day])

运行结果:

除夕

这个时候就得到了节日啦。

3、节假日放假休息与调班

继续运用准备好的字典holidays_dict(节假日信息),switch_dict(调班信息)。

1)节假日休息

比如我们知道2022.1.3是元旦的最后一天,这一天应该要显示个【休】~5d88fe88218089e5147ee4a89e684000.pnga7f5a09b50d3272ae5329f5c1a18ea9f.png62f9455dc734b8f0d452e80713ad1c84.png

  1. import datetime
  2. 202213
  3. calendar_year = 2022
  4. calendar_month = 1
  5. date = 3
  6. date_day = datetime.date(year=calendar_year, month=calendar_month, day=date)
  7. holidays_dict = {
  8.     datetime.date(year=2022, month=1, day=1) : '元旦' , 
  9.     ...
  10.     
  11.     '''为了更直观,这里把字典的内容省去了,详情可以看上面'''
  12. }
  13. all_holidays_days = list(holidays_dict.keys())
  14. if date_day in all_holidays_days:
  15.     print('休')
  16. else:
  17.     print('休息啥,搬砖去')

运行结果:

让人非常高兴的一个字~

2)节假日调班

对于单休的人来说,最怕调班周末,这意味着要连续上两个星期的班。0c30b04131a9ea58a1caffca0077426e.png7b608d17dc0beeb7cd05ba635d9ee619.png7481431434519ea7014376a9bb3da255.png

2022年1月的29和30需要为春节调班。以29号为例,我们来看看怎么实现吧。

  1. import datetime
  2. 2022129
  3. calendar_year = 2022
  4. calendar_month = 1
  5. date = 29
  6. date_day = datetime.date(year=calendar_year, month=calendar_month, day=date)
  7. switch_dict = {
  8.     datetime.date(year=2022, month=1, day=29): '春节',
  9.     ...
  10.     
  11.     '''为了更直观,这里把字典的内容省去了,详情可以看上面'''
  12. }
  13. all_switch_days = list(switch_dict.keys())
  14. if date_day in all_switch_days:
  15.     print('班')
  16. else:
  17.     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年日历】找山月要

  1. import datetime, calendar, xlwt
  2. from borax.calendars import LunarDate
  3. #2022年节日
  4. festival_dict = {
  5.     datetime.date(year=2022, month=1, day=1) : "元旦",
  6.     '''为了更直观,这里把字典的内容省去了,详情可以看上面'''
  7. }
  8. #2022年节假日
  9. holidays_dict = {
  10.     datetime.date(year=2022, month=1, day=1) : '元旦' , 
  11.     '''为了更直观,这里把字典的内容省去了,详情可以看上面'''
  12. }
  13. 2022年调班
  14. switch_dict = {
  15.     datetime.date(year=2022, month=1, day=29): '春节',
  16.     '''为了更直观,这里把字典的内容省去了,详情可以看上面'''
  17. }
  18. # 获取三个字典中的所有键
  19. all_festival_days = list(festival_dict.keys())
  20. all_holidays_days = list(holidays_dict.keys())
  21. all_switch_days = list(switch_dict.keys())
  22. 2022年*月
  23. calendar_year = 2022
  24. calendar_month = 1
  25. # 得出2022年*月的日历
  26. calendar.setfirstweekday(firstweekday=0)  #将星期一设置为一周第一天
  27. list_date = calendar.monthcalendar(calendar_year, calendar_month)
  28. # 创建一个新的工作薄及工作表
  29. wb = xlwt.Workbook(encoding='utf-8',style_compression=0)  
  30. ws = wb.add_sheet('日历',cell_overwrite_ok=True) 
  31. ws.set_show_grid(0)     #工作表隐藏网格线
  32. #设置写入格式
  33. style_month = xlwt.easyxf('font: bold True, height 320 ; alignment: horz center, vert center; borders: left thin, right thin, top thin, bottom thin ')
  34. style_week = xlwt.easyxf('font: bold True ; alignment: horz center, vert center; borders: left thin, right thin, top thin, bottom thin ')
  35. style_date = xlwt.easyxf('font: height 280  ; alignment: horz right, vert center; borders: left thin , top thin')
  36. style_lunar_date = xlwt.easyxf('font: height 160  ; alignment: horz center, vert top; borders: left thin, right thin, bottom thin  ')
  37. style_holiday = xlwt.easyxf('font: height 160, colour_index red ; alignment: horz left, vert center ; borders: right thin ')
  38. # 设置行高
  39. style_550 = xlwt.easyxf('font:height 550;')  
  40. style_400 = xlwt.easyxf('font:height 400;'
  41. style_350 = xlwt.easyxf('font:height 350;'
  42. row_2 = ws.row(1)
  43. row_3 = ws.row(2)
  44. row_2.set_style(style_550)
  45. row_3.set_style(style_400)
  46. for row_num in [3,5,7,9,11,13]:
  47.     row_height = ws.row(row_num)
  48.     row_height.set_style(style_350)
  49. #写抬头说明是2022年某月
  50. calendar_text = '2022年' + str(calendar_month) + '月'
  51. ws.write_merge(11114, calendar_text, style_month)  
  52. #写抬头显示星期几
  53. week_list = ['星期一''星期二''星期三''星期四''星期五''星期六''星期日']
  54. row_start = -1
  55. row_end = 0
  56. for i in range(7):
  57.     row_start += 2 
  58.     row_end += 2
  59.     ws.write_merge(22, row_start, row_end, week_list[i], style_week)
  60. #绘写日历
  61. row_date_list = [35791113]
  62. col_date_list = [135 , 7 , 91113]
  63. for row, week_list in enumerate(list_date):
  64.     for col, date in enumerate(week_list):
  65.         if date != 0:
  66.             #写日期
  67.             ws.write(row_date_list[row], col_date_list[col], date, style_date) 
  68.             date_day = datetime.date(year=calendar_year, month=calendar_month, day=date)
  69.             #写农历,如果是节日写节日
  70.             if date_day in all_festival_days:
  71.                 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) 
  72.             else:
  73.                 # 将公历日期转化为农历日期
  74.                 lunar_date = LunarDate.from_solar_date(calendar_year, calendar_month, date)
  75.                 lunar_day = lunar_date.strftime('%D'
  76.                 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) 
  77.             
  78.             #写节假日休息
  79.             if date_day in all_holidays_days:
  80.                 ws.write(row_date_list[row], col_date_list[col]+1'休', style_holiday)
  81.             #写节假日调班
  82.             elif date_day in all_switch_days:
  83.                 ws.write(row_date_list[row], col_date_list[col]+1'班', style_holiday)
  84.             else:
  85.                 ws.write(row_date_list[row], col_date_list[col]+1' ', style_holiday)
  86.        
  87.         else:
  88.             ws.write(row_date_list[row], col_date_list[col], ' ', style_date)
  89.             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) 
  90.             ws.write(row_date_list[row], col_date_list[col]+1' ', style_holiday)
  91. wb.save('2022年1月日历.xls')  #保存excel

完成~

当然,这是2022年某个月的日历代码,如果是要一整年的,可以用循环~这个就交给大家去尝试啦。

最后,也许有小伙伴会说每年还要做字典?这样不效率啊。

其实我们有一个节假日的库:chinesecalendar。

官网:https://pypi.org/project/chinesecalendar/

github:https://github.com/LKI/chinese-calendar

它目前最新版本已经更新到了2022年。

其实它的内核也是把一个个节假日日期整理成一个”wheel车轮”,这样下次可以就直接使用了。

58ef91f167aea340640b30357749fe57.png

有兴趣的同学可以去看看。也希望这一点能给正在学习python的你一些感想。

已经到底啦~(≧▽≦*)/~

65b6ad15eec2bd51be3444f8e40e5838.png 往 期 推 荐 6937c1e0fe594cba56020089dd106714.png

年会将近?赶紧学学如何用Python做个抽奖界面

2022-01-02

abeff24521853932246fe8a7298d83a9.png

用Python写份【幸运】的元旦祝福

2021-12-31

9696ff95931e2e75893f3a63931ce2a4.png

Python自动化办公:xlwt万字教程

2021-12-20

1e72e500b3adcce06dba5eecb988f2a7.png

Python自动化办公:xlwt教程(二)

2021-12-23

ee39e3dfc2add9cf4d8e7c8bb9c528bc.png

77cde6ca43135fedc486599908e99466.gif

您的“点赞”、“在看”和 “分享”是我们产出的动力。