date and time doc page
PYTHON-394
This commit is contained in:
87
docs/dates_and_times.rst
Normal file
87
docs/dates_and_times.rst
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
Working with Dates and Times
|
||||||
|
============================
|
||||||
|
|
||||||
|
This document is meant to provide on overview of the assumptions and limitations of the driver time handling, the
|
||||||
|
reasoning behind it, and describe approaches to working with these types.
|
||||||
|
|
||||||
|
timestamps (Cassandra DateType)
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Timestamps in Cassandra are timezone-naive timestamps encoded as microseconds since UNIX epoch. Clients working with
|
||||||
|
timestamps in this database usually find it easiest to reason about them if they are always assumed to be UTC. To quote the
|
||||||
|
pytz documentation, "The preferred way of dealing with times is to always work in UTC, converting to localtime only when
|
||||||
|
generating output to be read by humans." The driver adheres to this tenant, and assumes UTC is always in the database. The
|
||||||
|
driver attempts to make this correct on the way in, and assumes no timezone on the way out.
|
||||||
|
|
||||||
|
Write Path
|
||||||
|
~~~~~~~~~~
|
||||||
|
When inserting timestamps, the driver handles serialization for the write path as follows:
|
||||||
|
|
||||||
|
If the input is a ``datetime.datetime``, the serialization is normalized by starting with the ``utctimetuple()`` of the
|
||||||
|
value.
|
||||||
|
|
||||||
|
- If the ``datetime`` object is timezone-aware, the timestamp is shifted, and represents the UTC timestamp equivalent.
|
||||||
|
- If the ``datetime`` object is timezone-naive, this results in no shift -- any ``datetime`` with no timezone information is assumed to be UTC
|
||||||
|
|
||||||
|
Note the second point above applies even to "local" times created using ``now()``::
|
||||||
|
|
||||||
|
>>> d = datetime.now()
|
||||||
|
|
||||||
|
>>> print(d.tzinfo)
|
||||||
|
None
|
||||||
|
|
||||||
|
|
||||||
|
These do not contain timezone information intrinsically, so they will be assumed to be UTC and not shifted. When generating
|
||||||
|
timestamps in the application, it is clearer to use ``datetime.utcnow()`` to be explicit about it.
|
||||||
|
|
||||||
|
If the input for a timestamp is numeric, it is assumed to be a epoch-relative microsecond timestamp, as specified in the
|
||||||
|
CQL spec -- no scaling or conversion is done.
|
||||||
|
|
||||||
|
Read Path
|
||||||
|
~~~~~~~~~
|
||||||
|
The driver always assumes persisted timestamps are UTC and makes no attempt to localize them. Returned values are
|
||||||
|
timezone-naive ``datetime.datetime``. We follow this approach because the datetime API has deficiencies around daylight
|
||||||
|
saving time, and the defacto package for handling this is a third-party package (we try to minimize external dependencies
|
||||||
|
and not make decisions for the integrator).
|
||||||
|
|
||||||
|
The decision for how to handle timezones is left to the application. For the most part it is straightforward to apply
|
||||||
|
localization to the ``datetime``\s returned by queries. One prevalent method is to use pytz for localization::
|
||||||
|
|
||||||
|
import pytz
|
||||||
|
user_tz = pytz.timezone('US/Central')
|
||||||
|
timestamp_naive = row.ts
|
||||||
|
timestamp_utc = pytz.utc.localize(timestamp_naive)
|
||||||
|
timestamp_presented = timestamp_utc.astimezone(user_tz)
|
||||||
|
|
||||||
|
This is the most robust approach (likely refactored into a function). If it is deemed too cumbersome to apply for all call
|
||||||
|
sites in the application, it is possible to patch the driver with custom deserialization for this type. However, doing
|
||||||
|
this depends depends some on internal APIs and what extensions are present, so we will only mention the possibility, and
|
||||||
|
not spell it out here.
|
||||||
|
|
||||||
|
date, time (Cassandra DateType)
|
||||||
|
-------------------------------
|
||||||
|
Date and time in Cassandra are idealized markers, much like ``datetime.date`` and ``datetime.time`` in the Python standard
|
||||||
|
library. Unlike these Python implementations, the Cassandra encoding supports much wider ranges. To accommodate these
|
||||||
|
ranges without overflow, this driver returns these data in custom types: :class:`.util.Date` and :class:`.util.Time`.
|
||||||
|
|
||||||
|
Write Path
|
||||||
|
~~~~~~~~~~
|
||||||
|
For simple (not prepared) statements, the input values for each of these can be either a string literal or an encoded
|
||||||
|
integer. See `Working with dates <https://github.com/apache/cassandra/blob/trunk/doc/cql3/CQL.textile#working-with-dates>`_
|
||||||
|
or `Working with time <https://github.com/apache/cassandra/blob/trunk/doc/cql3/CQL.textile#working-with-time>`_ for details
|
||||||
|
on the encoding or string formats.
|
||||||
|
|
||||||
|
For prepared statements, the driver accepts anything that can be used to construct the :class:`.util.Date` or
|
||||||
|
:class:`.util.Time` classes. See the linked API docs for details.
|
||||||
|
|
||||||
|
Read Path
|
||||||
|
~~~~~~~~~
|
||||||
|
The driver always returns custom types for ``date`` and ``time``.
|
||||||
|
|
||||||
|
The driver returns :class:`.util.Date` for ``date`` in order to accommodate the wider range of values without overflow.
|
||||||
|
For applications working within the supported range of [``datetime.MINYEAR``, ``datetime.MAXYEAR``], these are easily
|
||||||
|
converted to standard ``datetime.date`` insances using :meth:`.Date.date`.
|
||||||
|
|
||||||
|
The driver returns :class:`.util.Time` for ``time`` in order to retain nanosecond precision stored in the database.
|
||||||
|
For applications not concerned with this level of precision, these are easily converted to standard ``datetime.time``
|
||||||
|
insances using :meth:`.Time.time`.
|
||||||
@@ -42,6 +42,9 @@ Contents
|
|||||||
:doc:`security`
|
:doc:`security`
|
||||||
An overview of the security features of the driver.
|
An overview of the security features of the driver.
|
||||||
|
|
||||||
|
:doc:`dates_and_times`
|
||||||
|
Some discussion on the driver's approach to working with timestamp, date, time types
|
||||||
|
|
||||||
:doc:`faq`
|
:doc:`faq`
|
||||||
A collection of Frequently Asked Questions
|
A collection of Frequently Asked Questions
|
||||||
|
|
||||||
@@ -58,6 +61,7 @@ Contents
|
|||||||
security
|
security
|
||||||
user_defined_types
|
user_defined_types
|
||||||
object_mapper
|
object_mapper
|
||||||
|
dates_and_times
|
||||||
faq
|
faq
|
||||||
|
|
||||||
Getting Help
|
Getting Help
|
||||||
|
|||||||
Reference in New Issue
Block a user