From 3e25eace63eef30662484354593ee18257f2b560 Mon Sep 17 00:00:00 2001 From: Michael Overmeyer Date: Tue, 22 Nov 2022 19:06:43 -0500 Subject: [PATCH] Update benchmark numbers --- README.rst | 186 +++++++++++++++++++++++++++-------------------------- 1 file changed, 95 insertions(+), 91 deletions(-) diff --git a/README.rst b/README.rst index c410d9b..2cdc99f 100644 --- a/README.rst +++ b/README.rst @@ -32,7 +32,7 @@ Tested with cPython 2.7, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11. .. contents:: Contents -Quick Start +Quick start ----------- .. code:: bash @@ -57,14 +57,14 @@ See `CHANGELOG`_ for the Migration Guide. .. _CHANGELOG: https://github.com/closeio/ciso8601/blob/master/CHANGELOG.md -When should I not use ``cis8601``? ----------------------------------- +When should I not use ``ciso8601``? +----------------------------------- ``ciso8601`` is not necessarily the best solution for every use case (especially since Python 3.11). See `Should I use ciso8601?`_ .. _`Should I use ciso8601?`: https://github.com/closeio/ciso8601/blob/master/why_ciso8601.md -Error Handling +Error handling -------------- Starting in v2.0.0, ``ciso8601`` offers strong guarantees when it comes to parsing strings. @@ -85,41 +85,43 @@ Parsing a timestamp with no time zone information (e.g., ``2014-01-09T21:48:00`` .. table:: - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - | Module |Python 3.10|Python 3.9|Python 3.8|Python 3.7|Python 3.6|Python 3.5| Python 2.7 |Relative Slowdown (versus ciso8601, latest Python)| - +==================+===========+==========+==========+==========+==========+==========+===============================+==================================================+ - |ciso8601 |147 nsec |135 nsec |150 nsec |143 nsec |131 nsec |155 nsec |159 nsec |N/A | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |pendulum |162 nsec |151 nsec |166 nsec |162 nsec |172 nsec |176 nsec |7.77 usec |1.1x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |udatetime |N/A |N/A |724 nsec |737 nsec |731 nsec |751 nsec |678 nsec |4.8x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |str2date |5.91 usec |6.06 usec |5.17 usec |6.2 usec |6.49 usec |9.05 usec |**Incorrect Result** (``None``)|40.1x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |iso8601 |7.99 usec |8.16 usec |7.32 usec |8.74 usec |8.92 usec |12.7 usec |25 usec |54.2x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |iso8601utils |N/A |8 usec |7.87 usec |9.02 usec |N/A |12.5 usec |10.9 usec |59.3x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |isodate |8.76 usec |9.49 usec |8.78 usec |10.3 usec |10.8 usec |13.6 usec |44.1 usec |59.4x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |PySO8601 |14.9 usec |15.4 usec |14.2 usec |16 usec |16.3 usec |19.8 usec |16.7 usec |101.2x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |zulu |21.9 usec |21.6 usec |20.1 usec |22.9 usec |25 usec |N/A |N/A |148.2x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |aniso8601 |23.9 usec |24.2 usec |22.5 usec |28 usec |29.7 usec |34.6 usec |30.3 usec |161.8x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |maya |47.8 usec |47.8 usec |43.6 usec |47.6 usec |55.6 usec |77.1 usec |68.2 usec |324.1x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |python-dateutil |62.3 usec |65.9 usec |58 usec |73.2 usec |76.3 usec |96.2 usec |132 usec |422.3x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |arrow |71.6 usec |67 usec |65.4 usec |75 usec |73.9 usec |96.2 usec |83.6 usec |485.4x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |moment |1.43 msec |1.4 msec |1.3 msec |1.56 msec |1.39 msec |1.78 msec |2.26 msec |9666.4x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - |metomi-isodatetime|1.72 msec |1.64 msec |1.63 msec |2.02 msec |1.77 msec |2.15 msec |N/A |11674.2x | - +------------------+-----------+----------+----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ - -ciso8601 takes 147 nsec, which is **1.1x faster than pendulum**, the next fastest ISO 8601 parser in this comparison. + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + | Module |Python 3.11|Python 3.10|Python 3.9|Python 3.8|Python 3.7| Python 2.7 |Relative Slowdown (versus ciso8601, latest Python)| + +==================+===========+===========+==========+==========+==========+===============================+==================================================+ + |ciso8601 |94.3 nsec |115 nsec |114 nsec |109 nsec |153 nsec |141 nsec |N/A | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |datetime (builtin)|125 nsec |N/A |N/A |N/A |N/A |N/A |1.3x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |pendulum |266 nsec |227 nsec |240 nsec |231 nsec |226 nsec |10.4 usec |2.8x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |udatetime |684 nsec |679 nsec |717 nsec |759 nsec |754 nsec |635 nsec |7.3x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |str2date |6.18 usec |7.08 usec |7.58 usec |6.59 usec |6.91 usec |**Incorrect Result** (``None``)|65.6x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |iso8601utils |N/A |N/A |9.17 usec |9.38 usec |10.1 usec |12.1 usec |80.7x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |isodate |10 usec |11.5 usec |13.2 usec |13.2 usec |22.8 usec |45 usec |106.4x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |iso8601 |14 usec |11.7 usec |10.7 usec |12.4 usec |20.9 usec |27.2 usec |148.3x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |PySO8601 |16 usec |20.6 usec |21.1 usec |19.4 usec |20.6 usec |25.3 usec |169.5x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |aniso8601 |17.3 usec |22.9 usec |24.3 usec |23.9 usec |29.7 usec |34.7 usec |184.0x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |zulu |20.8 usec |22.9 usec |22.9 usec |21.8 usec |26.2 usec |N/A |220.8x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |maya |39.5 usec |43.7 usec |44.6 usec |46.2 usec |44.8 usec |N/A |419.5x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |python-dateutil |51.4 usec |61.6 usec |102 usec |61.7 usec |122 usec |124 usec |545.3x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |arrow |56.7 usec |70.7 usec |72.4 usec |70.5 usec |73.5 usec |83.7 usec |602.1x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |metomi-isodatetime|1.41 msec |1.84 msec |2.18 msec |2.14 msec |2.18 msec |N/A |14971.6x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + |moment |1.84 msec |1.85 msec |2.04 msec |2.08 msec |2.17 msec |N/A |19489.6x | + +------------------+-----------+-----------+----------+----------+----------+-------------------------------+--------------------------------------------------+ + +ciso8601 takes 94.3 nsec, which is **1.3x faster than datetime (builtin)**, the next fastest ISO 8601 parser in this comparison. .. @@ -129,64 +131,66 @@ Parsing a timestamp with time zone information (e.g., ``2014-01-09T21:48:00-05:3 .. table:: - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - | Module | Python 3.10 | Python 3.9 | Python 3.8 | Python 3.7 | Python 3.6 | Python 3.5 | Python 2.7 |Relative Slowdown (versus ciso8601, latest Python)| - +==================+===============================+===============================+===============================+===============================+===============================+===============================+===============================+==================================================+ - |ciso8601 |159 nsec |143 nsec |156 nsec |149 nsec |142 nsec |154 nsec |190 nsec |N/A | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |pendulum |193 nsec |181 nsec |201 nsec |183 nsec |172 nsec |191 nsec |12.6 usec |1.2x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |udatetime |N/A |N/A |907 nsec |947 nsec |953 nsec |986 nsec |892 nsec |5.8x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |str2date |7.5 usec |7.76 usec |6.92 usec |7.77 usec |7.98 usec |10.7 usec |**Incorrect Result** (``None``)|47.0x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |iso8601 |12.4 usec |12.4 usec |11.2 usec |12.4 usec |12.7 usec |18.8 usec |30.5 usec |77.9x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |isodate |12.7 usec |12.9 usec |11.5 usec |13.7 usec |14.5 usec |18.2 usec |48.8 usec |79.8x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |iso8601utils |N/A |22.2 usec |21 usec |25.6 usec |N/A |34.2 usec |28.1 usec |155.3x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |PySO8601 |24.4 usec |24.9 usec |21.7 usec |24.9 usec |25.3 usec |30.9 usec |26.3 usec |153.0x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |zulu |25.9 usec |25.5 usec |24.1 usec |26.7 usec |30.5 usec |N/A |N/A |162.3x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |aniso8601 |32.9 usec |35.1 usec |32.6 usec |40 usec |40.7 usec |47.7 usec |42.1 usec |206.6x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |maya |50.9 usec |49.7 usec |44.1 usec |50.5 usec |58.4 usec |78.8 usec |76.2 usec |319.2x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |arrow |83.3 usec |84.3 usec |79 usec |92.9 usec |89.3 usec |116 usec |109 usec |522.0x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |python-dateutil |83.8 usec |86 usec |81.1 usec |94.3 usec |97 usec |126 usec |161 usec |525.2x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |metomi-isodatetime|1.77 msec |1.76 msec |1.63 msec |2.06 msec |1.81 msec |2.31 msec |N/A |11128.2x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - |moment |**Incorrect Result** (``None``)|**Incorrect Result** (``None``)|**Incorrect Result** (``None``)|**Incorrect Result** (``None``)|**Incorrect Result** (``None``)|**Incorrect Result** (``None``)|**Incorrect Result** (``None``)|1126277.5x | - +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ - -ciso8601 takes 159 nsec, which is **1.2x faster than pendulum**, the next fastest ISO 8601 parser in this comparison. + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + | Module | Python 3.11 | Python 3.10 | Python 3.9 | Python 3.8 | Python 3.7 | Python 2.7 |Relative Slowdown (versus ciso8601, latest Python)| + +==================+===============================+===============================+===============================+===============================+===============================+===============================+==================================================+ + |ciso8601 |103 nsec |163 nsec |133 nsec |137 nsec |146 nsec |147 nsec |N/A | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |datetime (builtin)|201 nsec |N/A |N/A |N/A |N/A |N/A |1.9x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |pendulum |247 nsec |235 nsec |286 nsec |238 nsec |250 nsec |16.7 usec |2.4x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |udatetime |812 nsec |843 nsec |835 nsec |824 nsec |1.07 usec |781 nsec |7.9x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |str2date |7.16 usec |8.79 usec |8.37 usec |8.21 usec |10.4 usec |**Incorrect Result** (``None``)|69.2x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |iso8601 |12.1 usec |14.2 usec |13.6 usec |20.2 usec |17.2 usec |36.7 usec |117.5x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |PySO8601 |21.8 usec |26.1 usec |27.4 usec |25.1 usec |28.8 usec |31 usec |210.4x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |isodate |23.8 usec |14.1 usec |22.2 usec |15.2 usec |17.7 usec |48.1 usec |229.8x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |aniso8601 |25.3 usec |34.5 usec |38.7 usec |33.5 usec |41.2 usec |41.5 usec |244.3x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |iso8601utils |N/A |N/A |28 usec |23.6 usec |28.1 usec |29.7 usec |211.0x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |zulu |28.5 usec |27.1 usec |31.6 usec |27.5 usec |31.3 usec |N/A |275.6x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |maya |49.9 usec |158 usec |54 usec |44.8 usec |47 usec |N/A |482.9x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |python-dateutil |71.1 usec |83.5 usec |95.4 usec |116 usec |106 usec |184 usec |687.8x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |arrow |80.3 usec |78.1 usec |113 usec |80.1 usec |86.8 usec |363 usec |776.6x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |metomi-isodatetime|1.35 msec |1.83 msec |1.85 msec |1.82 msec |2.16 msec |N/A |13021.3x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + |moment |**Incorrect Result** (``None``)|**Incorrect Result** (``None``)|**Incorrect Result** (``None``)|**Incorrect Result** (``None``)|**Incorrect Result** (``None``)|N/A |2263591.3x | + +------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+--------------------------------------------------+ + +ciso8601 takes 103 nsec, which is **1.9x faster than datetime (builtin)**, the next fastest ISO 8601 parser in this comparison. .. .. -Tested on Linux 5.10.16.3-microsoft-standard-WSL2 using the following modules: +Tested on Linux 5.15.49-linuxkit using the following modules: .. code:: python aniso8601==9.0.1 - arrow==0.17.0 (on Python 2.7, 3.5), arrow==1.2.1 (on Python 3.10, 3.6, 3.7, 3.8, 3.9) - ciso8601==2.2.0 - iso8601==0.1.16 (on Python 2.7, 3.5), iso8601==1.0.0 (on Python 3.10, 3.6, 3.7, 3.8, 3.9) + arrow==0.17.0 (on Python 2.7), arrow==1.2.3 (on Python 3.7, 3.8, 3.9, 3.10, 3.11) + ciso8601==2.3.0 + iso8601==0.1.16 (on Python 2.7), iso8601==1.1.0 (on Python 3.7, 3.8, 3.9, 3.10, 3.11) iso8601utils==0.1.2 - isodate==0.6.0 + isodate==0.6.1 maya==0.6.1 - metomi-isodatetime==1!2.0.2 + metomi-isodatetime==1!3.0.0 moment==0.12.1 pendulum==2.1.2 PySO8601==0.2.0 python-dateutil==2.8.2 str2date==0.905 - udatetime==0.0.16 + udatetime==0.0.17 zulu==2.0.0 .. @@ -197,12 +201,12 @@ For full benchmarking details (or to run the benchmark yourself), see `benchmark .. _`benchmarking/README.rst`: https://github.com/closeio/ciso8601/blob/master/benchmarking/README.rst -Supported Subset of ISO 8601 +Supported subset of ISO 8601 ---------------------------- ``ciso8601`` only supports the most common subset of ISO 8601. -Date Formats +Date formats ^^^^^^^^^^^^ The following date formats are supported: @@ -215,7 +219,7 @@ The following date formats are supported: ============================= ============== ================== ``YYYY-MM-DD`` ``2018-04-29`` ✅ ``YYYY-MM`` ``2018-04`` ✅ - ``YYYYMMDD`` ``20180429`` ✅ + ``YYYYMMDD`` ``20180429`` ✅ ``--MM-DD`` (omitted year) ``--04-29`` ❌ ``--MMDD`` (omitted year) ``--0429`` ❌ ``±YYYYY-MM`` (>4 digit year) ``+10000-04`` ❌ @@ -239,12 +243,12 @@ Week dates or ordinal dates are not currently supported. ``YYYYDDD`` (ordinal date) ``1981095`` ❌ ============================= ============== ================== -Time Formats +Time formats ^^^^^^^^^^^^ Times are optional and are separated from the date by the letter ``T``. -Consistent with `RFC 3339`__, ``ciso860`` also allows either a space character, or a lower-case ``t``, to be used instead of a ``T``. +Consistent with `RFC 3339`__, ``ciso8601`` also allows either a space character, or a lower-case ``t``, to be used instead of a ``T``. __ https://stackoverflow.com/questions/522251/whats-the-difference-between-iso-8601-and-rfc-3339-date-formats @@ -272,7 +276,7 @@ The following time formats are supported: **Note:** Python datetime objects only have microsecond precision (6 digits). Any additional precision will be truncated. -Time Zone Information +Time zone information ^^^^^^^^^^^^^^^^^^^^^ Time zone information may be provided in one of the following formats: @@ -292,9 +296,9 @@ Time zone information may be provided in one of the following formats: While the ISO 8601 specification allows the use of MINUS SIGN (U+2212) in the time zone separator, ``ciso8601`` only supports the use of the HYPHEN-MINUS (U+002D) character. -Consistent with `RFC 3339`_, ``ciso860`` also allows a lower-case ``z`` to be used instead of a ``Z``. +Consistent with `RFC 3339`_, ``ciso8601`` also allows a lower-case ``z`` to be used instead of a ``Z``. -Strict RFC 3339 Parsing +Strict RFC 3339 parsing ----------------------- ``ciso8601`` parses ISO 8601 datetimes, which can be thought of as a superset of `RFC 3339`_ (`roughly`_). In cases where you might want strict RFC 3339 parsing, ``ciso8601`` offers a ``parse_rfc3339`` method, which behaves in a similar manner to ``parse_datetime``: @@ -306,8 +310,8 @@ Strict RFC 3339 Parsing * Returns a properly parsed Python datetime, **if and only if** the **entire** string conforms to RFC 3339. * Raises a ``ValueError`` with a description of the reason why the string doesn't conform to RFC 3339. -Ignoring Timezone Information While Parsing -------------------------------------------- +Ignoring time zone information while parsing +-------------------------------------------- It takes more time to parse timestamps with time zone information, especially if they're not in UTC. However, there are times when you don't care about time zone information, and wish to produce naive datetimes instead. For example, if you are certain that your program will only parse timestamps from a single time zone, you might want to strip the time zone information and only output naive datetimes.