From 5d4f9ef2c5f9453c99a13edb56fcf81991677b6a Mon Sep 17 00:00:00 2001 From: Trevin Chow Date: Sat, 16 May 2026 21:40:25 -0700 Subject: [PATCH] fix(store): use UTC for all date arithmetic against SQLite columns Greptile flagged that _cli_query's --since parsing uses datetime.now() (local time) while first_seen is stored via SQLite's datetime('now') (UTC). The same bug exists in three other call sites that compare against either first_seen or run_date (both UTC): - get_daily_cost: "today" defaults to local date, returns wrong day's cost near UTC midnight - get_stats: "7 days ago" cutoff for runs_7d / successful_7d - get_trending: "N days ago" cutoff for finding activity ranking - _cli_query: "N days ago" cutoff for --since flag (Greptile's flag) All four now use datetime.now(timezone.utc). Same root cause and same fix as the test_get_new_findings_filters_by_date repair in the previous commit. --- skills/last30days/scripts/store.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/skills/last30days/scripts/store.py b/skills/last30days/scripts/store.py index 7173517..bb308da 100644 --- a/skills/last30days/scripts/store.py +++ b/skills/last30days/scripts/store.py @@ -14,7 +14,7 @@ import argparse import json import sqlite3 import sys -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from pathlib import Path from typing import Any, Dict, List, Optional @@ -519,7 +519,7 @@ def get_daily_cost(date: Optional[str] = None) -> float: conn = _connect() try: if not date: - date = datetime.now().strftime("%Y-%m-%d") + date = datetime.now(timezone.utc).strftime("%Y-%m-%d") row = conn.execute( """SELECT COALESCE(SUM(token_cost), 0) as total FROM research_runs @@ -575,7 +575,7 @@ def get_stats() -> Dict[str, Any]: topic_count = conn.execute("SELECT COUNT(*) FROM topics WHERE enabled = 1").fetchone()[0] finding_count = conn.execute("SELECT COUNT(*) FROM findings").fetchone()[0] - week_ago = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d") + week_ago = (datetime.now(timezone.utc) - timedelta(days=7)).strftime("%Y-%m-%d") runs_7d = conn.execute( "SELECT COUNT(*) FROM research_runs WHERE run_date >= ?", (week_ago,) ).fetchone()[0] @@ -621,7 +621,7 @@ def get_trending(days: int = 7) -> List[Dict[str, Any]]: """Get topics ranked by recent finding activity.""" conn = _connect() try: - since = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d") + since = (datetime.now(timezone.utc) - timedelta(days=days)).strftime("%Y-%m-%d") rows = conn.execute( """SELECT t.name, t.id, COUNT(f.id) as new_findings, @@ -725,9 +725,10 @@ def _cli_query(args): since = None if args.since: - # Parse duration like "7d", "30d" + # Parse duration like "7d", "30d". Use UTC to match SQLite's + # datetime('now') which writes first_seen in UTC. days = int(args.since.rstrip("d")) - since = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d") + since = (datetime.now(timezone.utc) - timedelta(days=days)).strftime("%Y-%m-%d") findings = get_new_findings(topic["id"], since) print(json.dumps({"topic": topic["name"], "findings": findings, "count": len(findings)}, default=str))