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