Some checks are pending
CI / Crawler (Python ${{ matrix.python-version }}) (3.10) (push) Waiting to run
CI / Crawler (Python ${{ matrix.python-version }}) (3.11) (push) Waiting to run
CI / API (Python 3.11) (push) Waiting to run
CI / Database migration (push) Waiting to run
CI / App web build (Node 20) (push) Waiting to run
85 lines
2.8 KiB
Python
85 lines
2.8 KiB
Python
import sqlite3
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from contextlib import closing
|
|
from datetime import date, datetime, timezone
|
|
from pathlib import Path
|
|
|
|
|
|
CRAWLER_DIR = Path(__file__).resolve().parents[1]
|
|
if str(CRAWLER_DIR) not in sys.path:
|
|
sys.path.insert(0, str(CRAWLER_DIR))
|
|
|
|
from crawler_manager import CrawlerManager
|
|
from time_utils import (
|
|
KST,
|
|
ensure_kst,
|
|
kst_day_bounds_utc,
|
|
parse_legacy_kst_datetime,
|
|
)
|
|
|
|
|
|
class TimeUtilsTest(unittest.TestCase):
|
|
def test_new_year_kst_day_uses_previous_utc_date(self):
|
|
start, end = kst_day_bounds_utc(date(2026, 1, 1))
|
|
|
|
self.assertEqual("2025-12-31T15:00:00+00:00", start.isoformat())
|
|
self.assertEqual("2026-01-01T15:00:00+00:00", end.isoformat())
|
|
|
|
def test_month_end_is_half_open_at_next_kst_midnight(self):
|
|
start, end = kst_day_bounds_utc(date(2026, 8, 31))
|
|
|
|
self.assertEqual("2026-08-30T15:00:00+00:00", start.isoformat())
|
|
self.assertEqual("2026-08-31T15:00:00+00:00", end.isoformat())
|
|
|
|
def test_legacy_naive_sqlite_datetime_is_treated_as_kst(self):
|
|
parsed = parse_legacy_kst_datetime("2026-08-06T09:00:00")
|
|
|
|
self.assertEqual(KST, parsed.tzinfo)
|
|
self.assertEqual(9, parsed.hour)
|
|
|
|
def test_aware_utc_datetime_is_converted_to_kst(self):
|
|
parsed = ensure_kst(datetime(2026, 8, 5, 15, 0, tzinfo=timezone.utc))
|
|
|
|
self.assertEqual(date(2026, 8, 6), parsed.date())
|
|
self.assertEqual(0, parsed.hour)
|
|
|
|
|
|
class CrawlerManagerTimezoneTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.temp_dir = tempfile.TemporaryDirectory()
|
|
self.current = datetime(2026, 8, 5, 19, 59, tzinfo=timezone.utc)
|
|
self.manager = CrawlerManager(
|
|
db_path=Path(self.temp_dir.name) / "crawler_manager.db",
|
|
now_provider=lambda: self.current,
|
|
)
|
|
|
|
def tearDown(self):
|
|
self.temp_dir.cleanup()
|
|
|
|
def test_night_window_uses_kst_when_host_clock_is_utc(self):
|
|
# UTC 19:59 == KST 04:59
|
|
self.assertFalse(self.manager.should_run("plant-a"))
|
|
|
|
# UTC 20:00 == KST 05:00
|
|
self.current = datetime(2026, 8, 5, 20, 0, tzinfo=timezone.utc)
|
|
self.assertTrue(self.manager.should_run("plant-a"))
|
|
|
|
def test_legacy_naive_heartbeat_value_can_be_compared(self):
|
|
self.current = datetime(2026, 8, 6, 1, 0, tzinfo=timezone.utc) # KST 10:00
|
|
self.assertTrue(self.manager.should_save("plant-a", {"kw": 10, "today": 20}))
|
|
|
|
with closing(sqlite3.connect(self.manager.db_path)) as conn:
|
|
conn.execute(
|
|
"UPDATE site_data SET updated_at = ? WHERE site_id = ?",
|
|
("2026-08-06T08:59:59", "plant-a"),
|
|
)
|
|
conn.commit()
|
|
|
|
self.assertTrue(self.manager.should_save("plant-a", {"kw": 10, "today": 20}))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|