-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcal.py
More file actions
executable file
·136 lines (112 loc) · 3.58 KB
/
Copy pathcal.py
File metadata and controls
executable file
·136 lines (112 loc) · 3.58 KB
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/env python
#
# cal.py
# ------
# Copyright (c) 2017 Chandranath Gunjal. Available under the MIT License
#
# A friendlier cal - converts month names.
#
# o With no arguments, print calendar for current month & year
# o With two arguments, assumes month & year are given
# o With one argument
# - the argument is assumed to be a month (if valid) for this year.
# - a "month+/-" format uses the next/prev year.
# - a lone "+/-" prints the next/prev month's calendar.
# - a leading zero forces the argument to be a "year".
#
import calendar
import datetime
import getopt
import sys
def month2num(given: str) -> int:
"""Convert a given month name to numeric"""
month_names = [
"january",
"february",
"march",
"april",
"may",
"june",
"july",
"august",
"september",
"october",
"november",
"december",
]
given = given.lower()
for i, month in enumerate(month_names, 1):
if month.startswith(given):
return i
return 0
def determine_year_month(args: list) -> list[int]:
"""Determine the year/month. Returns [year] or [year, month]"""
today = datetime.date.today()
cur_month, cur_year = today.month, today.year
# 0 args - calendar for current year & month
if len(args) == 0:
return [cur_year, cur_month]
# 2 args - calendar for given year & month
if len(args) == 2:
m = month2num(args[0])
return [int(args[1]), int(args[0])] if (m == 0) else [int(args[1]), m]
# 1 argument - multiple possibilities
arg = args[0]
# cal + ==> next month
if arg == "+":
return [cur_year + 1, 1] if (cur_month == 12) else [cur_year, cur_month + 1]
# cal - ==> prev month
if arg == "-":
return [cur_year - 1, 12] if (cur_month == 1) else [cur_year, cur_month - 1]
# cal jun+ or cal 12+ ==> given month for next year
if arg.endswith("+"):
m = month2num(arg[:-1])
return [cur_year + 1, int(arg[:-1])] if (m == 0) else [cur_year + 1, m]
# cal jun- or cal 12- ==> given month for prev year
if arg.endswith("-"):
m = month2num(arg[:-1])
return [cur_year - 1, int(arg[:-1])] if (m == 0) else [cur_year - 1, m]
# cal 0nn ==> assume as year
if arg.startswith("0"):
return [int(arg)]
# cal numeric ==> assume as month if in 1..12
if arg.isnumeric():
m = int(arg)
return [cur_year, m] if (1 <= m <= 12) else [m]
# cal any ==> convert month if possible
m = month2num(arg)
return [int(arg)] if (m == 0) else [cur_year, m]
def print_calendar(ym: list[int]) -> None:
"""Print calendar for [year, month]."""
tc = calendar.TextCalendar(firstweekday=6)
tc.pryear(ym[0]) if len(ym) == 1 else tc.prmonth(ym[0], ym[1])
return
# Main
# ====
if __name__ == "__main__":
synopsis = """usage: cal.py -h [mth][+|-] | mth year | [0]year
Month names (shortened or otherwise) can be used.
"""
def usage():
"""Print usage and exit"""
print(synopsis)
sys.exit(2)
def parse_args(argv):
"""Parse command line arguments"""
try:
opts, args = getopt.getopt(argv, "h", ["help"])
except getopt.GetoptError:
usage()
for opt, arg in opts:
if opt in ["-h", "--help"]:
usage()
if len(args) > 2:
usage()
return args
# main
cmd_args = parse_args(sys.argv[1:])
try:
ym = determine_year_month(cmd_args)
print_calendar(ym)
except Exception:
usage()