crate-python icon indicating copy to clipboard operation
crate-python copied to clipboard

Return `TIMESTAMP` types as timezone-aware native Python `datetime` objects

Open amotl opened this issue 3 years ago • 0 comments

About

When requested, make the driver return timezone-aware native Python datetime objects for CrateDB's TIMESTAMP types. The user can easily supply the desired time zone by different means.

Rationale

@mfussenegger asked at https://github.com/crate/crate-python/pull/442#pullrequestreview-1088223785:

I think something common like setting the timezone for datetime objects could be made even easier for users.

I shared some initial thoughts about it at https://github.com/crate/crate-python/pull/442#pullrequestreview-1110538218 ff., and finally settled with this implementation, separately from the baseline implementation for the data type converter.

Details

This patch adds additional convenience based on the data type converter machinery added with #442.

  • A time_zone keyword argument can be passed to both the connect() method, or when creating new Cursor objects.
  • The time_zone attribute can also be changed at runtime on both the connection and cursor object instances.

Different ways to populate the time_zone value are supported. Some examples::

  • datetime.timezone.utc
  • datetime.timezone(datetime.timedelta(hours=7), name="MST")
  • pytz.timezone("Australia/Sydney")
  • zoneinfo.ZoneInfo("Australia/Sydney")
  • +0530 (UTC offset in string format)

Acknowledgements

This interface was inspired by the DBAPI drivers for MySQL and Elasticsearch. Thank you!

  • https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlconnection-time-zone.html
  • https://github.com/preset-io/elasticsearch-dbapi#time-zone

Synopsis

Use time_zone argument when creating a new connection. Here, use a pytz.timezone object.

>>> import pytz
>>> from crate.client import connect

>>> connect("localhost:4200", time_zone=pytz.timezone("Australia/Sydney"))
>>> cursor = connection.cursor()
>>> cursor.execute(stmt)
>>> cursor.fetchone()
['foo', datetime.datetime(2022, 7, 19, 4, 10, 36, 758000, tzinfo=<DstTzInfo 'Australia/Sydney' AEST+10:00:00 STD>)]

Use time_zone argument when creating a new cursor. Here, use an UTC offset string.

>>> from crate.client import connect

>>> connection = connect("localhost:4200")
>>> cursor = connection.cursor(time_zone="+0530")
>>> cursor.execute(stmt)
>>> cursor.fetchone()
['foo', datetime.datetime(2022, 7, 18, 23, 40, 36, 758000, tzinfo=datetime.timezone(datetime.timedelta(seconds=19800), '+0530'))]

References

  • #395
  • #426
  • #437
  • #442

amotl avatar Sep 16 '22 17:09 amotl