Unify all timestamps to Beijing time (UTC+8)

- Add BEIJING_TZ constant in config.py
- Replace all timezone.utc references across 11 files
- Device-reported times, DB defaults, protocol sync all use Beijing time

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
This commit is contained in:
2026-03-24 05:25:31 +00:00
parent 11281e5be2
commit ced836179c
11 changed files with 70 additions and 47 deletions

View File

@@ -14,6 +14,8 @@ import asyncio
import logging
import struct
from datetime import datetime, timezone
from app.config import BEIJING_TZ
from typing import Any, Dict, Optional, Tuple
from sqlalchemy import select, update
@@ -240,7 +242,7 @@ class ConnectionInfo:
def __init__(self, addr: Tuple[str, int]) -> None:
self.imei: Optional[str] = None
self.addr = addr
self.connected_at = datetime.now(timezone.utc)
self.connected_at = datetime.now(BEIJING_TZ)
self.last_activity = self.connected_at
self.serial_counter: int = 1
@@ -331,7 +333,7 @@ class TCPManager:
break
recv_buffer += data
conn_info.last_activity = datetime.now(timezone.utc)
conn_info.last_activity = datetime.now(BEIJING_TZ)
logger.info("Received %d bytes from %s:%d (IMEI=%s): %s",
len(data), addr[0], addr[1], conn_info.imei, data[:50].hex())
@@ -555,12 +557,12 @@ class TCPManager:
@staticmethod
def _parse_datetime(content: bytes, offset: int = 0) -> Optional[datetime]:
"""Parse a 6-byte datetime field at *offset* and return a UTC datetime."""
"""Parse a 6-byte datetime field at *offset* and return a Beijing-time datetime."""
if len(content) < offset + 6:
return None
yy, mo, dd, hh, mi, ss = struct.unpack_from("BBBBBB", content, offset)
try:
return datetime(2000 + yy, mo, dd, hh, mi, ss, tzinfo=timezone.utc)
return datetime(2000 + yy, mo, dd, hh, mi, ss, tzinfo=BEIJING_TZ)
except ValueError:
return None
@@ -634,7 +636,7 @@ class TCPManager:
lang_str = "zh" if lang_code == 1 else "en" if lang_code == 2 else str(lang_code)
# Persist device record
now = datetime.now(timezone.utc)
now = datetime.now(BEIJING_TZ)
try:
async with async_session() as session:
async with session.begin():
@@ -731,7 +733,7 @@ class TCPManager:
if ext_info:
extension_data = ext_info
now = datetime.now(timezone.utc)
now = datetime.now(BEIJING_TZ)
try:
async with async_session() as session:
@@ -854,7 +856,7 @@ class TCPManager:
content = pkt["content"]
proto = pkt["protocol"]
now = datetime.now(timezone.utc)
now = datetime.now(BEIJING_TZ)
# Parse recorded_at from the 6-byte datetime at offset 0
recorded_at = self._parse_datetime(content, 0) or now
@@ -1247,7 +1249,7 @@ class TCPManager:
if len(content) >= 8:
language = struct.unpack("!H", content[6:8])[0]
now = datetime.now(timezone.utc)
now = datetime.now(BEIJING_TZ)
if language == 0x0001:
# Chinese: use GMT+8 timestamp
ts = int(now.timestamp()) + 8 * 3600
@@ -1269,7 +1271,7 @@ class TCPManager:
conn_info: ConnectionInfo,
) -> None:
"""Handle time sync 2 request (0x8A). Respond with YY MM DD HH MM SS."""
now = datetime.now(timezone.utc)
now = datetime.now(BEIJING_TZ)
payload = bytes(
[
now.year % 100,
@@ -1361,7 +1363,7 @@ class TCPManager:
content = pkt["content"]
proto = pkt["protocol"]
now = datetime.now(timezone.utc)
now = datetime.now(BEIJING_TZ)
recorded_at = self._parse_datetime(content, 0) or now
@@ -1660,7 +1662,7 @@ class TCPManager:
imei = conn_info.imei
content = pkt["content"]
proto = pkt["protocol"]
now = datetime.now(timezone.utc)
now = datetime.now(BEIJING_TZ)
# -- Parse fields --
pos = 0
@@ -1886,7 +1888,7 @@ class TCPManager:
"""
content = pkt["content"]
imei = conn_info.imei
now = datetime.now(timezone.utc)
now = datetime.now(BEIJING_TZ)
# -- Parse 0xB2 fields --
pos = 0
@@ -2036,7 +2038,7 @@ class TCPManager:
"""
content = pkt["content"]
imei = conn_info.imei
now = datetime.now(timezone.utc)
now = datetime.now(BEIJING_TZ)
pos = 0
recorded_at = self._parse_datetime(content, pos) or now
@@ -2293,7 +2295,7 @@ class TCPManager:
except Exception:
response_text = content[5:].hex()
now = datetime.now(timezone.utc)
now = datetime.now(BEIJING_TZ)
try:
async with async_session() as session: