--- /dev/null
+"""
+Timezone utility functions.
+"""
+
+# Copyright (C) 2020-2021 The Psycopg Team
+
+import logging
+from typing import Dict, Optional, Union
+from datetime import timezone, tzinfo
+
+from .pq.proto import PGconn
+from .utils.compat import ZoneInfo
+
+logger = logging.getLogger("psycopg3")
+
+_timezones: Dict[Union[None, bytes], tzinfo] = {
+ None: timezone.utc,
+ b"UTC": timezone.utc,
+}
+
+
+def get_tzinfo(pgconn: Optional[PGconn]) -> tzinfo:
+ """Return the Python timezone info of the connection's timezone."""
+ tzname = pgconn.parameter_status(b"TimeZone") if pgconn else None
+ try:
+ return _timezones[tzname]
+ except KeyError:
+ sname = tzname.decode("utf8") if tzname else "UTC"
+ try:
+ zi: tzinfo = ZoneInfo(sname)
+ except KeyError:
+ logger.warning(
+ "unknown PostgreSQL timezone: %r; will use UTC", sname
+ )
+ zi = timezone.utc
+
+ _timezones[tzname] = zi
+ return zi
import warnings
import threading
from types import TracebackType
-from typing import Any, AsyncIterator, Dict, Callable, Generic, Iterator, List
+from typing import Any, AsyncIterator, Callable, Generic, Iterator, List
from typing import NamedTuple, Optional, Type, TypeVar, Union
from typing import overload, TYPE_CHECKING
from weakref import ref, ReferenceType
from .generators import notifies
from ._preparing import PrepareManager
from .transaction import Transaction, AsyncTransaction
-from .utils.compat import asynccontextmanager, ZoneInfo
+from .utils.compat import asynccontextmanager
from .server_cursor import ServerCursor, AsyncServerCursor
logger = logging.getLogger("psycopg3")
connect = generators.connect
execute = generators.execute
-_timezones: Dict[Union[None, bytes], ZoneInfo] = {}
-
class Notify(NamedTuple):
"""An asynchronous notification received from the database."""
if result.status != ExecStatus.TUPLES_OK:
raise e.error_from_result(result, encoding=self.client_encoding)
- @property
- def timezone(self) -> ZoneInfo:
- """The Python timezone info of the connection's timezone."""
- tzname = self.pgconn.parameter_status(b"TimeZone")
- try:
- return _timezones[tzname]
- except KeyError:
- sname = tzname.decode("utf8") if tzname else "UTC"
- try:
- zi = ZoneInfo(sname)
- except KeyError:
- logger.warning(
- "unknown PostgreSQL timezone: %r will use UTC", sname
- )
- zi = ZoneInfo("UTC")
-
- _timezones[tzname] = zi
- return zi
-
@property
def info(self) -> ConnectionInfo:
"""A `ConnectionInfo` attribute to inspect connection properties."""
import re
from typing import Any, Dict, List, Optional
from pathlib import Path
+from datetime import tzinfo
from . import pq
from . import errors as e
from . import encodings
+from ._tz import get_tzinfo
def make_conninfo(conninfo: str = "", **kwargs: Any) -> str:
"""
return self._get_pgconn_attr("error_message")
+ @property
+ def timezone(self) -> tzinfo:
+ """The Python timezone info of the connection's timezone."""
+ return get_tzinfo(self.pgconn)
+
def _get_pgconn_attr(self, name: str) -> str:
value: bytes = getattr(self.pgconn, name)
return value.decode(self._pyenc)
from ..adapt import Buffer, Dumper, Loader, Format as Pg3Format
from ..proto import AdaptContext
from ..errors import InterfaceError, DataError
-from ..utils.compat import ZoneInfo
+from .._tz import get_tzinfo
_PackInt = Callable[[int], bytes]
_UnpackInt = Callable[[bytes], Tuple[int]]
def __init__(self, oid: int, context: Optional[AdaptContext] = None):
super().__init__(oid, context)
- self._timezone = (
- self.connection.timezone if self.connection else ZoneInfo("UTC")
+ self._timezone = get_tzinfo(
+ self.connection.pgconn if self.connection else None
)
def _format_from_context(self) -> str:
def __init__(self, oid: int, context: Optional[AdaptContext] = None):
super().__init__(oid, context)
- self._timezone = (
- self.connection.timezone if self.connection else ZoneInfo("UTC")
+ self._timezone = get_tzinfo(
+ self.connection.pgconn if self.connection else None
)
def load(self, data: Buffer) -> datetime: