summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2021-03-31 18:12:12 +0200
committerGregor Kleen <gkleen@yggdrasil.li>2021-03-31 18:12:12 +0200
commita58b96622154b0dc341c77e0f6229e16313e0c6c (patch)
tree5a954bc633f09a5f5658928bc8654f158c13fdf7
parent6076eacd2a783c0f80a801fbf8a6f65ca7f01dcd (diff)
downloadnixos-a58b96622154b0dc341c77e0f6229e16313e0c6c.tar
nixos-a58b96622154b0dc341c77e0f6229e16313e0c6c.tar.gz
nixos-a58b96622154b0dc341c77e0f6229e16313e0c6c.tar.bz2
nixos-a58b96622154b0dc341c77e0f6229e16313e0c6c.tar.xz
nixos-a58b96622154b0dc341c77e0f6229e16313e0c6c.zip
worktime holidays
-rw-r--r--overlays/worktime/default.nix2
-rwxr-xr-xoverlays/worktime/worktime.py68
2 files changed, 51 insertions, 19 deletions
diff --git a/overlays/worktime/default.nix b/overlays/worktime/default.nix
index 26e1dfed..ab6fb40a 100644
--- a/overlays/worktime/default.nix
+++ b/overlays/worktime/default.nix
@@ -5,7 +5,7 @@ final: prev: {
5 5
6 phases = [ "buildPhase" "installPhase" ]; 6 phases = [ "buildPhase" "installPhase" ];
7 7
8 python = prev.python37.withPackages (ps: with ps; [pyxdg dateutil uritools requests configparser]); 8 python = prev.python39.withPackages (ps: with ps; [pyxdg dateutil uritools requests configparser tabulate]);
9 9
10 buildPhase = '' 10 buildPhase = ''
11 substituteAll $src worktime 11 substituteAll $src worktime
diff --git a/overlays/worktime/worktime.py b/overlays/worktime/worktime.py
index 9e514e65..b9af430a 100755
--- a/overlays/worktime/worktime.py
+++ b/overlays/worktime/worktime.py
@@ -22,6 +22,10 @@ import argparse
22 22
23from copy import deepcopy 23from copy import deepcopy
24 24
25import sys
26
27from tabulate import tabulate
28
25class TogglAPISection(Enum): 29class TogglAPISection(Enum):
26 TOGGL = '/api/v8' 30 TOGGL = '/api/v8'
27 REPORTS = '/reports/api/v2' 31 REPORTS = '/reports/api/v2'
@@ -100,6 +104,36 @@ class Worktime(object):
100 time_to_work = None 104 time_to_work = None
101 force_day_to_work = True 105 force_day_to_work = True
102 106
107 @staticmethod
108 def holidays(year):
109 holidays = dict()
110
111 y_easter = datetime.combine(easter(year), time(), tzinfo=tzlocal())
112
113 # Legal holidays in munich, bavaria
114 holidays[datetime(year, 1, 1, tzinfo=tzlocal()).date()] = 1
115 holidays[datetime(year, 1, 6, tzinfo=tzlocal()).date()] = 1
116 holidays[(y_easter+timedelta(days=-2)).date()] = 1
117 holidays[(y_easter+timedelta(days=+1)).date()] = 1
118 holidays[datetime(year, 5, 1, tzinfo=tzlocal()).date()] = 1
119 holidays[(y_easter+timedelta(days=+39)).date()] = 1
120 holidays[(y_easter+timedelta(days=+50)).date()] = 1
121 holidays[(y_easter+timedelta(days=+60)).date()] = 1
122 holidays[datetime(year, 8, 15, tzinfo=tzlocal()).date()] = 1
123 holidays[datetime(year, 10, 3, tzinfo=tzlocal()).date()] = 1
124 holidays[datetime(year, 11, 1, tzinfo=tzlocal()).date()] = 1
125 holidays[datetime(year, 12, 25, tzinfo=tzlocal()).date()] = 1
126 holidays[datetime(year, 12, 26, tzinfo=tzlocal()).date()] = 1
127
128 return holidays
129
130 @staticmethod
131 def config():
132 config = configparser.ConfigParser()
133 config_dir = BaseDirectory.load_first_config('worktime')
134 config.read(f"{config_dir}/worktime.ini")
135 return config
136
103 def __init__(self, start_datetime=None, end_datetime=None, now=None, include_running=True, force_day_to_work=True, **kwargs): 137 def __init__(self, start_datetime=None, end_datetime=None, now=None, include_running=True, force_day_to_work=True, **kwargs):
104 self.include_running = include_running 138 self.include_running = include_running
105 self.force_day_to_work = force_day_to_work 139 self.force_day_to_work = force_day_to_work
@@ -107,9 +141,8 @@ class Worktime(object):
107 if now: 141 if now:
108 self.now = now 142 self.now = now
109 143
110 config = configparser.ConfigParser() 144 config = Worktime.config()
111 config_dir = BaseDirectory.load_first_config('worktime') 145 config_dir = BaseDirectory.load_first_config('worktime')
112 config.read(f"{config_dir}/worktime.ini")
113 api = TogglAPI(api_token=config['TOGGL']['ApiToken'], workspace_id=config['TOGGL']['Workspace']) 146 api = TogglAPI(api_token=config['TOGGL']['ApiToken'], workspace_id=config['TOGGL']['Workspace'])
114 date_format = config.get('WORKTIME', 'DateFormat', fallback='%Y-%m-%d') 147 date_format = config.get('WORKTIME', 'DateFormat', fallback='%Y-%m-%d')
115 148
@@ -136,22 +169,7 @@ class Worktime(object):
136 holidays = dict() 169 holidays = dict()
137 170
138 for year in range(start_date.year, end_date.year + 1): 171 for year in range(start_date.year, end_date.year + 1):
139 y_easter = datetime.combine(easter(year), time(), tzinfo=tzlocal()) 172 holidays |= {k: v * time_per_day for k, v in Worktime.holidays(year).items()}
140
141 # Legal holidays in munich, bavaria
142 holidays[datetime(year, 1, 1, tzinfo=tzlocal()).date()] = time_per_day
143 holidays[datetime(year, 1, 6, tzinfo=tzlocal()).date()] = time_per_day
144 holidays[(y_easter+timedelta(days=-2)).date()] = time_per_day
145 holidays[(y_easter+timedelta(days=+1)).date()] = time_per_day
146 holidays[datetime(year, 5, 1, tzinfo=tzlocal()).date()] = time_per_day
147 holidays[(y_easter+timedelta(days=+39)).date()] = time_per_day
148 holidays[(y_easter+timedelta(days=+50)).date()] = time_per_day
149 holidays[(y_easter+timedelta(days=+60)).date()] = time_per_day
150 holidays[datetime(year, 8, 15, tzinfo=tzlocal()).date()] = time_per_day
151 holidays[datetime(year, 10, 3, tzinfo=tzlocal()).date()] = time_per_day
152 holidays[datetime(year, 11, 1, tzinfo=tzlocal()).date()] = time_per_day
153 holidays[datetime(year, 12, 25, tzinfo=tzlocal()).date()] = time_per_day
154 holidays[datetime(year, 12, 26, tzinfo=tzlocal()).date()] = time_per_day
155 173
156 try: 174 try:
157 with open(f"{config_dir}/excused", 'r') as excused: 175 with open(f"{config_dir}/excused", 'r') as excused:
@@ -365,7 +383,19 @@ def diff(now, **args):
365 now = Worktime(**dict(args, now = now, include_running = False)) 383 now = Worktime(**dict(args, now = now, include_running = False))
366 384
367 print(now.time_to_work - then.time_to_work) 385 print(now.time_to_work - then.time_to_work)
386
387def holidays(now, **args):
388 config = Worktime.config()
389 date_format = config.get('WORKTIME', 'DateFormat', fallback='%Y-%m-%d')
390
391 table_data = []
368 392
393 holidays = Worktime.holidays(now.year)
394 for k, v in holidays.items():
395 kstr = k.strftime(date_format)
396
397 table_data += [[kstr, v]]
398 print(tabulate(table_data, tablefmt="plain"))
369 399
370def main(): 400def main():
371 parser = argparse.ArgumentParser(prog = "worktime", description = 'Track worktime using toggl API') 401 parser = argparse.ArgumentParser(prog = "worktime", description = 'Track worktime using toggl API')
@@ -379,6 +409,8 @@ def main():
379 time_worked_parser.set_defaults(cmd = time_worked) 409 time_worked_parser.set_defaults(cmd = time_worked)
380 diff_parser = subparsers.add_parser('diff') 410 diff_parser = subparsers.add_parser('diff')
381 diff_parser.set_defaults(cmd = diff) 411 diff_parser.set_defaults(cmd = diff)
412 holidays_parser = subparsers.add_parser('holidays')
413 holidays_parser.set_defaults(cmd = holidays)
382 args = parser.parse_args() 414 args = parser.parse_args()
383 415
384 args.cmd(**vars(args)) 416 args.cmd(**vars(args))