您现在的位置是:首页 > 技术教程 正文

python自定义日历库,与对应calendar库函数功能基本一致

admin 阅读: 2024-03-20
后台-插件-广告管理-内容页头部广告(手机)

目录

自定义日历库

常用列表

日期列表

常用函数

闰年判断

月份天数

元旦序号

日历表头

星期序号

序号及天数

月历字串

打印月历

年历字串

打印年历

对比测试

测试结果

完整代码

运行结果


自定义日历库

自定义日历库函数,并使得其与python calendar库中对应的函数功能基本一致。

常用列表

month_name = ['January', 'February', 'March', 'April', 'May', 'June', 'July',
                  'August', 'September', 'October', 'November', 'December']
day_name = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']

def daylist(year, month):
    days = [' ']*weekday(year, month) + [*range(1, monthday(year)[month-1]+1)]
    return days + [' ']*(42-len(days))

def dayslist(year, month):
    dlist, count = daylist(year, month), monthday(year)[month-1]//7+2
    mlist = [' '.join(map(lambda n:str(n).rjust(2), dlist[i*7:i*7+7])) for i in range(count)]
    return [month_name[month-1].center(20), weekheader(), *mlist]

常用函数

为方便写代码间隔都以库函数默认值为准,放弃对库函数的间隔参数进行模拟,比如:

calendar.prcal(theyear, w=0, l=0, c=6, m=3),其中 w, l, c 为间隔参数。

闰年判断

判断条件:年份数能被4整除且不能被100整除,或者能被400整除的

def isleap(year):
    '''Return True for leap years, False for non-leap years.'''
    return year%4==0 and year%100!=0 or year%400==0

月份天数

12个月份的天数,只有2月份的天数是可变的,闰年+1。

