|
29 | 29 | LOCAL_TIMEZONE = tzlocal() |
30 | 30 |
|
31 | 31 |
|
32 | | -class cached_property: |
| 32 | +def register_adapters_and_converters(): |
| 33 | + sqlite3.register_converter( |
| 34 | + 'timestamp', |
| 35 | + lambda d: datetime.fromtimestamp(float(d), LOCAL_TIMEZONE) |
| 36 | + ) |
| 37 | + |
| 38 | + |
| 39 | +register_adapters_and_converters() |
| 40 | + |
| 41 | + |
| 42 | +class cached_property: # noqa |
33 | 43 | """A read-only @property that is only evaluated once. Only usable on class |
34 | 44 | instances' methods. |
35 | 45 | """ |
@@ -426,7 +436,10 @@ def __init__(self, path: str): |
426 | 436 | self.cache_path = str(path) |
427 | 437 | os.makedirs(os.path.dirname(self.cache_path), exist_ok=True) |
428 | 438 |
|
429 | | - self._conn = sqlite3.connect(self.cache_path) |
| 439 | + self._conn = sqlite3.connect( |
| 440 | + str(self.cache_path), |
| 441 | + detect_types=sqlite3.PARSE_DECLTYPES, |
| 442 | + ) |
430 | 443 | self._conn.row_factory = sqlite3.Row |
431 | 444 | self._conn.execute("PRAGMA foreign_keys = ON") |
432 | 445 |
|
@@ -498,15 +511,15 @@ def create_tables(self): |
498 | 511 | "id" INTEGER PRIMARY KEY, |
499 | 512 | "uid" TEXT, |
500 | 513 | "summary" TEXT, |
501 | | - "due" INTEGER, |
| 514 | + "due" TIMESTAMP, |
502 | 515 | "due_dt" INTEGER, |
503 | | - "start" INTEGER, |
| 516 | + "start" TIMESTAMP, |
504 | 517 | "start_dt" INTEGER, |
505 | 518 | "priority" INTEGER, |
506 | | - "created_at" INTEGER, |
507 | | - "completed_at" INTEGER, |
| 519 | + "created_at" timestamp, |
| 520 | + "completed_at" timestamp, |
508 | 521 | "percent_complete" INTEGER, |
509 | | - "dtstamp" INTEGER, |
| 522 | + "dtstamp" timestamp, |
510 | 523 | "status" TEXT, |
511 | 524 | "description" TEXT, |
512 | 525 | "location" TEXT, |
@@ -841,41 +854,26 @@ def todos( |
841 | 854 | seen_paths.add(path) |
842 | 855 | yield todo |
843 | 856 |
|
844 | | - def _datetime_from_db(self, dt) -> datetime | None: |
845 | | - if dt: |
846 | | - return datetime.fromtimestamp(dt, LOCAL_TIMEZONE) |
847 | | - return None |
848 | | - |
849 | | - def _date_from_db(self, dt, is_date=False) -> date | None: |
850 | | - """Deserialise a date (possible datetime).""" |
851 | | - if not dt: |
852 | | - return dt |
853 | | - |
854 | | - if is_date: |
855 | | - return datetime.fromtimestamp(dt, LOCAL_TIMEZONE).date() |
856 | | - else: |
857 | | - return datetime.fromtimestamp(dt, LOCAL_TIMEZONE) |
858 | | - |
859 | 857 | def _todo_from_db(self, row: dict) -> Todo: |
860 | 858 | todo = Todo() |
861 | | - todo.id = row["id"] |
862 | | - todo.uid = row["uid"] |
863 | | - todo.summary = row["summary"] |
864 | | - todo.due = self._date_from_db(row["due"], row["due_dt"]) |
865 | | - todo.start = self._date_from_db(row["start"], row["start_dt"]) |
866 | | - todo.priority = row["priority"] |
867 | | - todo.created_at = self._datetime_from_db(row["created_at"]) |
868 | | - todo.completed_at = self._datetime_from_db(row["completed_at"]) |
869 | | - todo.dtstamp = self._datetime_from_db(row["dtstamp"]) |
870 | | - todo.percent_complete = row["percent_complete"] |
871 | | - todo.status = row["status"] |
872 | | - todo.description = row["description"] |
873 | | - todo.location = row["location"] |
874 | | - todo.sequence = row["sequence"] |
875 | | - todo.last_modified = row["last_modified"] |
876 | | - todo.list = self.lists_map[row["list_name"]] |
877 | | - todo.filename = os.path.basename(row["path"]) |
878 | | - todo.rrule = row["rrule"] |
| 859 | + todo.id = row['id'] |
| 860 | + todo.uid = row['uid'] |
| 861 | + todo.summary = row['summary'] |
| 862 | + todo.due = row['due'] |
| 863 | + todo.start = row['start'] |
| 864 | + todo.priority = row['priority'] |
| 865 | + todo.created_at = row['created_at'] |
| 866 | + todo.completed_at = row['completed_at'] |
| 867 | + todo.dtstamp = row['dtstamp'] |
| 868 | + todo.percent_complete = row['percent_complete'] |
| 869 | + todo.status = row['status'] |
| 870 | + todo.description = row['description'] |
| 871 | + todo.location = row['location'] |
| 872 | + todo.sequence = row['sequence'] |
| 873 | + todo.last_modified = row['last_modified'] |
| 874 | + todo.list = self.lists_map[row['list_name']] |
| 875 | + todo.filename = os.path.basename(row['path']) |
| 876 | + todo.rrule = row['rrule'] |
879 | 877 | return todo |
880 | 878 |
|
881 | 879 | def lists(self) -> Iterable[TodoList]: |
|
0 commit comments