53 lines
1.7 KiB
Python
53 lines
1.7 KiB
Python
"""System timezone detection for local-day activity totals.
|
|
|
|
Provides timezone detection (TZ env, /etc/localtime) and offset
|
|
computation used by local-day derivation. All functions are
|
|
stateless and safe to call from the collector and TUI reader.
|
|
"""
|
|
import os
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
|
|
|
|
def detect_system_tz() -> str:
|
|
"""Detect the system timezone name.
|
|
|
|
Resolution order:
|
|
1. ``TZ`` environment variable (may be empty or ":UTC")
|
|
2. Symlink target of ``/etc/localtime``
|
|
3. Falls back to ``"UTC"``
|
|
|
|
Returns a POSIX timezone name like ``"Asia/Kolkata"`` or ``"UTC"``.
|
|
"""
|
|
tz = os.environ.get("TZ", "").strip()
|
|
if tz:
|
|
return tz.lstrip(":")
|
|
|
|
localtime = Path("/etc/localtime")
|
|
if localtime.is_symlink():
|
|
target_path = Path(os.readlink(str(localtime)))
|
|
if not target_path.is_absolute():
|
|
target_path = localtime.parent / target_path
|
|
target = target_path.resolve().as_posix()
|
|
marker = "/zoneinfo/"
|
|
marker_index = target.find(marker)
|
|
if marker_index >= 0:
|
|
return target[marker_index + len(marker):]
|
|
return target
|
|
|
|
return "UTC"
|
|
|
|
|
|
def get_tz_offset_str(dt: datetime, tz_name: str) -> str:
|
|
"""UTC offset as ``+HH:MM`` or ``-HH:MM`` string for *dt* in *tz_name*."""
|
|
from zoneinfo import ZoneInfo
|
|
local_tz = ZoneInfo(tz_name)
|
|
local_dt = dt.astimezone(local_tz)
|
|
offset = local_dt.utcoffset()
|
|
total_seconds = int(offset.total_seconds())
|
|
sign = "+" if total_seconds >= 0 else "-"
|
|
total_seconds = abs(total_seconds)
|
|
hours = total_seconds // 3600
|
|
minutes = (total_seconds % 3600) // 60
|
|
return "%s%02d:%02d" % (sign, hours, minutes)
|