monthday = lambda year: [31, 28+isleap(year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

元旦序号

这个计算公式看似很神奇,实际上它的本质也就来源于闰年判断公式isleap(year)。即计算公元1年到给定年份(不包括)之间有多少个年份是闰年,公元1年1月1日是星期一是计算基准。所以年份数减一加上能被4整除的年数减去那些能被100整除但不能被400整除的年数加上能被400整除的年数即周一的总位移数,这个结果取余(%7)后的结果0-6对应的是周一~周日。

firstday = lambda year: (year-1+(year-1)//4-(year-1)//100+(year-1)//400)%7

使用python 3.8及以上的版本,有个海象操作符,上式改写成以下形式:

firstday = lambda year: (y+y//4-y//100+y//400)%7 if (y:=year-1)+1 else None

是不是更简洁了,顺便还去掉了0年,因为年份只有公元1年公元前1年,中间没有公元0年的。

日历表头

def weekheader(width=2):
    '''Return a header for a week.'''
    space = ((width-2 if width>3 else 1)*' ')
    return space.join(map(lambda x:x[:min(width, 3) if width<9 else 9], day_name))

星期序号

以 firstday(year) 作基准计算指定日期的星期序号,结果0~6则对应周一~周日。

def weekday(year, month, day=1):
    '''Return weekday (0-6 ~ Mon-Sun) for year, month (1-12), day (1-31).'''
    return (firstday(year)+sum(monthday(year)[:month-1])+day-1)%7

序号及天数

def monthrange(year, month):
    '''Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month.'''
    return weekday(year, month, 1), monthday(year)[month-1]

月历字串

def month(year, month):
    '''Return a month's calendar string (multi-line).'''
    days = [day for day in dayslist(year, month) if day.strip()]
    return (" ".join([days[0].strip(),str(year)]).center(20).rstrip()+'\n'+'\n'.join(days[1:])).rstrip()+'\n'

打印月历

def prmonth(year, month):
    '''Print a month's calendar.'''
    print(month(year, month))

年历字串

def calendar(year):
    '''Returns a year's calendar as a multi-line string.'''
    result = str(year).center(72).rstrip()+'\n'
    for i in range(4):
        result += '\n'
        for row in zip(*[dayslist(year,i*3+j) for j in range(1,4)]):
            result += (6*' ').join(row).rstrip()+'\n' if (6*' ').join(row).strip() else ''
    return result

打印年历

def prcal(year):
    '''Print a year's calendar.'''
    print(calendar(year))

对比测试

测试结果

本文末尾有完整代码,保存为mycalendar.py;然后与对应内置的日历库函数对比:

>>> import calendar, mycalendar
>>> all((calendar.weekday(i,1,1)==mycalendar.weekday(i,1,1) for i in range(3000)))
True
>>> all((calendar.monthrange(i,1)==mycalendar.monthrange(i,1) for i in range(3000)))
True
>>> all((calendar.month(i,1)==mycalendar.month(i,1) for i in range(3000)))
True
>>> all((calendar.calendar(i)==mycalendar.calendar(i) for i in range(3000)))
True

# 测试结果:四个主要函数的运行结果在3000年中与对应库函数的完全一致。

完整代码

  1. month_name = ['January', 'February', 'March', 'April', 'May', 'June', 'July',
  2. 'August', 'September', 'October', 'November', 'December']
  3. day_name = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
  4. def daylist(year, month):
  5. days = [' ']*weekday(year, month) + [*range(1, monthday(year)[month-1]+1)]
  6. return days + [' ']*(42-len(days))
  7. def dayslist(year, month):
  8. dlist, count = daylist(year, month), monthday(year)[month-1]//7+2
  9. mlist = [' '.join(map(lambda n:str(n).rjust(2), dlist[i*7:i*7+7])) for i in range(count)]
  10. return [month_name[month-1].center(20), weekheader(), *mlist]
  11. def isleap(year):
  12. '''Return True for leap years, False for non-leap years.'''
  13. return year%4==0 and year%100!=0 or year%400==0
  14. monthday = lambda year: [31, 28+isleap(year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  15. firstday = lambda year: (year-1+(year-1)//4-(year-1)//100+(year-1)//400)%7
  16. def weekheader(width=2):
  17. '''Return a header for a week.'''
  18. space = ((width-2 if width>3 else 1)*' ')
  19. return space.join(map(lambda x:x[:min(width, 3) if width<9 else 9], day_name))
  20. def weekday(year, month, day=1):
  21. '''Return weekday (0-6 ~ Mon-Sun) for year, month (1-12), day (1-31).'''
  22. return (firstday(year)+sum(monthday(year)[:month-1])+day-1)%7
  23. def monthrange(year, month):
  24. '''Return weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month.'''
  25. return weekday(year, month, 1), monthday(year)[month-1]
  26. def month(year, month):
  27. '''Return a month's calendar string (multi-line).'''
  28. days = [day for day in dayslist(year, month) if day.strip()]
  29. return (" ".join([days[0].strip(),str(year)]).center(20).rstrip()+'\n'+'\n'.join(days[1:])).rstrip()+'\n'
  30. def prmonth(year, month):
  31. '''Print a month's calendar.'''
  32. print(month(year, month))
  33. def calendar(year):
  34. '''Returns a year's calendar as a multi-line string.'''
  35. result = str(year).center(72).rstrip()+'\n'
  36. for i in range(4):
  37. result += '\n'
  38. for row in zip(*[dayslist(year,i*3+j) for j in range(1,4)]):
  39. result += (6*' ').join(row).rstrip()+'\n' if (6*' ').join(row).strip() else ''
  40. return result
  41. def prcal(year):
  42. '''Print a year's calendar.'''
  43. print(calendar(year))

运行结果

                                  2023

      January                   February                   March
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
                   1             1  2  3  4  5             1  2  3  4  5
 2  3  4  5  6  7  8       6  7  8  9 10 11 12       6  7  8  9 10 11 12
 9 10 11 12 13 14 15      13 14 15 16 17 18 19      13 14 15 16 17 18 19
16 17 18 19 20 21 22      20 21 22 23 24 25 26      20 21 22 23 24 25 26
23 24 25 26 27 28 29      27 28                     27 28 29 30 31
30 31

       April                      May                       June
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
                1  2       1  2  3  4  5  6  7                1  2  3  4
 3  4  5  6  7  8  9       8  9 10 11 12 13 14       5  6  7  8  9 10 11
10 11 12 13 14 15 16      15 16 17 18 19 20 21      12 13 14 15 16 17 18
17 18 19 20 21 22 23      22 23 24 25 26 27 28      19 20 21 22 23 24 25
24 25 26 27 28 29 30      29 30 31                  26 27 28 29 30

        July                     August                  September
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
                1  2          1  2  3  4  5  6                   1  2  3
 3  4  5  6  7  8  9       7  8  9 10 11 12 13       4  5  6  7  8  9 10
10 11 12 13 14 15 16      14 15 16 17 18 19 20      11 12 13 14 15 16 17
17 18 19 20 21 22 23      21 22 23 24 25 26 27      18 19 20 21 22 23 24
24 25 26 27 28 29 30      28 29 30 31               25 26 27 28 29 30
31

      October                   November                  December
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
                   1             1  2  3  4  5                   1  2  3
 2  3  4  5  6  7  8       6  7  8  9 10 11 12       4  5  6  7  8  9 10
 9 10 11 12 13 14 15      13 14 15 16 17 18 19      11 12 13 14 15 16 17
16 17 18 19 20 21 22      20 21 22 23 24 25 26      18 19 20 21 22 23 24
23 24 25 26 27 28 29      27 28 29 30               25 26 27 28 29 30 31
30 31

                                  2024

      January                   February                   March
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
 1  2  3  4  5  6  7                1  2  3  4                   1  2  3
 8  9 10 11 12 13 14       5  6  7  8  9 10 11       4  5  6  7  8  9 10
15 16 17 18 19 20 21      12 13 14 15 16 17 18      11 12 13 14 15 16 17
22 23 24 25 26 27 28      19 20 21 22 23 24 25      18 19 20 21 22 23 24
29 30 31                  26 27 28 29               25 26 27 28 29 30 31

       April                      May                       June
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
 1  2  3  4  5  6  7             1  2  3  4  5                      1  2
 8  9 10 11 12 13 14       6  7  8  9 10 11 12       3  4  5  6  7  8  9
15 16 17 18 19 20 21      13 14 15 16 17 18 19      10 11 12 13 14 15 16
22 23 24 25 26 27 28      20 21 22 23 24 25 26      17 18 19 20 21 22 23
29 30                     27 28 29 30 31            24 25 26 27 28 29 30

        July                     August                  September
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
 1  2  3  4  5  6  7                1  2  3  4                         1
 8  9 10 11 12 13 14       5  6  7  8  9 10 11       2  3  4  5  6  7  8
15 16 17 18 19 20 21      12 13 14 15 16 17 18       9 10 11 12 13 14 15
22 23 24 25 26 27 28      19 20 21 22 23 24 25      16 17 18 19 20 21 22
29 30 31                  26 27 28 29 30 31         23 24 25 26 27 28 29
                                                    30

      October                   November                  December
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
    1  2  3  4  5  6                   1  2  3                         1
 7  8  9 10 11 12 13       4  5  6  7  8  9 10       2  3  4  5  6  7  8
14 15 16 17 18 19 20      11 12 13 14 15 16 17       9 10 11 12 13 14 15
21 22 23 24 25 26 27      18 19 20 21 22 23 24      16 17 18 19 20 21 22
28 29 30 31               25 26 27 28 29 30         23 24 25 26 27 28 29
                                                    30 31

                                  2025

      January                   February                   March
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
       1  2  3  4  5                      1  2                      1  2
 6  7  8  9 10 11 12       3  4  5  6  7  8  9       3  4  5  6  7  8  9
13 14 15 16 17 18 19      10 11 12 13 14 15 16      10 11 12 13 14 15 16
20 21 22 23 24 25 26      17 18 19 20 21 22 23      17 18 19 20 21 22 23
27 28 29 30 31            24 25 26 27 28            24 25 26 27 28 29 30
                                                    31

       April                      May                       June
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
    1  2  3  4  5  6                1  2  3  4                         1
 7  8  9 10 11 12 13       5  6  7  8  9 10 11       2  3  4  5  6  7  8
14 15 16 17 18 19 20      12 13 14 15 16 17 18       9 10 11 12 13 14 15
21 22 23 24 25 26 27      19 20 21 22 23 24 25      16 17 18 19 20 21 22
28 29 30                  26 27 28 29 30 31         23 24 25 26 27 28 29
                                                    30

        July                     August                  September
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
    1  2  3  4  5  6                   1  2  3       1  2  3  4  5  6  7
 7  8  9 10 11 12 13       4  5  6  7  8  9 10       8  9 10 11 12 13 14
14 15 16 17 18 19 20      11 12 13 14 15 16 17      15 16 17 18 19 20 21
21 22 23 24 25 26 27      18 19 20 21 22 23 24      22 23 24 25 26 27 28
28 29 30 31               25 26 27 28 29 30 31      29 30

      October                   November                  December
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
       1  2  3  4  5                      1  2       1  2  3  4  5  6  7
 6  7  8  9 10 11 12       3  4  5  6  7  8  9       8  9 10 11 12 13 14
13 14 15 16 17 18 19      10 11 12 13 14 15 16      15 16 17 18 19 20 21
20 21 22 23 24 25 26      17 18 19 20 21 22 23      22 23 24 25 26 27 28
27 28 29 30 31            24 25 26 27 28 29 30      29 30 31

空格的原因看上去像没对齐,看在源码框里的效果:

  1. 2023
  2. January February March
  3. Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
  4. 1 1 2 3 4 5 1 2 3 4 5
  5. 2 3 4 5 6 7 8 6 7 8 9 10 11 12 6 7 8 9 10 11 12
  6. 9 10 11 12 13 14 15 13 14 15 16 17 18 19 13 14 15 16 17 18 19
  7. 16 17 18 19 20 21 22 20 21 22 23 24 25 26 20 21 22 23 24 25 26
  8. 23 24 25 26 27 28 29 27 28 27 28 29 30 31
  9. 30 31
  10. April May June
  11. Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
  12. 1 2 1 2 3 4 5 6 7 1 2 3 4
  13. 3 4 5 6 7 8 9 8 9 10 11 12 13 14 5 6 7 8 9 10 11
  14. 10 11 12 13 14 15 16 15 16 17 18 19 20 21 12 13 14 15 16 17 18
  15. 17 18 19 20 21 22 23 22 23 24 25 26 27 28 19 20 21 22 23 24 25
  16. 24 25 26 27 28 29 30 29 30 31 26 27 28 29 30
  17. July August September
  18. Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
  19. 1 2 1 2 3 4 5 6 1 2 3
  20. 3 4 5 6 7 8 9 7 8 9 10 11 12 13 4 5 6 7 8 9 10
  21. 10 11 12 13 14 15 16 14 15 16 17 18 19 20 11 12 13 14 15 16 17
  22. 17 18 19 20 21 22 23 21 22 23 24 25 26 27 18 19 20 21 22 23 24
  23. 24 25 26 27 28 29 30 28 29 30 31 25 26 27 28 29 30
  24. 31
  25. October November December
  26. Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
  27. 1 1 2 3 4 5 1 2 3
  28. 2 3 4 5 6 7 8 6 7 8 9 10 11 12 4 5 6 7 8 9 10
  29. 9 10 11 12 13 14 15 13 14 15 16 17 18 19 11 12 13 14 15 16 17
  30. 16 17 18 19 20 21 22 20 21 22 23 24 25 26 18 19 20 21 22 23 24
  31. 23 24 25 26 27 28 29 27 28 29 30 25 26 27 28 29 30 31
  32. 30 31
  33. 2024
  34. January February March
  35. Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
  36. 1 2 3 4 5 6 7 1 2 3 4 1 2 3
  37. 8 9 10 11 12 13 14 5 6 7 8 9 10 11 4 5 6 7 8 9 10
  38. 15 16 17 18 19 20 21 12 13 14 15 16 17 18 11 12 13 14 15 16 17
  39. 22 23 24 25 26 27 28 19 20 21 22 23 24 25 18 19 20 21 22 23 24
  40. 29 30 31 26 27 28 29 25 26 27 28 29 30 31
  41. April May June
  42. Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
  43. 1 2 3 4 5 6 7 1 2 3 4 5 1 2
  44. 8 9 10 11 12 13 14 6 7 8 9 10 11 12 3 4 5 6 7 8 9
  45. 15 16 17 18 19 20 21 13 14 15 16 17 18 19 10 11 12 13 14 15 16
  46. 22 23 24 25 26 27 28 20 21 22 23 24 25 26 17 18 19 20 21 22 23
  47. 29 30 27 28 29 30 31 24 25 26 27 28 29 30
  48. July August September
  49. Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
  50. 1 2 3 4 5 6 7 1 2 3 4 1
  51. 8 9 10 11 12 13 14 5 6 7 8 9 10 11 2 3 4 5 6 7 8
  52. 15 16 17 18 19 20 21 12 13 14 15 16 17 18 9 10 11 12 13 14 15
  53. 22 23 24 25 26 27 28 19 20 21 22 23 24 25 16 17 18 19 20 21 22
  54. 29 30 31 26 27 28 29 30 31 23 24 25 26 27 28 29
  55. 30
  56. October November December
  57. Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
  58. 1 2 3 4 5 6 1 2 3 1
  59. 7 8 9 10 11 12 13 4 5 6 7 8 9 10 2 3 4 5 6 7 8
  60. 14 15 16 17 18 19 20 11 12 13 14 15 16 17 9 10 11 12 13 14 15
  61. 21 22 23 24 25 26 27 18 19 20 21 22 23 24 16 17 18 19 20 21 22
  62. 28 29 30 31 25 26 27 28 29 30 23 24 25 26 27 28 29
  63. 30 31
  64. 2025
  65. January February March
  66. Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
  67. 1 2 3 4 5 1 2 1 2
  68. 6 7 8 9 10 11 12 3 4 5 6 7 8 9 3 4 5 6 7 8 9
  69. 13 14 15 16 17 18 19 10 11 12 13 14 15 16 10 11 12 13 14 15 16
  70. 20 21 22 23 24 25 26 17 18 19 20 21 22 23 17 18 19 20 21 22 23
  71. 27 28 29 30 31 24 25 26 27 28 24 25 26 27 28 29 30
  72. 31
  73. April May June
  74. Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
  75. 1 2 3 4 5 6 1 2 3 4 1
  76. 7 8 9 10 11 12 13 5 6 7 8 9 10 11 2 3 4 5 6 7 8
  77. 14 15 16 17 18 19 20 12 13 14 15 16 17 18 9 10 11 12 13 14 15
  78. 21 22 23 24 25 26 27 19 20 21 22 23 24 25 16 17 18 19 20 21 22
  79. 28 29 30 26 27 28 29 30 31 23 24 25 26 27 28 29
  80. 30
  81. July August September
  82. Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
  83. 1 2 3 4 5 6 1 2 3 1 2 3 4 5 6 7
  84. 7 8 9 10 11 12 13 4 5 6 7 8 9 10 8 9 10 11 12 13 14
  85. 14 15 16 17 18 19 20 11 12 13 14 15 16 17 15 16 17 18 19 20 21
  86. 21 22 23 24 25 26 27 18 19 20 21 22 23 24 22 23 24 25 26 27 28
  87. 28 29 30 31 25 26 27 28 29 30 31 29 30
  88. October November December
  89. Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
  90. 1 2 3 4 5 1 2 1 2 3 4 5 6 7
  91. 6 7 8 9 10 11 12 3 4 5 6 7 8 9 8 9 10 11 12 13 14
  92. 13 14 15 16 17 18 19 10 11 12 13 14 15 16 15 16 17 18 19 20 21
  93. 20 21 22 23 24 25 26 17 18 19 20 21 22 23 22 23 24 25 26 27 28
  94. 27 28 29 30 31 24 25 26 27 28 29 30 29 30 31

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索
排行榜