From 272eba3bc1217d339cb1b0e23fd5aad2bee752a4 Mon Sep 17 00:00:00 2001 From: Frederick Yin Date: Wed, 2 Feb 2022 23:23:15 +0800 Subject: Mostly westling timezones --- jimbrella/umbrellas.py | 59 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 23 deletions(-) (limited to 'jimbrella/umbrellas.py') diff --git a/jimbrella/umbrellas.py b/jimbrella/umbrellas.py index ff88277..2525a31 100644 --- a/jimbrella/umbrellas.py +++ b/jimbrella/umbrellas.py @@ -1,7 +1,8 @@ import sqlite3 -from datetime import datetime, timedelta +from datetime import datetime, timezone, timedelta +from dateutil.parser import isoparse from typing import Union -from .utils import human_datetime, human_timedelta +from .utils import human_datetime, human_timedelta, CST from .config import DUE_HOURS, ADMIN_LOG_PATH from .exceptions import * @@ -27,8 +28,8 @@ class Umbrellas: - tenant_id | string. student or faculty ID. - tenant_phone | string. phone number via which to contact tenant when the lease is due. - tenant_email | string. for future compatibility. always None for the time being. - - lent_at | an ISO 8601 date string "YYYY-MM-DDThh:mm:ss.mmm+08:00" if status is - | "lent" or "overdue. is None otherwise. + - lent_at | an ISO 8601 datetime string if status is "lent" or "overdue", empty string + | otherwise. Schema: CREATE TABLE Umbrellas( @@ -54,7 +55,9 @@ class Umbrellas: if umbid is None: data = db.execute("SELECT * FROM Umbrellas").fetchall() else: - data = db.execute("SELECT * FROM Umbrellas WHERE id = ?", (umbid,)).fetchone() + data = db.execute( + "SELECT * FROM Umbrellas WHERE id = ?", (umbid,) + ).fetchone() db.close() return data @@ -64,13 +67,14 @@ class Umbrellas: Not all fields in an umbrella dict need to be present in `umb`. Only `id` is required. If an optional field is not found, its value is left untouched. If an optional field is - present but its value is an empty string or None, the old datum will become NULL. + present but its value is an empty string, it will be erased. Invalid values are rejected as an UmbrellaValueError. If `status` is not "lent" or "overdue", `tenant_*` and `lent_at` are automatically erased. - `lent_at` may be either an ISO 8601 string or a datetime.datetime object. Must be UTC+8. + `lent_at` may be either an ISO 8601 string or a datetime.datetime object. If no timezone is + supplied, UTC+8 is assumed. Returns a dict of : (, ) for each updated field unless its erasure can be inferred. For AdminLog. @@ -82,11 +86,13 @@ class Umbrellas: raise UmbrellaValueError("id") db = sqlite3.connect(self.path) - db.row_factory = sqlite.Row + db.row_factory = sqlite3.Row # check if umbrella # exists in database umbid = umb["id"] - umb_in_db = db.execute("SELECT * FROM Umbrellas WHERE id = ?", (umbid,)).fetchone() + umb_in_db = db.execute( + "SELECT * FROM Umbrellas WHERE id = ?", (umbid,) + ).fetchone() if umb_in_db is None: raise UmbrellaNotFoundError(umbid) @@ -99,12 +105,14 @@ class Umbrellas: if umb_in_db["status"] != umb["status"]: diff["status"] = (umb_in_db["status"], umb["status"]) - db.execute("UPDATE Umbrellas SET status = ? WHERE id = ?", (status, umbid)) + db.execute( + "UPDATE Umbrellas SET status = ? WHERE id = ?", (status, umbid) + ) else: raise UmbrellaValueError("status") if status in ("lent", "overdue"): - for key in ( + for col in ( "tenant_name", "tenant_id", "tenant_phone", @@ -115,16 +123,17 @@ class Umbrellas: diff[col] = (umb_in_db[col], umb[col]) db.execute( - "UPDATE Umbrellas SET ? = ? WHERE id = ?", - (col, - umb[col], - umbid,) + f"UPDATE Umbrellas SET {col} = ? WHERE id = ?", + ( + umb[col], + umbid, + ), ) if "lent_at" in umb: try: # lent_at could be a string, in which case it is parsed - lent_at = datetime.fromisoformat(umb["lent_at"]) + lent_at = isoparse(umb["lent_at"]) except TypeError: # or it could be a datetime.datetime lent_at = umb["lent_at"] @@ -132,16 +141,20 @@ class Umbrellas: # anything else is invalid raise UmbrellaValueError("lent_at") - if lent_at.tzinfo.utcoffset(None).seconds != 28800: - # timezone must be +08:00 - raise UmbrellaValueError("lent_at") + if lent_at.tzinfo is None: + lent_at = lent_at.replace(tzinfo=CST) - diff["lent_at"] = (umb_in_db["lent_at"], lent_at.isoformat(timespec="milliseconds")) + diff["lent_at"] = ( + umb_in_db["lent_at"], + lent_at.isoformat(timespec="milliseconds"), + ) db.execute( "UPDATE Umbrellas SET lent_at = ? WHERE id = ?", - ( lent_at.isoformat(timespec="milliseconds"), - umbid,) + ( + lent_at.isoformat(timespec="milliseconds"), + umbid, + ), ) else: # discard unneeded fields @@ -152,7 +165,7 @@ class Umbrellas: "tenant_email", "lent_at", ): - db.execute("UPDATE Umbrellas SET ? = NULL WHERE id = ?", (col, umbid)) + db.execute(f"UPDATE Umbrellas SET {col} = '' WHERE id = ?", (umbid,)) # now that new data are validated, commit the SQL transaction db.commit() -- cgit v1.2.3