fix: bib.sync — normalize timestamps to Zotero format (no T, no Z)

Zotero expects 'YYYY-MM-DD HH:MM:SS' for date fields, not ISO 8601
with T separator and Z suffix. Added _normalize_zotero_date() and
applied it to accessDate, dateEnacted, and date fields in _set_field().
Also fixed _now_iso() for dateAdded/dateModified on item creation.
This commit is contained in:
kert
2026-03-25 14:12:10 -04:00
parent d7c624b127
commit 8b6e6ef1b3
2 changed files with 13 additions and 4 deletions

View File

@@ -94,7 +94,8 @@ def _is_valid_zotero_key(key: str) -> bool:
def _now_iso() -> str: def _now_iso() -> str:
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") """Zotero internal timestamp: ``YYYY-MM-DD HH:MM:SS`` (no T, no Z)."""
return datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
def _ensure_value(con: sqlite3.Connection, value: str) -> int: def _ensure_value(con: sqlite3.Connection, value: str) -> int:
@@ -118,6 +119,11 @@ def _ensure_tag(con: sqlite3.Connection, name: str) -> int:
return cur.lastrowid return cur.lastrowid
def _normalize_zotero_date(value: str) -> str:
"""Convert ISO 8601 timestamps to Zotero's format (no T, no Z)."""
return value.replace("T", " ").rstrip("Z")
def _set_field( def _set_field(
con: sqlite3.Connection, con: sqlite3.Connection,
item_id: int, item_id: int,
@@ -130,6 +136,9 @@ def _set_field(
field_id = _FIELD_IDS.get(field_name) field_id = _FIELD_IDS.get(field_name)
if field_id is None: if field_id is None:
return return
# Normalize date fields to Zotero's expected format
if field_name in ("accessDate", "dateEnacted", "date"):
value = _normalize_zotero_date(value)
value_id = _ensure_value(con, value) value_id = _ensure_value(con, value)
con.execute( con.execute(
"INSERT OR REPLACE INTO itemData (itemID, fieldID, valueID) VALUES (?, ?, ?)", "INSERT OR REPLACE INTO itemData (itemID, fieldID, valueID) VALUES (?, ?, ?)",

View File

@@ -106,9 +106,9 @@ class TestZoteroKey:
class TestNowIso: class TestNowIso:
def test_format(self) -> None: def test_format(self) -> None:
result = _now_iso() result = _now_iso()
assert len(result) == 20 # "YYYY-MM-DDTHH:MM:SSZ" assert len(result) == 19 # "YYYY-MM-DD HH:MM:SS"
assert "T" in result assert " " in result
assert result.endswith("Z") assert not result.endswith("Z")
# ── _ensure_value ─────────────────────────────────────────────────── # ── _ensure_value ───────────────────────────────────────────────────