From: Daniele Varrazzo Date: Wed, 8 Jun 2022 22:11:52 +0000 (+0200) Subject: docs: mention different infinity date adaptation in psycopg2 differences pages X-Git-Tag: 3.1~62^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dde03b506ac30291cf233c6190f77af6f8254a66;p=thirdparty%2Fpsycopg.git docs: mention different infinity date adaptation in psycopg2 differences pages See #315 --- diff --git a/docs/advanced/adapt.rst b/docs/advanced/adapt.rst index 7ae1c7851..73a82ea32 100644 --- a/docs/advanced/adapt.rst +++ b/docs/advanced/adapt.rst @@ -172,10 +172,10 @@ PostgreSQL but not handled by Python: .. code:: python - >>> conn.execute("'infinity'::date").fetchone() + >>> conn.execute("SELECT 'infinity'::date").fetchone() Traceback (most recent call last): ... - psycopg.DataError: Python date doesn't support years after 9999: got infinity + DataError: date too large (after year 10K): 'infinity' One possibility would be to store Python's `datetime.date.max` as PostgreSQL infinity. For this, let's create a subclass for the dumper and the loader and @@ -193,6 +193,8 @@ cursor): def dump(self, obj): if obj == date.max: return b"infinity" + elif obj == date.min: + return b"-infinity" else: return super().dump(obj) @@ -200,6 +202,8 @@ cursor): def load(self, data): if data == b"infinity": return date.max + elif data == b"-infinity": + return date.min else: return super().load(data) diff --git a/docs/basic/from_pg2.rst b/docs/basic/from_pg2.rst index d6cfec325..2bd3bd69e 100644 --- a/docs/basic/from_pg2.rst +++ b/docs/basic/from_pg2.rst @@ -274,6 +274,36 @@ connection by running a :sql:`SET client_encoding` statement... But why would you? +.. _infinity-datetime: + +No default infinity dates handling +---------------------------------- + +PostgreSQL can represent has a much wider range of dates and timestamps than +Python. While Python dates are limited to the years between 1 and 9999 +(represented by constants such as `datetime.date.min` and +`~datetime.date.max`), PostgreSQL dates extend to BC dates and past the year +10K. Furthermore PostgreSQL can also represent symbolic dates "infinity", in +both directions. + +In psycopg2, by default, `infinity dates and timestamps map to 'date.max'`__ +and similar constants. This has the problem of creating a non-bijective +mapping (two Postgres dates, infinity and 9999-12-31, both map to the same +Python date). There is also the perversity that valid Postgres dates, greater +than Python `!date.max` but arguably lesser than infinity, will still +overflow. + +In Psycopg 3, every date greater than year 9999 will overflow, including +infinity. If you would like to customize this mapping (for instance flattening +every date past Y10K on `!date.max`) you can subclass and adapt the +appropriate loaders: take a look at :ref:`this example +` to see how. + +.. __: https://www.psycopg.org/docs/usage.html#infinite-dates-handling + + +.. _whats-new: + What's new in Psycopg 3 -----------------------