- Drop support for Python 3.8.
+Psycopg 3.2.8 (unreleased)
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Fix `DateFromTicks` and `TimeFromTicks` return values to return date and
+ time referred as UTC rather than the local timezone. Change
+ `TimestampFromTicks` to return a datetime in UTC rather than in the local
+ timezone (:ticket:`#1058`).
+
Psycopg 3.2.7
^^^^^^^^^^^^^
from __future__ import annotations
-import time
import datetime as dt
-from math import floor
from typing import Any
from collections.abc import Sequence
from .abc import AdaptContext, Buffer
from .types.string import BytesBinaryDumper, BytesDumper
+EPOCH = dt.datetime(1970, 1, 1, tzinfo=dt.timezone.utc)
+
class DBAPITypeObject:
def __init__(self, name: str, oids: Sequence[int]):
def TimestampFromTicks(ticks: float) -> dt.datetime:
- secs = floor(ticks)
- frac = ticks - secs
- t = time.localtime(ticks)
- tzinfo = dt.timezone(dt.timedelta(seconds=t.tm_gmtoff))
- rv = dt.datetime(*t[:6], round(frac * 1_000_000), tzinfo=tzinfo)
- return rv
+ return EPOCH + dt.timedelta(seconds=ticks)
def register_dbapi20_adapters(context: AdaptContext) -> None:
"ticks, want",
[
(0, "1970-01-01T00:00:00.000000+0000"),
+ (86370, "1970-01-01T23:59:30.000000+0000"),
(1273173119.99992, "2010-05-06T14:11:59.999920-0500"),
],
)
"ticks, want",
[
(0, "1970-01-01"),
- # Returned date is local
- (1273173119.99992, ["2010-05-06", "2010-05-07"]),
+ (86370, "1970-01-01"), # 30 sec from Jan the 2nd, to test East localization
+ (1273173119.99992, "2010-05-06"),
],
)
def test_date_from_ticks(ticks, want):
s = psycopg.DateFromTicks(ticks)
- if isinstance(want, str):
- want = [want]
- want = [dt.datetime.strptime(w, "%Y-%m-%d").date() for w in want]
- assert s in want
+ want = dt.datetime.strptime(want, "%Y-%m-%d").date()
+ assert s == want
@pytest.mark.parametrize(
"ticks, want",
- [(0, "00:00:00.000000"), (1273173119.99992, "00:11:59.999920")],
+ [(0, "00:00:00.000000"), (1273173119.99992, "19:11:59.999920")],
)
def test_time_from_ticks(ticks, want):
s = psycopg.TimeFromTicks(ticks)
want = dt.datetime.strptime(want, "%H:%M:%S.%f").time()
- assert s.replace(hour=0) == want
+ assert s == want
@pytest.mark.parametrize(