Running pytest I get:
FAILED tests/test_psycopg_dbapi20.py::test_date_from_ticks[0-1970-01-01] - assert datetime.date(1969, 12, 31) in [datetime.date(1970, 1, 1)]
Tested with:
- psycopg 3.2.7
- postgresql 17.4
- python 3.13.3
- macOS 15.4
- Apple M4
This issue was also reported here for riscv64: #883
I think the problem is in TimestampFromTicks(ticks) in dbapi20.py. It uses time.localtime(0) to find the epoch start, with offset to local timezone. This is turned into a timezone-aware datetime object.
I'm in timezone UTC-7 so TimestampFromTicks(0) returns:
datetime.datetime(1969, 12, 31, 17, 0, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
DateFromTicks(0) calls .date() on that object, which ignores the timezone and returns datetime.date(1969, 12, 31), which is incorrect.
TimeFromTicks(0) returns datetime.time(17, 0) which is also incorrect. However, in test_time_from_ticks, the hour is forced to 0 so the test passes.
According to the Python documentation (referred to from PEP-249):
The epoch is the point where the time starts, the return value of time.gmtime(0). It is January 1, 1970, 00:00:00 (UTC) on all platforms.
I think the solution is to use time.gmtime(0) in TimestampFromTicks and set the timezone to UTC.
For reference, SQLAlchemy sets epoch like this:
epoch = dt.datetime.fromtimestamp(0, dt.timezone.utc).replace(tzinfo=None)
Running pytest I get:
Tested with:
This issue was also reported here for riscv64: #883
I think the problem is in
TimestampFromTicks(ticks)in dbapi20.py. It usestime.localtime(0)to find the epoch start, with offset to local timezone. This is turned into a timezone-aware datetime object.I'm in timezone UTC-7 so
TimestampFromTicks(0)returns:DateFromTicks(0)calls.date()on that object, which ignores the timezone and returnsdatetime.date(1969, 12, 31), which is incorrect.TimeFromTicks(0)returnsdatetime.time(17, 0)which is also incorrect. However, intest_time_from_ticks, the hour is forced to 0 so the test passes.According to the Python documentation (referred to from PEP-249):
I think the solution is to use
time.gmtime(0)inTimestampFromTicksand set the timezone to UTC.For reference, SQLAlchemy sets epoch like this: