From b931543508377c0e48a6801e4ea217eb523e2b03 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Tue, 13 Sep 2022 10:29:35 +0200 Subject: ... --- overlays/worktime/worktime.py | 58 +++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 22 deletions(-) (limited to 'overlays/worktime') diff --git a/overlays/worktime/worktime.py b/overlays/worktime/worktime.py index 9cfc6cd4..1fc00061 100755 --- a/overlays/worktime/worktime.py +++ b/overlays/worktime/worktime.py @@ -117,6 +117,7 @@ class Worktime(object): force_day_to_work = True leave_days = set() leave_budget = dict() + time_per_day = None @staticmethod def holidays(year): @@ -151,10 +152,10 @@ class Worktime(object): def __init__(self, start_datetime=None, end_datetime=None, now=None, include_running=True, force_day_to_work=True, **kwargs): self.include_running = include_running self.force_day_to_work = force_day_to_work - + if now: self.now = now - + config = Worktime.config() config_dir = BaseDirectory.load_first_config('worktime') api = TogglAPI(api_token=config['TOGGL']['ApiToken'], workspace_id=config['TOGGL']['Workspace']) @@ -174,17 +175,17 @@ class Worktime(object): except IOError as e: if e.errno != 2: raise e - + hours_per_week = float(config.get('WORKTIME', 'HoursPerWeek', fallback=40)) workdays = set([int(d.strip()) for d in config.get('WORKTIME', 'Workdays', fallback='1,2,3,4,5').split(',')]) - time_per_day = timedelta(hours = hours_per_week) / len(workdays) + self.time_per_day = timedelta(hours = hours_per_week) / len(workdays) holidays = dict() leave_per_year = int(config.get('WORKTIME', 'LeavePerYear', fallback=30)) for year in range(start_date.year, end_date.year + 1): - holidays |= {k: v * time_per_day for k, v in Worktime.holidays(year).items()} + holidays |= {k: v * self.time_per_day for k, v in Worktime.holidays(year).items()} leave_frac = 1 if date(year, 1, 1) < start_date.date(): leave_frac = (date(year + 1, 1, 1) - start_date.date()) / (date(year + 1, 1, 1) - date(year, 1, 1)) @@ -199,7 +200,7 @@ class Worktime(object): day = datetime.strptime(datestr, date_format).replace(tzinfo=tzlocal()).date() if day != start_date.date(): continue - + self.leave_budget[day.year] = (self.leave_budget[day.year] if day.year in self.leave_budget else 0) + int(count) except IOError as e: if e.errno != 2: @@ -224,7 +225,7 @@ class Worktime(object): toDay = parse_single(toDay) else: fromDay = toDay = parse_single(datestr) - time = time_per_day + time = self.time_per_day if len(splitLine) == 2: [hours, datestr] = splitLine time = timedelta(hours = float(hours)) @@ -236,7 +237,7 @@ class Worktime(object): if end_date.date() < day or day < start_date.date(): continue - if excused_kind == 'leave' and not (day in holidays and holidays[day] >= time_per_day) and day.isoweekday() in workdays: + if excused_kind == 'leave' and not (day in holidays and holidays[day] >= self.time_per_day) and day.isoweekday() in workdays: self.leave_days.add(day) holidays[day] = time except IOError as e: @@ -244,7 +245,7 @@ class Worktime(object): raise e pull_forward = dict() - + start_day = start_date.date() end_day = end_date.date() @@ -271,7 +272,7 @@ class Worktime(object): if not d == datetime.strptime(c, date_format).replace(tzinfo=tzlocal()).date(): break else: if d >= end_date.date(): - pull_forward[d] = min(timedelta(hours = float(hours)), time_per_day - (holidays[d] if d in holidays else timedelta())) + pull_forward[d] = min(timedelta(hours = float(hours)), self.time_per_day - (holidays[d] if d in holidays else timedelta())) except IOError as e: if e.errno != 2: raise e @@ -280,10 +281,10 @@ class Worktime(object): if pull_forward: end_day = max(end_day, max(list(pull_forward))) - + for day in [start_day + timedelta(days = x) for x in range(0, (end_day - start_day).days + 1)]: if day.isoweekday() in workdays: - time_to_work = time_per_day + time_to_work = self.time_per_day if day in holidays.keys(): time_to_work -= holidays[day] if time_to_work > timedelta(): @@ -302,7 +303,7 @@ class Worktime(object): day = datetime.strptime(datestr, date_format).replace(tzinfo=tzlocal()).date() extra_days_to_work[day] = timedelta(hours = float(hours)) else: - extra_days_to_work[datetime.strptime(stripped_line, date_format).replace(tzinfo=tzlocal()).date()] = time_per_day + extra_days_to_work[datetime.strptime(stripped_line, date_format).replace(tzinfo=tzlocal()).date()] = self.time_per_day except IOError as e: if e.errno != 2: raise e @@ -329,15 +330,15 @@ class Worktime(object): extra_day_time_left = timedelta() for extra_day in extra_days_forward: - day_time = max(timedelta(), time_per_day - extra_days_to_work[extra_day]) + day_time = max(timedelta(), self.time_per_day - extra_days_to_work[extra_day]) extra_day_time_left += day_time extra_day_time = min(extra_day_time_left, pull_forward[day]) time_forward = pull_forward[day] - extra_day_time if extra_day_time_left > timedelta(): for extra_day in extra_days_forward: - day_time = max(timedelta(), time_per_day - extra_days_to_work[extra_day]) + day_time = max(timedelta(), self.time_per_day - extra_days_to_work[extra_day]) extra_days_to_work[extra_day] += extra_day_time * (day_time / extra_day_time_left) - + hours_per_day_forward = time_forward / len(days_forward) if len(days_forward) > 0 else timedelta() days_forward.discard(end_date.date()) @@ -345,7 +346,7 @@ class Worktime(object): if end_date.date() in extra_days_to_work: self.time_pulled_forward += extra_days_to_work[end_date.date()] - + self.time_to_work += self.time_pulled_forward self.time_worked += api.get_billable_hours(start_date, self.now, rounding = config.getboolean('WORKTIME', 'rounding', fallback=True)) @@ -377,10 +378,10 @@ def worktime(**args): if total_minutes_difference >= 0: difference_string = difference_string(total_minutes_difference * timedelta(minutes = 1)) - return "{difference_string}/{clockout_time}".format(difference_string = difference_string, clockout_time = clockout_time.strftime("%H:%M")) + return f"{difference_string}/{clockout_time:%H:%M}" else: difference_string = difference_string(abs(total_minutes_difference) * timedelta(minutes = 1)) - return "{clockout_time}/{difference_string}".format(difference_string = difference_string, clockout_time = clockout_time.strftime("%H:%M")) + return f"{clockout_time:%H:%M}/{difference_string}" else: if worktime.running_entry: difference_string = difference_string(abs(total_minutes_difference) * timedelta(minutes = 1)) @@ -427,7 +428,20 @@ def time_worked(now, **args): if hours_difference == 0 or minutes_difference != 0: difference_string += f"{minutes_difference}m" - print(difference_string) + clockout_time = None + clockout_difference = None + if then.is_workday or now.is_workday: + target_time = max(then.time_per_day, now.time_per_day) if then.time_per_day and now.time_per_day else (then.time_per_day if then.time_per_day else now.time_per_day); + difference = target_time - worked + clockout_difference = 5 * ceil(difference / timedelta(minutes = 5)) + clockout_time = now.now + difference + clockout_time += (5 - clockout_time.minute % 5) * timedelta(minutes = 1) + clockout_time = clockout_time.replace(second = 0, microsecond = 0) + + if now.running_entry and clockout_time and clockout_difference >= 0: + print(f"{difference_string}/{clockout_time:%H:%M}") + else: + print(difference_string) else: print(worked) @@ -445,7 +459,7 @@ def holidays(year, **args): date_format = config.get('WORKTIME', 'DateFormat', fallback='%Y-%m-%d') table_data = [] - + holidays = Worktime.holidays(year) for k, v in holidays.items(): kstr = k.strftime(date_format) @@ -473,7 +487,7 @@ def leave(year, table, **args): break else: print(f'Unaccounted leave: {day}', file=stderr) - + if table: table_data = [] for year, days in leave_budget.items(): -- cgit v1.2.3