home · contact · privacy
In calendar day gap filling, ensure days before and after existing days.
[plomtask] / plomtask / days.py
index 8dd384349bd1419a16b19971ee4d9aa81deff796..e3d56d7fb1049c161b146af555b05ccf2ed2f904 100644 (file)
@@ -3,6 +3,7 @@ from __future__ import annotations
 from datetime import datetime, timedelta
 from plomtask.exceptions import BadFormatException
 from plomtask.db import DatabaseConnection, BaseModel
 from datetime import datetime, timedelta
 from plomtask.exceptions import BadFormatException
 from plomtask.db import DatabaseConnection, BaseModel
+from plomtask.todos import Todo
 
 DATE_FORMAT = '%Y-%m-%d'
 MIN_RANGE_DATE = '2024-01-01'
 
 DATE_FORMAT = '%Y-%m-%d'
 MIN_RANGE_DATE = '2024-01-01'
@@ -36,6 +37,7 @@ class Day(BaseModel[str]):
         super().__init__(id_)
         self.datetime = datetime.strptime(self.date, DATE_FORMAT)
         self.comment = comment
         super().__init__(id_)
         self.datetime = datetime.strptime(self.date, DATE_FORMAT)
         self.comment = comment
+        self.calendarized_todos: list[Todo] = []
 
     def __lt__(self, other: Day) -> bool:
         return self.date < other.date
 
     def __lt__(self, other: Day) -> bool:
         return self.date < other.date
@@ -61,15 +63,20 @@ class Day(BaseModel[str]):
         for row in db_conn.exec(sql, (start_date, end_date)):
             days += [cls.by_id(db_conn, row[0])]
         days.sort()
         for row in db_conn.exec(sql, (start_date, end_date)):
             days += [cls.by_id(db_conn, row[0])]
         days.sort()
-        if fill_gaps and len(days) > 1:
-            gapless_days = []
-            for i, day in enumerate(days):
-                gapless_days += [day]
-                if i < len(days) - 1:
-                    while day.next_date != days[i+1].date:
-                        day = Day(day.next_date)
-                        gapless_days += [day]
-            days = gapless_days
+        if fill_gaps:
+            if start_date not in [d.date for d in days]:
+                days = [Day(start_date)] + days
+            if end_date not in [d.date for d in days]:
+                days += [Day(end_date)]
+            if len(days) > 1:
+                gapless_days = []
+                for i, day in enumerate(days):
+                    gapless_days += [day]
+                    if i < len(days) - 1:
+                        while day.next_date != days[i+1].date:
+                            day = Day(day.next_date)
+                            gapless_days += [day]
+                days = gapless_days
         return days
 
     @property
         return days
 
     @property
@@ -78,6 +85,17 @@ class Day(BaseModel[str]):
         assert isinstance(self.id_, str)
         return self.id_
 
         assert isinstance(self.id_, str)
         return self.id_
 
+    @property
+    def first_of_month(self) -> bool:
+        """Return what month self.date is part of."""
+        assert isinstance(self.id_, str)
+        return self.id_[-2:] == '01'
+
+    @property
+    def month_name(self) -> str:
+        """Return what month self.date is part of."""
+        return self.datetime.strftime('%B')
+
     @property
     def weekday(self) -> str:
         """Return what weekday matches self.date."""
     @property
     def weekday(self) -> str:
         """Return what weekday matches self.date."""
@@ -95,6 +113,7 @@ class Day(BaseModel[str]):
         next_datetime = self.datetime + timedelta(days=1)
         return next_datetime.strftime(DATE_FORMAT)
 
         next_datetime = self.datetime + timedelta(days=1)
         return next_datetime.strftime(DATE_FORMAT)
 
-    def save(self, db_conn: DatabaseConnection) -> None:
-        """Add (or re-write) self to DB and cache."""
-        self.save_core(db_conn)
+    def collect_calendarized_todos(self, db_conn: DatabaseConnection) -> None:
+        """Fill self.calendarized_todos."""
+        self.calendarized_todos = [t for t in Todo.by_date(db_conn, self.date)
+                                   if t.calendarize]