mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-10 19:16:34 +03:00
Use datetime.timezone as default tzinfo_factory.
This commit is contained in:
parent
2eac70786e
commit
f28502663f
2
NEWS
2
NEWS
|
@ -20,6 +20,8 @@ Other changes:
|
|||
|
||||
- Dropped support for Python 2.7, 3.4, 3.5 (:tickets:`#1198, #1000, #1197`).
|
||||
- Dropped support for mx.DateTime.
|
||||
- Use `datetime.timezone` objects by default in datetime objects instead of
|
||||
`~psycopg2.tz.FixedOffsetTimezone`.
|
||||
- Build system for Linux/MacOS binary packages moved to GitHub action, now
|
||||
providing :pep:`600`\-style wheels packages.
|
||||
|
||||
|
|
|
@ -498,8 +498,10 @@ The ``cursor`` class
|
|||
|
||||
The time zone factory used to handle data types such as
|
||||
:sql:`TIMESTAMP WITH TIME ZONE`. It should be a `~datetime.tzinfo`
|
||||
object. A few implementations are available in the `psycopg2.tz`
|
||||
module.
|
||||
object. Default is `datetime.timezone`.
|
||||
|
||||
.. versionchanged:: 2.9
|
||||
previosly the default factory was `psycopg2.tz.FixedOffsetTimezone`.
|
||||
|
||||
|
||||
.. method:: nextset()
|
||||
|
|
|
@ -574,14 +574,13 @@ Time zones handling
|
|||
'''''''''''''''''''
|
||||
|
||||
The PostgreSQL type :sql:`timestamp with time zone` (a.k.a.
|
||||
:sql:`timestamptz`) is converted into Python `~datetime.datetime` objects with
|
||||
a `~datetime.datetime.tzinfo` attribute set to a
|
||||
`~psycopg2.tz.FixedOffsetTimezone` instance.
|
||||
:sql:`timestamptz`) is converted into Python `~datetime.datetime` objects.
|
||||
|
||||
>>> cur.execute("SET TIME ZONE 'Europe/Rome'") # UTC + 1 hour
|
||||
>>> cur.execute("SELECT '2010-01-01 10:30:45'::timestamptz")
|
||||
>>> cur.fetchone()[0].tzinfo
|
||||
psycopg2.tz.FixedOffsetTimezone(offset=60, name=None)
|
||||
>>> cur.fetchone()[0]
|
||||
datetime.datetime(2010, 1, 1, 10, 30, 45,
|
||||
tzinfo=datetime.timezone(datetime.timedelta(seconds=3600)))
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -594,9 +593,9 @@ a `~datetime.datetime.tzinfo` attribute set to a
|
|||
>>> cur.execute("SELECT '1900-01-01 10:30:45'::timestamptz")
|
||||
>>> cur.fetchone()[0].tzinfo
|
||||
# On Python 3.6: 5h, 21m
|
||||
psycopg2.tz.FixedOffsetTimezone(offset=datetime.timedelta(0, 19260), name=None)
|
||||
datetime.timezone(datetime.timedelta(0, 19260))
|
||||
# On Python 3.7 and following: 5h, 21m, 10s
|
||||
psycopg2.tz.FixedOffsetTimezone(offset=datetime.timedelta(seconds=19270), name=None)
|
||||
datetime.timezone(datetime.timedelta(seconds=19270))
|
||||
|
||||
.. versionchanged:: 2.2.2
|
||||
timezones with seconds are supported (with rounding). Previously such
|
||||
|
@ -605,6 +604,9 @@ a `~datetime.datetime.tzinfo` attribute set to a
|
|||
.. versionchanged:: 2.9
|
||||
timezones with seconds are supported without rounding.
|
||||
|
||||
.. versionchanged:: 2.9
|
||||
use `datetime.timezone` as default tzinfo object instead of
|
||||
`~psycopg2.tz.FixedOffsetTimezone`.
|
||||
|
||||
.. index::
|
||||
double: Date objects; Infinite
|
||||
|
|
|
@ -1951,10 +1951,11 @@ cursor_setup(cursorObject *self, connectionObject *conn, const char *name)
|
|||
|
||||
/* default tzinfo factory */
|
||||
{
|
||||
/* The datetime api doesn't seem to have a constructor to make a
|
||||
* datetime.timezone, so use the Python interface. */
|
||||
PyObject *m = NULL;
|
||||
if ((m = PyImport_ImportModule("psycopg2.tz"))) {
|
||||
self->tzinfo_factory = PyObject_GetAttrString(
|
||||
m, "FixedOffsetTimezone");
|
||||
if ((m = PyImport_ImportModule("datetime"))) {
|
||||
self->tzinfo_factory = PyObject_GetAttrString(m, "timezone");
|
||||
Py_DECREF(m);
|
||||
}
|
||||
if (!self->tzinfo_factory) {
|
||||
|
|
|
@ -104,9 +104,18 @@ _parse_inftz(const char *str, PyObject *curs)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (!(tzinfo = PyObject_CallFunction(tzinfo_factory, "i", 0))) {
|
||||
goto exit;
|
||||
#if PY_VERSION_HEX < 0x03070000
|
||||
{
|
||||
PyObject *tzoff;
|
||||
if (!(tzoff = PyDelta_FromDSU(0, 0, 0))) { goto exit; }
|
||||
tzinfo = PyObject_CallFunctionObjArgs(tzinfo_factory, tzoff, NULL);
|
||||
Py_DECREF(tzoff);
|
||||
if (!tzinfo) { goto exit; }
|
||||
}
|
||||
#else
|
||||
tzinfo = PyDateTime_TimeZone_UTC;
|
||||
Py_INCREF(tzinfo);
|
||||
#endif
|
||||
|
||||
/* m.replace(tzinfo=tzinfo) */
|
||||
if (!(args = PyTuple_New(0))) { goto exit; }
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
import sys
|
||||
import math
|
||||
import pickle
|
||||
from datetime import date, datetime, time, timedelta
|
||||
from datetime import date, datetime, time, timedelta, timezone
|
||||
|
||||
import psycopg2
|
||||
from psycopg2.tz import FixedOffsetTimezone, ZERO
|
||||
|
@ -192,6 +192,22 @@ class DatetimeTests(ConnectingTestCase, CommonDatetimeTestsMixin):
|
|||
value_utc = value.astimezone(UTC).replace(tzinfo=None)
|
||||
self.assertEqual(base - value_utc, timedelta(seconds=offset))
|
||||
|
||||
def test_default_tzinfo(self):
|
||||
self.curs.execute("select '2000-01-01 00:00+02:00'::timestamptz")
|
||||
dt = self.curs.fetchone()[0]
|
||||
self.assert_(isinstance(dt.tzinfo, timezone))
|
||||
self.assertEqual(dt,
|
||||
datetime(2000, 1, 1, tzinfo=timezone(timedelta(minutes=120))))
|
||||
|
||||
def test_fotz_tzinfo(self):
|
||||
self.curs.tzinfo_factory = FixedOffsetTimezone
|
||||
self.curs.execute("select '2000-01-01 00:00+02:00'::timestamptz")
|
||||
dt = self.curs.fetchone()[0]
|
||||
self.assert_(not isinstance(dt.tzinfo, timezone))
|
||||
self.assert_(isinstance(dt.tzinfo, FixedOffsetTimezone))
|
||||
self.assertEqual(dt,
|
||||
datetime(2000, 1, 1, tzinfo=timezone(timedelta(minutes=120))))
|
||||
|
||||
def test_parse_datetime_timezone(self):
|
||||
self.check_datetime_tz("+01", 3600)
|
||||
self.check_datetime_tz("-01", -3600)
|
||||
|
|
Loading…
Reference in New Issue
Block a user