summaryrefslogtreecommitdiff
path: root/date_calculator.py
diff options
context:
space:
mode:
authormatin <matin.kaufmann@gmail.com>2025-04-21 18:06:36 +0200
committermatin <matin.kaufmann@gmail.com>2025-04-21 18:06:36 +0200
commit793667291457380a0341f2ce7f3d25934de56b5b (patch)
treefbe6d6b66de2c375b07a284ca38deec320b4f988 /date_calculator.py
parent4bbc79b052dd6edfbf6802e81cf043111ea038cb (diff)
first try to add commentary and save functionalities by Claude
Diffstat (limited to 'date_calculator.py')
-rw-r--r--date_calculator.py306
1 files changed, 153 insertions, 153 deletions
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