diff --git a/pyproject.toml b/pyproject.toml index 513e76d..e5ca9d4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,9 +13,11 @@ description = "Logging/encoding/decoding using CLP's IR stream format" readme = "README.md" requires-python = ">=3.7" dependencies = [ + "backports.zoneinfo >= 0.2.1; python_version < '3.9'", "clp-ffi-py >= 0.0.11", - "python-dateutil >= 2.7.0", "typing-extensions >= 3.7.4", + "tzlocal == 5.1; python_version < '3.8'", + "tzlocal >= 5.2; python_version >= '3.8'", "zstandard >= 0.18.0", ] classifiers = [ diff --git a/src/clp_logging/handlers.py b/src/clp_logging/handlers.py index 95c048f..ede0003 100644 --- a/src/clp_logging/handlers.py +++ b/src/clp_logging/handlers.py @@ -4,7 +4,6 @@ import sys import time from abc import ABCMeta, abstractmethod -from datetime import tzinfo from math import floor from pathlib import Path from queue import Empty, Queue @@ -13,7 +12,7 @@ from types import FrameType from typing import Callable, ClassVar, Dict, IO, Optional, Tuple, Union -import dateutil.tz +import tzlocal from clp_ffi_py.ir import FourByteEncoder from zstandard import FLUSH_FRAME, ZstdCompressionWriter, ZstdCompressor @@ -59,12 +58,11 @@ def _init_timeinfo(fmt: Optional[str], tz: Optional[str]) -> Tuple[str, str]: if not fmt: fmt = "yyyy-MM-d H:m:s.A" if not tz: - tzf: Optional[tzinfo] = dateutil.tz.gettz() - if tzf: - tzp: Path = Path.resolve(Path(tzf._filename)) # type: ignore - tz = "/".join([tzp.parent.name, tzp.name]) - else: + try: + tz = tzlocal.get_localzone_name() + except Exception: tz = "UTC" + return fmt, tz diff --git a/src/clp_logging/readers.py b/src/clp_logging/readers.py index d083c1a..3b6aaad 100644 --- a/src/clp_logging/readers.py +++ b/src/clp_logging/readers.py @@ -1,11 +1,10 @@ from abc import ABCMeta, abstractmethod -from datetime import datetime, tzinfo +from datetime import datetime from pathlib import Path from sys import stderr from types import TracebackType from typing import IO, Iterator, List, Match, Optional, Tuple, Type, Union -import dateutil.tz from clp_ffi_py.ir import FourByteEncoder from zstandard import ZstdDecompressionReader, ZstdDecompressor @@ -31,6 +30,13 @@ VAR_COMPACT_ENCODING, ) +try: + from zoneinfo import ZoneInfo # type: ignore[import-not-found, unused-ignore] +except ImportError: + from backports.zoneinfo import ( # type: ignore[import-not-found, no-redef, unused-ignore] + ZoneInfo, + ) + class Log: """ @@ -61,7 +67,7 @@ def __init__(self) -> None: def __str__(self) -> str: return self.formatted_msg - def _decode(self, timestamp_format: Optional[str], timezone: Optional[tzinfo]) -> int: + def _decode(self, timestamp_format: Optional[str], timezone: Optional[ZoneInfo]) -> int: """ Populate the `variables`, `msg`, and `formatted_msg` fields by decoding the encoded `encoded_logtype and `encoded_variables`. @@ -148,7 +154,7 @@ def __init__(self, timestamp_format: Optional[str], chunk_size: int) -> None: self.metadata: Optional[Metadata] = None self.last_timestamp_ms: int self.timestamp_format: Optional[str] = timestamp_format - self.timezone: Optional[tzinfo] + self.timezone: Optional[ZoneInfo] self.pos: int def read_preamble(self) -> int: @@ -186,7 +192,7 @@ def read_preamble(self) -> int: # We do not use the timestamp pattern from the preamble as it may # be from other languages and therefore incompatible. # self.timestamp_format = self.metadata[METADATA_TIMESTAMP_PATTERN_KEY] - self.timezone = dateutil.tz.gettz(self.metadata[METADATA_TZ_ID_KEY]) + self.timezone = ZoneInfo(self.metadata[METADATA_TZ_ID_KEY]) return self.pos @abstractmethod