77
88import sys
99import datetime
10+ from enum import IntEnum , global_enum
1011import locale as _locale
1112from itertools import repeat
13+ import warnings
1214
1315__all__ = ["IllegalMonthError" , "IllegalWeekdayError" , "setfirstweekday" ,
1416 "firstweekday" , "isleap" , "leapdays" , "weekday" , "monthrange" ,
1517 "monthcalendar" , "prmonth" , "month" , "prcal" , "calendar" ,
1618 "timegm" , "month_name" , "month_abbr" , "day_name" , "day_abbr" ,
1719 "Calendar" , "TextCalendar" , "HTMLCalendar" , "LocaleTextCalendar" ,
1820 "LocaleHTMLCalendar" , "weekheader" ,
21+ "Day" , "Month" , "JANUARY" , "FEBRUARY" , "MARCH" ,
22+ "APRIL" , "MAY" , "JUNE" , "JULY" ,
23+ "AUGUST" , "SEPTEMBER" , "OCTOBER" , "NOVEMBER" , "DECEMBER" ,
1924 "MONDAY" , "TUESDAY" , "WEDNESDAY" , "THURSDAY" , "FRIDAY" ,
2025 "SATURDAY" , "SUNDAY" ]
2126
@@ -37,9 +42,46 @@ def __str__(self):
3742 return "bad weekday number %r; must be 0 (Monday) to 6 (Sunday)" % self .weekday
3843
3944
40- # Constants for months referenced later
41- January = 1
42- February = 2
45+ def __getattr__ (name ):
46+ if name in ('January' , 'February' ):
47+ warnings .warn (f"The '{ name } ' attribute is deprecated, use '{ name .upper ()} ' instead" ,
48+ DeprecationWarning , stacklevel = 2 )
49+ if name == 'January' :
50+ return 1
51+ else :
52+ return 2
53+
54+ raise AttributeError (f"module '{ __name__ } ' has no attribute '{ name } '" )
55+
56+
57+ # Constants for months
58+ @global_enum
59+ class Month (IntEnum ):
60+ JANUARY = 1
61+ FEBRUARY = 2
62+ MARCH = 3
63+ APRIL = 4
64+ MAY = 5
65+ JUNE = 6
66+ JULY = 7
67+ AUGUST = 8
68+ SEPTEMBER = 9
69+ OCTOBER = 10
70+ NOVEMBER = 11
71+ DECEMBER = 12
72+
73+
74+ # Constants for days
75+ @global_enum
76+ class Day (IntEnum ):
77+ MONDAY = 0
78+ TUESDAY = 1
79+ WEDNESDAY = 2
80+ THURSDAY = 3
81+ FRIDAY = 4
82+ SATURDAY = 5
83+ SUNDAY = 6
84+
4385
4486# Number of days per month (except for February in leap years)
4587mdays = [0 , 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ]
@@ -95,9 +137,6 @@ def __len__(self):
95137month_name = _localized_month ('%B' )
96138month_abbr = _localized_month ('%b' )
97139
98- # Constants for weekdays
99- (MONDAY , TUESDAY , WEDNESDAY , THURSDAY , FRIDAY , SATURDAY , SUNDAY ) = range (7 )
100-
101140
102141def isleap (year ):
103142 """Return True for leap years, False for non-leap years."""
@@ -116,7 +155,7 @@ def weekday(year, month, day):
116155 """Return weekday (0-6 ~ Mon-Sun) for year, month (1-12), day (1-31)."""
117156 if not datetime .MINYEAR <= year <= datetime .MAXYEAR :
118157 year = 2000 + year % 400
119- return datetime .date (year , month , day ).weekday ()
158+ return Day ( datetime .date (year , month , day ).weekday () )
120159
121160
122161def monthrange (year , month ):
@@ -125,12 +164,12 @@ def monthrange(year, month):
125164 if not 1 <= month <= 12 :
126165 raise IllegalMonthError (month )
127166 day1 = weekday (year , month , 1 )
128- ndays = mdays [month ] + (month == February and isleap (year ))
167+ ndays = mdays [month ] + (month == FEBRUARY and isleap (year ))
129168 return day1 , ndays
130169
131170
132171def _monthlen (year , month ):
133- return mdays [month ] + (month == February and isleap (year ))
172+ return mdays [month ] + (month == FEBRUARY and isleap (year ))
134173
135174
136175def _prevmonth (year , month ):
@@ -260,10 +299,7 @@ def yeardatescalendar(self, year, width=3):
260299 Each month contains between 4 and 6 weeks and each week contains 1-7
261300 days. Days are datetime.date objects.
262301 """
263- months = [
264- self .monthdatescalendar (year , i )
265- for i in range (January , January + 12 )
266- ]
302+ months = [self .monthdatescalendar (year , m ) for m in Month ]
267303 return [months [i :i + width ] for i in range (0 , len (months ), width ) ]
268304
269305 def yeardays2calendar (self , year , width = 3 ):
@@ -273,10 +309,7 @@ def yeardays2calendar(self, year, width=3):
273309 (day number, weekday number) tuples. Day numbers outside this month are
274310 zero.
275311 """
276- months = [
277- self .monthdays2calendar (year , i )
278- for i in range (January , January + 12 )
279- ]
312+ months = [self .monthdays2calendar (year , m ) for m in Month ]
280313 return [months [i :i + width ] for i in range (0 , len (months ), width ) ]
281314
282315 def yeardayscalendar (self , year , width = 3 ):
@@ -285,10 +318,7 @@ def yeardayscalendar(self, year, width=3):
285318 yeardatescalendar()). Entries in the week lists are day numbers.
286319 Day numbers outside this month are zero.
287320 """
288- months = [
289- self .monthdayscalendar (year , i )
290- for i in range (January , January + 12 )
291- ]
321+ months = [self .monthdayscalendar (year , m ) for m in Month ]
292322 return [months [i :i + width ] for i in range (0 , len (months ), width ) ]
293323
294324
@@ -509,7 +539,7 @@ def formatyear(self, theyear, width=3):
509539 a ('\n ' )
510540 a ('<tr><th colspan="%d" class="%s">%s</th></tr>' % (
511541 width , self .cssclass_year_head , theyear ))
512- for i in range (January , January + 12 , width ):
542+ for i in range (JANUARY , JANUARY + 12 , width ):
513543 # months in this row
514544 months = range (i , min (i + width , 13 ))
515545 a ('<tr>' )
@@ -693,7 +723,7 @@ def main(args):
693723 parser .add_argument (
694724 "-L" , "--locale" ,
695725 default = None ,
696- help = "locale to be used from month and weekday names"
726+ help = "locale to use for month and weekday names"
697727 )
698728 parser .add_argument (
699729 "-e" , "--encoding" ,
0 commit comments