-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdetail.py
More file actions
162 lines (124 loc) · 4.37 KB
/
Copy pathdetail.py
File metadata and controls
162 lines (124 loc) · 4.37 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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import sys
import calendar
import datetime as dt
import re
from typing import List, Optional, Union
from terminal import *
from file import *
def get_month_abbr_len() -> int:
"""Calculate the number of characters we need to display the month
abbreviated name. It depends on the locale.
"""
return max(len(calendar.month_abbr[i]) for i in range(1, 13)) + 1
def week_number(date: dt.date) -> int:
"""return iso week number for dt.date object
:param date: date
:return: weeknumber
"""
return dt.date.isocalendar(date)[1]
def timedelta_format(td: dt.timedelta) -> str:
seconds = td.total_seconds()
minutes = abs(seconds / 60)
hours = int(minutes / 60)
minutes = abs(int(minutes - (hours * 60)))
out = ""
if td < dt.timedelta(0):
out += "-"
out += str(abs(hours)).rjust(2) + "h " + str(minutes).rjust(2) + "min"
return out
def str_week(
week: List[dt.date],
month: int,
today: dt.date,
data,
locale=None,
) -> str:
# strweek = str(week_number(week[1])).rjust(3) + ": "
strweek = ""
week_sum = dt.timedelta(0)
week_sum_expected = dt.timedelta(0)
cal = calendar.Calendar(0)
for day in week:
week_sum += data.getActual(day)
week_sum_expected += data.getExpected(day)
bg = None
fg = None
if day.weekday() >= 5:
# saturday or sunday
fg = 'dark blue'
if data.isHoliday(day):
# holidays are red (and have priority over sat/sun)
fg = "light red"
if not data.isInWorkTime(day):
# if the day is before the begin of the work contract -> gray
fg = "dark gray"
if data.isVacation(day):
fg = "light green"
# apply colors
day_str = colored(str(day.day).rjust(2), fg, bg)
# add format
day_str = day_str + " " + timedelta_format(data.getActual(day))
if(data.getExpected(day) > dt.timedelta(0)):
percentage_today = f"({data.getActual(day) / data.getExpected(day) * 100:.0f}%)".rjust(6)
day_str += " " + percentage_today
# if today, reverse the colors
if day == today:
day_str = reverse(day_str) # custom styling for today
# one space between days
strweek += day_str + '\n'
if week_sum_expected == dt.timedelta(0):
# if no work is expected in this week, hide the time overview
pass
else:
completeness = f"{week_sum / week_sum_expected * 100:.0f}".rjust(3)
# strweek += " " + timedelta_format(week_sum) + " / " + timedelta_format(work_per_week) + f" ({completeness}%)"
strweek += " " + timedelta_format(week_sum) + f" ({completeness}%) " + timedelta_format(week_sum - week_sum_expected)
return strweek
def str_vertical_month(
start: dt.date,
end: dt.date
) -> str:
# first week day = 0 = monday
cal = calendar.Calendar(0)
month_abbr_len = get_month_abbr_len()
# load stored data
data = DataFile()
out = []
today = dt.date.today()
month = start.month
new_month = True
while start <= end:
year = start.year
for week in cal.monthdatescalendar(year, month):
if not start in week:
continue
week_str = str_week(week, month, today, data=data)
if new_month:
mon_str = calendar.month_abbr[month].ljust(month_abbr_len) + "\n"
new_month = False
else:
mon_str = " " * month_abbr_len
line = bold(mon_str) + "\n" + week_str
out.append(line)
start += dt.timedelta(days=7)
if month != start.month:
new_month = True
month = start.month
return "\n".join(out)
def main():
today = dt.date.today()
start = today
end = today
if len(sys.argv) >= 2:
regex = re.compile("(-?[0-9]+)?:(-?[0-9]+)?")
matcher = regex.match(sys.argv[1])
if matcher != None:
if matcher.group(1) != None:
# offset the start by the number of weeks
start = start + dt.timedelta(days=7*int(matcher.group(1)))
if matcher.group(2) != None:
# offset the end by the number of weeks
end = end + dt.timedelta(days=7*int(matcher.group(2)))
print(str_vertical_month(start, end))
if __name__ == '__main__':
main()