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