def write_line(file_path: str, date_string: str): file_match = re.match("^[1-2][0-9]{3}-[0-2][0-9]\.txt", os.path.basename(file_path)) if not file_match: raise errors.ReportError( "File name is not a month file: \"{}\"".format(file_path)) date_match = re.match("^\s*(\d+)\.\s+.*$", date_string) if not date_match: raise errors.ReportError( "Bad report string: \"{}\"".format(date_string)) date = date_match.group(1) date_string = date_string.strip() if os.path.exists(file_path): with open(file_path, 'r') as text_file: lines = text_file.readlines() lines = [l.rstrip("\n") for l in lines if l.rstrip()] else: lines = [] if lines and lines[-1].startswith(date + "."): lines[-1] = date_string else: lines.append(date_string) lines = "\n".join(lines) with open(file_path, 'w') as text_file: text_file.write(lines)
def add_day(self, date_string: str) -> Day: new_day = Day(date_string) if new_day.date.year != self.year or new_day.date.month != self.month: raise errors.ReportError("New date string didn't match month. " "{}-{:02d} doesn't include {}.".format( self.year, self.month, date_string)) for old_day in self.days: if new_day.date == old_day.date: raise errors.ReportError( "Date 2014-09-02 already added to month.") if not old_day.complete(): raise errors.ReportError("New days can't be added while the " "report for a previous day is " "incomplete.") next_workday = datetime.strptime(self.next_workday(), "%Y-%m-%d").date() if new_day.date > next_workday: raise errors.ReportError( "New work days must be added consecutively. Expected {}, got " "{}.".format(self.next_workday(), date_string)) if date_string in self.holidays: new_day.day_type = DayType.holiday new_day.info = self.holidays[date_string] self.days.append(new_day) return new_day
def report_deviation(self, deviation: str): match = re.match("^(\d{1,2})(?::(\d{2}))?$", deviation) if match: self.deviation = timedelta( hours=int(match.group(1)), minutes=int(match.group(2) or 0)) else: raise errors.ReportError("Bad deviation for date {}: '{}'".format( self.date, deviation))
def report_lunch_duration(self, lunch_duration: str): if self.start_time is None: raise errors.ReportError( "Date {} must have a start time before a lunch duration can " "be reported.".format(self.date.isoformat())) if self.lunch_duration is not None: raise errors.ReportError("Date {} allready has a lunch duration." .format(self.date.isoformat())) match = re.match("^(\d{1,2})(?::(\d{2}))?$", lunch_duration) if match: self.lunch_duration = timedelta( hours=int(match.group(1)), minutes=int(match.group(2) or 0)) else: raise errors.ReportError( "Bad lunch duration for date {}: '{}'".format(self.date, lunch_duration))
def archive_month(self, month: month.Month): for old_month in self.months: if old_month.year == month.year and old_month.month == month.month: raise errors.ReportError( "Month {}-{} is allready archived.".format( month.year, month.month)) date_string = "{}-{:02d}".format(month.year, month.month) if self.next_month() != "" and date_string != self.next_month(): raise errors.ReportError( "Months must be archived sequentially. Expected {}, got " "{}-{:02d}.".format(self.next_month(), month.year, month.month)) if not month.complete(): raise errors.ReportError("Month still has unreported workdays and " "can't be archived.") self.months.append(month)
def report_end_time(self, end_time: str): if self.start_time is None: raise errors.ReportError( "Date {} must have a start time before an end time can be " "reported.".format(self.date.isoformat())) if self.lunch_duration is None: raise errors.ReportError( "Date {} must have a lunch duration before an end time can be " "reported.".format(self.date.isoformat())) try: end_time = datetime.strptime( end_time, "%H:%M").time() except TypeError: raise TypeError("Given end time must be a string.") except ValueError: raise errors.BadTimeError("Bad end time: \"{}\"".format(end_time)) self.end_time = datetime.combine(self.date, end_time)
def report_start_time(self, start_time: str): if self.start_time is not None: raise errors.ReportError("Date {} allready has a start time." .format(self.date.isoformat())) try: start_time = datetime.strptime( start_time, "%H:%M").time() except ValueError: raise errors.BadTimeError( "Bad start time: \"{}\".".format(start_time)) self.start_time = datetime.combine(self.date, start_time)
def add_day(self, date_string: str) -> day.Day: new_day = day.Day(date_string) if new_day.date.year != self.year: raise errors.ReportError( "New date string didn't match year. {} doesn't include {}.". format(self.year, date_string)) if self.next_workday()[:7] == self.next_month(): new_month = month.Month(self.next_month()) for date, name in self.holidays[self.next_month()].items(): new_month.add_holiday(date, name) self.months.append(new_month) day_1 = self.months[-1].add_day(date_string) return day_1