From 793667291457380a0341f2ce7f3d25934de56b5b Mon Sep 17 00:00:00 2001 From: matin Date: Mon, 21 Apr 2025 18:06:36 +0200 Subject: first try to add commentary and save functionalities by Claude --- date_calculator.py | 306 ++++++++++++++++++++++++++--------------------------- 1 file changed, 153 insertions(+), 153 deletions(-) (limited to 'date_calculator.py') diff --git a/date_calculator.py b/date_calculator.py index e6c20fc..402a58c 100644 --- a/date_calculator.py +++ b/date_calculator.py @@ -1,154 +1,154 @@ -# date_calculator.py -from datetime import datetime, timedelta -from dateutil.relativedelta import relativedelta -import math - -class DateCalculator: - @staticmethod - def truncate_periods(periods, launch, prediction): - considered_periods = [] - for start, end, id in periods: - # print(start) - # print(launch) - truncated_start = max(start, launch) - truncated_end = min(end, prediction) - if truncated_start <= end and truncated_start <= prediction: - considered_periods.append((truncated_start, truncated_end, id)) - return considered_periods - - @staticmethod - def round_periods(periods): - rounded_periods = [] - total_months = 0 - - for start, end, id in periods: - year_diff = end.year - start.year - month_diff = end.month - start.month - months = year_diff * 12 + month_diff - if end.day >= start.day: - months += 1 - rounded_end = start + relativedelta(months=months) - timedelta(days=1) - - rounded_periods.append((start, rounded_end, id)) - total_months += months - - return rounded_periods, total_months - - @staticmethod - def merge_periods(periods): - if not periods: - return [] - - periods.sort() - merged_periods = [] - - current_start, current_end, current_id = periods[0] - - for start, end, id in periods[1:]: - if start <= current_end + timedelta(days=1): - current_end = max(current_end, end) - else: - merged_periods.append((current_start, current_end, current_id)) - current_start, current_end, current_id = start, end, id - - merged_periods.append((current_start, current_end, current_id)) - - return merged_periods - - @staticmethod - def find_non_overlapping_periods(existing_periods, test_period): - existing_periods.sort(key=lambda x: x[0]) - - test_start, test_end, id = test_period - non_overlapping_periods = [] - - for start, end, _ in existing_periods: - if test_end < start: - non_overlapping_periods.append((test_start, test_end, id)) - return non_overlapping_periods - - elif test_start > end: - continue - - else: - if test_start < start: - non_overlapping_periods.append((test_start, start - timedelta(days=1), id)) - - test_start = end + timedelta(days=1) - - if test_start <= test_end: - non_overlapping_periods.append((test_start, test_end, id)) - - return non_overlapping_periods - - def calculate_prediction(self, launch_date, duration, **kwargs): - total_days = 0 - total_months = 0 - updated = True - prediction_start = launch_date + duration - timedelta(days = 1) - prediction = prediction_start - - events = [] - half_projects = [] - full_projects = [] - other_kwargs = {} - - for k, v in kwargs.items(): - if k == "event": - events.extend(v) - elif k == "half_project": - half_projects.extend(v) - elif k == "full_project": - full_projects.extend(v) - elif k == "two_years": - full_projects.extend(v) - else: - other_kwargs[k] = v - - while updated: - updated = False - considered_events = self.truncate_periods(events, launch_date, prediction) - considered_full_projects = self.truncate_periods(full_projects, launch_date, prediction) - considered_half_projects = self.truncate_periods(half_projects, launch_date, prediction) - - considered_full_projects_merged = self.merge_periods(considered_full_projects) - considered_full_projects_rounded, months = self.round_periods(considered_full_projects_merged) - considered_full_projects_merged2 = self.merge_periods(considered_full_projects_rounded) - considered_full_projects_rounded2, months = self.round_periods(considered_full_projects_merged2) - - non_overlapping_half_projects = [] - for test_interval in considered_half_projects: - non_overlapping_half_projects.extend( - self.find_non_overlapping_periods(considered_full_projects_rounded2, test_interval) - ) - - considered_half_projects_merged = self.merge_periods(non_overlapping_half_projects) - considered_half_projects_rounded, months2 = self.round_periods(considered_half_projects_merged) - considered_half_projects_merged2 = self.merge_periods(considered_half_projects_rounded) - considered_half_projects_rounded2, months2 = self.round_periods(considered_half_projects_merged2) - - all_projects_merged = self.merge_periods( - considered_full_projects_rounded2 + considered_half_projects_rounded2 - ) - merged_event_periods = self.merge_periods(considered_events) - - non_overlapping_event_periods = [] - for test_interval in merged_event_periods: - non_overlapping_event_periods.extend( - self.find_non_overlapping_periods(all_projects_merged, test_interval) - ) - - new_total_months = months + math.ceil(months2 / 2) - new_total_days = sum((end - start).days + 1 for start, end, _ in non_overlapping_event_periods) - - if new_total_days != total_days or new_total_months != total_months: - total_days = new_total_days - total_months = new_total_months - updated = True - prediction = launch_date + duration + relativedelta(months=total_months) + timedelta(days=total_days-1) - - # print(prediction, prediction_start + relativedelta(years = 6)) - if prediction > prediction_start + relativedelta(years = 6): - prediction = prediction_start + relativedelta(years = 6) - +# date_calculator.py +from datetime import datetime, timedelta +from dateutil.relativedelta import relativedelta +import math + +class DateCalculator: + @staticmethod + def truncate_periods(periods, launch, prediction): + considered_periods = [] + for start, end, id in periods: + # print(start) + # print(launch) + truncated_start = max(start, launch) + truncated_end = min(end, prediction) + if truncated_start <= end and truncated_start <= prediction: + considered_periods.append((truncated_start, truncated_end, id)) + return considered_periods + + @staticmethod + def round_periods(periods): + rounded_periods = [] + total_months = 0 + + for start, end, id in periods: + year_diff = end.year - start.year + month_diff = end.month - start.month + months = year_diff * 12 + month_diff + if end.day >= start.day: + months += 1 + rounded_end = start + relativedelta(months=months) - timedelta(days=1) + + rounded_periods.append((start, rounded_end, id)) + total_months += months + + return rounded_periods, total_months + + @staticmethod + def merge_periods(periods): + if not periods: + return [] + + periods.sort() + merged_periods = [] + + current_start, current_end, current_id = periods[0] + + for start, end, id in periods[1:]: + if start <= current_end + timedelta(days=1): + current_end = max(current_end, end) + else: + merged_periods.append((current_start, current_end, current_id)) + current_start, current_end, current_id = start, end, id + + merged_periods.append((current_start, current_end, current_id)) + + return merged_periods + + @staticmethod + def find_non_overlapping_periods(existing_periods, test_period): + existing_periods.sort(key=lambda x: x[0]) + + test_start, test_end, id = test_period + non_overlapping_periods = [] + + for start, end, _ in existing_periods: + if test_end < start: + non_overlapping_periods.append((test_start, test_end, id)) + return non_overlapping_periods + + elif test_start > end: + continue + + else: + if test_start < start: + non_overlapping_periods.append((test_start, start - timedelta(days=1), id)) + + test_start = end + timedelta(days=1) + + if test_start <= test_end: + non_overlapping_periods.append((test_start, test_end, id)) + + return non_overlapping_periods + + def calculate_prediction(self, launch_date, duration, **kwargs): + total_days = 0 + total_months = 0 + updated = True + prediction_start = launch_date + duration - timedelta(days = 1) + prediction = prediction_start + + events = [] + half_projects = [] + full_projects = [] + other_kwargs = {} + + for k, v in kwargs.items(): + if k == "event": + events.extend(v) + elif k == "half_project": + half_projects.extend(v) + elif k == "full_project": + full_projects.extend(v) + elif k == "two_years": + full_projects.extend(v) + else: + other_kwargs[k] = v + + while updated: + updated = False + considered_events = self.truncate_periods(events, launch_date, prediction) + considered_full_projects = self.truncate_periods(full_projects, launch_date, prediction) + considered_half_projects = self.truncate_periods(half_projects, launch_date, prediction) + + considered_full_projects_merged = self.merge_periods(considered_full_projects) + considered_full_projects_rounded, months = self.round_periods(considered_full_projects_merged) + considered_full_projects_merged2 = self.merge_periods(considered_full_projects_rounded) + considered_full_projects_rounded2, months = self.round_periods(considered_full_projects_merged2) + + non_overlapping_half_projects = [] + for test_interval in considered_half_projects: + non_overlapping_half_projects.extend( + self.find_non_overlapping_periods(considered_full_projects_rounded2, test_interval) + ) + + considered_half_projects_merged = self.merge_periods(non_overlapping_half_projects) + considered_half_projects_rounded, months2 = self.round_periods(considered_half_projects_merged) + considered_half_projects_merged2 = self.merge_periods(considered_half_projects_rounded) + considered_half_projects_rounded2, months2 = self.round_periods(considered_half_projects_merged2) + + all_projects_merged = self.merge_periods( + considered_full_projects_rounded2 + considered_half_projects_rounded2 + ) + merged_event_periods = self.merge_periods(considered_events) + + non_overlapping_event_periods = [] + for test_interval in merged_event_periods: + non_overlapping_event_periods.extend( + self.find_non_overlapping_periods(all_projects_merged, test_interval) + ) + + new_total_months = months + math.ceil(months2 / 2) + new_total_days = sum((end - start).days + 1 for start, end, _ in non_overlapping_event_periods) + + if new_total_days != total_days or new_total_months != total_months: + total_days = new_total_days + total_months = new_total_months + updated = True + prediction = launch_date + duration + relativedelta(months=total_months) + timedelta(days=total_days-1) + + # print(prediction, prediction_start + relativedelta(years = 6)) + if prediction > prediction_start + relativedelta(years = 6): + prediction = prediction_start + relativedelta(years = 6) + return prediction, considered_full_projects_rounded2 + considered_half_projects_rounded2 + non_overlapping_event_periods \ No newline at end of file -- cgit v1.1