Skip to content

Commit 65da210

Browse files
Ruben Di Battistadjc
authored andcommitted
Add microseconds support for DateTimeField (#293)
* Add microseconds support for DateTimeField A check is introduced in the DateTimeField to understand if microseconds are provided in the datetime string or not. The return value is then handled in accordance to that check. Tests related to the feature implemented are also introduced. Doctest examples are updated too. * Add microseconds support for DateTimeField A check is introduced in the DateTimeField to understand if microseconds are provided in the datetime string or not. The return value is then handled in accordance to that check. Tests related to the feature implemented are also introduced. Doctest examples are updated too.
1 parent 411ef7b commit 65da210

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

couchdb/mapping.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -474,22 +474,32 @@ def _to_json(self, value):
474474

475475
class DateTimeField(Field):
476476
"""Mapping field for storing date/time values.
477-
477+
478478
>>> field = DateTimeField()
479479
>>> field._to_python('2007-04-01T15:30:00Z')
480480
datetime.datetime(2007, 4, 1, 15, 30)
481-
>>> field._to_json(datetime(2007, 4, 1, 15, 30, 0, 9876))
481+
>>> field._to_python('2007-04-01T15:30:00.009876Z')
482+
datetime.datetime(2007, 4, 1, 15, 30, 0, 9876)
483+
>>> field._to_json(datetime(2007, 4, 1, 15, 30, 0))
482484
'2007-04-01T15:30:00Z'
485+
>>> field._to_json(datetime(2007, 4, 1, 15, 30, 0, 9876))
486+
'2007-04-01T15:30:00.009876Z'
483487
>>> field._to_json(date(2007, 4, 1))
484488
'2007-04-01T00:00:00Z'
485489
"""
486490

487491
def _to_python(self, value):
488492
if isinstance(value, util.strbase):
489493
try:
490-
value = value.split('.', 1)[0] # strip out microseconds
491-
value = value.rstrip('Z') # remove timezone separator
492-
value = datetime(*strptime(value, '%Y-%m-%dT%H:%M:%S')[:6])
494+
split_value = value.split('.') # strip out microseconds
495+
if len(split_value) == 1: # No microseconds provided
496+
value = split_value[0]
497+
value = value.rstrip('Z') #remove timezone separator
498+
value = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S')
499+
else:
500+
value = value.rstrip('Z')
501+
value = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%f')
502+
493503
except ValueError:
494504
raise ValueError('Invalid ISO date/time %r' % value)
495505
return value
@@ -499,12 +509,12 @@ def _to_json(self, value):
499509
value = datetime.utcfromtimestamp(timegm(value))
500510
elif not isinstance(value, datetime):
501511
value = datetime.combine(value, time(0))
502-
return value.replace(microsecond=0).isoformat() + 'Z'
512+
return value.isoformat() + 'Z'
503513

504514

505515
class TimeField(Field):
506516
"""Mapping field for storing times.
507-
517+
508518
>>> field = TimeField()
509519
>>> field._to_python('15:30:00')
510520
datetime.time(15, 30)

couchdb/tests/mapping.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
from couchdb import design, mapping
1313
from couchdb.tests import testutil
14+
from datetime import datetime
1415

1516
class DocumentTestCase(testutil.TempDatabaseMixin, unittest.TestCase):
1617

@@ -83,6 +84,15 @@ def test_old_datetime(self):
8384
dt = mapping.DateTimeField()
8485
assert dt._to_python('1880-01-01T00:00:00Z')
8586

87+
def test_datetime_with_microseconds(self):
88+
dt = mapping.DateTimeField()
89+
assert dt._to_python('2016-06-09T21:21:49.739248Z')
90+
91+
def test_datetime_to_json(self):
92+
dt = mapping.DateTimeField()
93+
d = datetime.now()
94+
assert dt._to_json(d)
95+
8696
def test_get_has_default(self):
8797
doc = mapping.Document()
8898
doc.get('foo')

0 commit comments

Comments
 (0)