DateTimeField now auto converts valid datetime isostrings into dates (#343)

This commit is contained in:
Ross Lawley 2013-06-04 09:08:13 +00:00
parent f1b97fbc8b
commit 5447c6e947
4 changed files with 32 additions and 9 deletions

View File

@ -5,6 +5,8 @@ Changelog
Changes in 0.8.2
================
- DateTimeField now auto converts valid datetime isostrings into dates (#343)
- DateTimeField now uses dateutil for parsing if available (#343)
- Fixed Doc.objects(read_preference=X) not setting read preference (#352)
- Django session ttl index expiry fixed (#329)
- Fixed pickle.loads (#342)

View File

@ -7,6 +7,7 @@ import urllib2
import uuid
import warnings
from operator import itemgetter
try:
import dateutil
except ImportError:
@ -353,6 +354,11 @@ class BooleanField(BaseField):
class DateTimeField(BaseField):
"""A datetime field.
Uses the python-dateutil library if available alternatively use time.strptime
to parse the dates. Note: python-dateutil's parser is fully featured and when
installed you can utilise it to convert varing types of date formats into valid
python datetime objects.
Note: Microseconds are rounded to the nearest millisecond.
Pre UTC microsecond support is effecively broken.
Use :class:`~mongoengine.fields.ComplexDateTimeField` if you
@ -360,13 +366,11 @@ class DateTimeField(BaseField):
"""
def validate(self, value):
if not isinstance(value, (datetime.datetime, datetime.date)):
new_value = self.to_mongo(value)
if not isinstance(new_value, (datetime.datetime, datetime.date)):
self.error(u'cannot parse date "%s"' % value)
def to_mongo(self, value):
return self.prepare_query_value(None, value)
def prepare_query_value(self, op, value):
if value is None:
return value
if isinstance(value, datetime.datetime):
@ -376,10 +380,16 @@ class DateTimeField(BaseField):
if callable(value):
return value()
if not isinstance(value, basestring):
return None
# Attempt to parse a datetime:
if dateutil:
return dateutil.parser.parse(value)
# value = smart_str(value)
try:
return dateutil.parser.parse(value)
except ValueError:
return None
# split usecs, because they are not recognized by strptime.
if '.' in value:
try:
@ -404,6 +414,9 @@ class DateTimeField(BaseField):
except ValueError:
return None
def prepare_query_value(self, op, value):
return self.to_mongo(value)
class ComplexDateTimeField(StringField):
"""

View File

@ -57,7 +57,7 @@ if sys.version_info[0] == 3:
extra_opts['packages'].append("tests")
extra_opts['package_data'] = {"tests": ["fields/mongoengine.png", "fields/mongodb_leaf.png"]}
else:
extra_opts['tests_require'] = ['nose', 'coverage', 'blinker', 'django>=1.4.2', 'PIL', 'jinja2==2.6']
extra_opts['tests_require'] = ['nose', 'coverage', 'blinker', 'django>=1.4.2', 'PIL', 'jinja2==2.6', 'python-dateutil==1.5']
extra_opts['packages'] = find_packages(exclude=('tests',))
setup(name='mongoengine',

View File

@ -408,9 +408,16 @@ class FieldTest(unittest.TestCase):
log.time = datetime.date.today()
log.validate()
log.time = datetime.datetime.now().isoformat(' ')
log.validate()
if dateutil:
log.time = datetime.datetime.now().isoformat('T')
log.validate()
log.time = -1
self.assertRaises(ValidationError, log.validate)
log.time = '1pm'
log.time = 'ABC'
self.assertRaises(ValidationError, log.validate)
def test_datetime_tz_aware_mark_as_changed(self):
@ -497,6 +504,7 @@ class FieldTest(unittest.TestCase):
d1 = datetime.datetime(1970, 01, 01, 00, 00, 01)
log = LogEntry()
log.date = d1
log.validate()
log.save()
for query in (d1, d1.isoformat(' ')):