Skip to content

Commit 203730b

Browse files
authored
DOCSP-37000 - Dates and Times (#22)
1 parent b90c501 commit 203730b

File tree

4 files changed

+176
-184
lines changed

4 files changed

+176
-184
lines changed

source/faq.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ about the decision, but here is a brief summary:
436436
What is the Correct Way to Handle Time Zones with {+driver-short+}?
437437
----------------------------------------------------------
438438

439-
See :ref:`pymongo-datetimes-timezones` for examples of how to handle
439+
See :ref:`pymongo-dates-times` for examples of how to handle
440440
``~datetime.datetime`` objects correctly.
441441

442442
How Can I Save a ``datetime.date`` Instance?

source/fundamentals.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Fundamentals
1212
:maxdepth: 1
1313

1414
/fundamentals/authentication
15+
/fundamentals/dates-and-times
1516
/fundamentals/enterprise-authentication
1617
/fundamentals/gridfs
1718
/fundamentals/indexes
@@ -20,6 +21,7 @@ Fundamentals
2021
/fundamentals/type-hints
2122

2223
- :ref:`pymongo-auth`
24+
- :ref:`pymongo-dates-times`
2325
- :ref:`pymongo-enterprise-auth`
2426
- :ref:`pymongo-gridfs`
2527
- :ref:`pymongo-indexes`
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
.. _pymongo-dates-times:
2+
3+
Dates and Times
4+
===============
5+
6+
.. contents:: On this page
7+
:local:
8+
:backlinks: none
9+
:depth: 1
10+
:class: singlecol
11+
12+
.. facet::
13+
:name: genre
14+
:values: reference
15+
16+
.. meta::
17+
:keywords: convert, span, central, mountain, pacific, eastern, calendar
18+
19+
These examples show how to handle Python ``datetime.datetime`` objects
20+
correctly in PyMongo.
21+
22+
Basic Usage
23+
-----------
24+
25+
PyMongo uses ``datetime.datetime`` objects to represent dates and times
26+
in MongoDB documents. Because MongoDB assumes that dates and times are in UTC,
27+
take care to ensure that dates and times written to the database
28+
reflect UTC. For example, the following code stores the current UTC date and
29+
time into MongoDB:
30+
31+
.. code-block:: python
32+
33+
>>> result = db.objects.insert_one(
34+
... {"last_modified": datetime.datetime.now(tz=datetime.timezone.utc)}
35+
... )
36+
37+
.. important::
38+
39+
Always use the ``datetime.datetime.now(tz=datetime.timezone.utc)`` method, which
40+
explicitly returns the current time in UTC. Avoid using the ``datetime.datetime.now()``
41+
method, with no arguments, which returns the current local time.
42+
43+
Saving Datetimes with Time Zones
44+
--------------------------------
45+
46+
When storing ``datetime.datetime`` objects that specify a time zone
47+
(they have a ``tzinfo`` property that isn't ``None``), PyMongo automatically converts
48+
the ``datetime`` value to UTC:
49+
50+
.. code-block:: python
51+
52+
>>> import pytz
53+
>>> pacific = pytz.timezone("US/Pacific")
54+
>>> aware_datetime = pacific.localize(datetime.datetime(2002, 10, 27, 6, 0, 0))
55+
>>> result = db.times.insert_one({"date": aware_datetime})
56+
>>> db.times.find_one()["date"]
57+
datetime.datetime(2002, 10, 27, 14, 0)
58+
59+
Reading Time
60+
------------
61+
62+
By default, PyMongo retrieves "naive" ``datetime`` values, which show the time
63+
only in UTC. The ``bson.codec_options.CodecOptions``
64+
class contains a ``tz_aware`` option that enables
65+
"aware" ``datetime.datetime`` objects, which include a ``tzinfo`` property that
66+
shows the UTC time zone.
67+
68+
The following example stores a ``datetime`` value, then retrieves the value twice: once
69+
without the ``tz_aware`` option, and once with ``tz_aware=true``.
70+
71+
.. code-block:: python
72+
73+
>>> result = db.tzdemo.insert_one({"date": datetime.datetime(2002, 10, 27, 6, 0, 0)})
74+
>>> db.tzdemo.find_one()["date"]
75+
datetime.datetime(2002, 10, 27, 6, 0)
76+
>>> options = CodecOptions(tz_aware=True)
77+
>>> db.get_collection("tzdemo", codec_options=options).find_one()["date"]
78+
datetime.datetime(2002, 10, 27, 6, 0,
79+
tzinfo=<bson.tz_util.FixedOffset object at 0x10583a050>)
80+
81+
To automatically convert all times read from MongoDB to a specific time zone,
82+
call the ``CodecOptions()`` constructor and pass in the ``tz_aware`` and ``tzinfo``
83+
arguments. Pass your ``CodecOptions`` object to the ``with_options()`` method.
84+
85+
The following example shows how to automatically convert all times
86+
read MongoDB into US/Pacific time:
87+
88+
.. code-block::
89+
90+
>>> from bson.codec_options import CodecOptions
91+
>>> db.times.find_one()['date']
92+
datetime.datetime(2002, 10, 27, 14, 0)
93+
>>> aware_times = db.times.with_options(codec_options=CodecOptions(
94+
... tz_aware=True,
95+
... tzinfo=pytz.timezone('US/Pacific')))
96+
>>> result = aware_times.find_one()
97+
datetime.datetime(2002, 10, 27, 6, 0,
98+
tzinfo=<DstTzInfo 'US/Pacific' PST-1 day, 16:00:00 STD>)
99+
100+
.. _handling-out-of-range-datetimes:
101+
102+
Handling Out-of-Range datetimes
103+
-------------------------------
104+
105+
Python's ``~datetime.datetime`` can only represent ``datetime`` values within the
106+
range allowed by ``~datetime.datetime.min`` and ``~datetime.datetime.max``.
107+
BSON allows any 64-bit of milliseconds from the Unix epoch.
108+
109+
If you need represent a BSON time, you can use a
110+
``bson.datetime_ms.DatetimeMS`` object, a wrapper for the
111+
built-in ``int`` type.
112+
113+
To decode UTC datetime values as ``~bson.datetime_ms.DatetimeMS``,
114+
set the ``datetime_conversion`` parameter of ``~bson.codec_options.CodecOptions``
115+
to one of the following values from ``bson.datetime_ms.DatetimeConversion``:
116+
117+
- ``~bson.datetime_ms.DatetimeConversion.DATETIME``
118+
- ``~bson.datetime_ms.DatetimeConversion.DATETIME_MS``
119+
- ``~bson.datetime_ms.DatetimeConversion.DATETIME_AUTO``
120+
- ``~bson.datetime_ms.DatetimeConversion.DATETIME_CLAMP``
121+
122+
The default value, ``~bson.datetime_ms.DatetimeConversion.DATETIME``,
123+
raises an ``~builtin.OverflowError`` upon attempting to decode an out-of-range date.
124+
125+
``~bson.datetime_ms.DatetimeConversion.DATETIME_MS`` returns only
126+
``~bson.datetime_ms.DatetimeMS`` objects, regardless of whether the
127+
represented datetime is in out-of-range:
128+
129+
.. code-block:: python
130+
131+
>>> from datetime import datetime
132+
>>> from bson import encode, decode
133+
>>> from bson.datetime_ms import DatetimeMS
134+
>>> from bson.codec_options import CodecOptions, DatetimeConversion
135+
>>> x = encode({"x": datetime(1970, 1, 1)})
136+
>>> codec_ms = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_MS)
137+
>>> decode(x, codec_options=codec_ms)
138+
{'x': DatetimeMS(0)}
139+
140+
``~bson.datetime_ms.DatetimeConversion.DATETIME_AUTO`` returns
141+
``~datetime.datetime`` if the underlying UTC datetime is within range,
142+
or ``~bson.datetime_ms.DatetimeMS`` if the underlying datetime
143+
cannot be represented using the built-in Python ``~datetime.datetime``:
144+
145+
.. code-block:: python
146+
147+
>>> x = encode({"x": datetime(1970, 1, 1)})
148+
>>> y = encode({"x": DatetimeMS(-(2**62))})
149+
>>> codec_auto = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_AUTO)
150+
>>> decode(x, codec_options=codec_auto)
151+
{'x': datetime.datetime(1970, 1, 1, 0, 0)}
152+
>>> decode(y, codec_options=codec_auto)
153+
{'x': DatetimeMS(-4611686018427387904)}
154+
155+
``~bson.datetime_ms.DatetimeConversion.DATETIME_CLAMP`` "clamps"
156+
the resulting ``~datetime.datetime`` objects, forcing them to be within
157+
the ``~datetime.datetime.min`` and ``~datetime.datetime.max`` boundaries
158+
(trimmed to ``999000`` microseconds):
159+
160+
.. code-block:: python
161+
162+
>>> x = encode({"x": DatetimeMS(2**62)})
163+
>>> y = encode({"x": DatetimeMS(-(2**62))})
164+
>>> codec_clamp = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_CLAMP)
165+
>>> decode(x, codec_options=codec_clamp)
166+
{'x': datetime.datetime(9999, 12, 31, 23, 59, 59, 999000)}
167+
>>> decode(y, codec_options=codec_clamp)
168+
{'x': datetime.datetime(1, 1, 1, 0, 0)}
169+
170+
``~bson.datetime_ms.DatetimeMS`` objects support rich comparison
171+
methods against other instances of ``~bson.datetime_ms.DatetimeMS``.
172+
They can also be converted to ``~datetime.datetime`` objects by using
173+
the ``~bson.datetime_ms.DatetimeMS.to_datetime()`` method.

source/fundamentals/datetimes-and-timezones.txt

Lines changed: 0 additions & 183 deletions
This file was deleted.

0 commit comments

Comments
 (0)