DateTimeField now auto converts valid datetime isostrings into dates (#343)
This commit is contained in:
parent
f1b97fbc8b
commit
5447c6e947
@ -5,6 +5,8 @@ Changelog
|
|||||||
|
|
||||||
Changes in 0.8.2
|
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)
|
- Fixed Doc.objects(read_preference=X) not setting read preference (#352)
|
||||||
- Django session ttl index expiry fixed (#329)
|
- Django session ttl index expiry fixed (#329)
|
||||||
- Fixed pickle.loads (#342)
|
- Fixed pickle.loads (#342)
|
||||||
|
@ -7,6 +7,7 @@ import urllib2
|
|||||||
import uuid
|
import uuid
|
||||||
import warnings
|
import warnings
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import dateutil
|
import dateutil
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -353,6 +354,11 @@ class BooleanField(BaseField):
|
|||||||
class DateTimeField(BaseField):
|
class DateTimeField(BaseField):
|
||||||
"""A datetime field.
|
"""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.
|
Note: Microseconds are rounded to the nearest millisecond.
|
||||||
Pre UTC microsecond support is effecively broken.
|
Pre UTC microsecond support is effecively broken.
|
||||||
Use :class:`~mongoengine.fields.ComplexDateTimeField` if you
|
Use :class:`~mongoengine.fields.ComplexDateTimeField` if you
|
||||||
@ -360,13 +366,11 @@ class DateTimeField(BaseField):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def validate(self, value):
|
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)
|
self.error(u'cannot parse date "%s"' % value)
|
||||||
|
|
||||||
def to_mongo(self, value):
|
def to_mongo(self, value):
|
||||||
return self.prepare_query_value(None, value)
|
|
||||||
|
|
||||||
def prepare_query_value(self, op, value):
|
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
if isinstance(value, datetime.datetime):
|
if isinstance(value, datetime.datetime):
|
||||||
@ -376,10 +380,16 @@ class DateTimeField(BaseField):
|
|||||||
if callable(value):
|
if callable(value):
|
||||||
return value()
|
return value()
|
||||||
|
|
||||||
|
if not isinstance(value, basestring):
|
||||||
|
return None
|
||||||
|
|
||||||
# Attempt to parse a datetime:
|
# Attempt to parse a datetime:
|
||||||
if dateutil:
|
if dateutil:
|
||||||
return dateutil.parser.parse(value)
|
try:
|
||||||
# value = smart_str(value)
|
return dateutil.parser.parse(value)
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
# split usecs, because they are not recognized by strptime.
|
# split usecs, because they are not recognized by strptime.
|
||||||
if '.' in value:
|
if '.' in value:
|
||||||
try:
|
try:
|
||||||
@ -404,6 +414,9 @@ class DateTimeField(BaseField):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def prepare_query_value(self, op, value):
|
||||||
|
return self.to_mongo(value)
|
||||||
|
|
||||||
|
|
||||||
class ComplexDateTimeField(StringField):
|
class ComplexDateTimeField(StringField):
|
||||||
"""
|
"""
|
||||||
|
2
setup.py
2
setup.py
@ -57,7 +57,7 @@ if sys.version_info[0] == 3:
|
|||||||
extra_opts['packages'].append("tests")
|
extra_opts['packages'].append("tests")
|
||||||
extra_opts['package_data'] = {"tests": ["fields/mongoengine.png", "fields/mongodb_leaf.png"]}
|
extra_opts['package_data'] = {"tests": ["fields/mongoengine.png", "fields/mongodb_leaf.png"]}
|
||||||
else:
|
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',))
|
extra_opts['packages'] = find_packages(exclude=('tests',))
|
||||||
|
|
||||||
setup(name='mongoengine',
|
setup(name='mongoengine',
|
||||||
|
@ -408,9 +408,16 @@ class FieldTest(unittest.TestCase):
|
|||||||
log.time = datetime.date.today()
|
log.time = datetime.date.today()
|
||||||
log.validate()
|
log.validate()
|
||||||
|
|
||||||
|
log.time = datetime.datetime.now().isoformat(' ')
|
||||||
|
log.validate()
|
||||||
|
|
||||||
|
if dateutil:
|
||||||
|
log.time = datetime.datetime.now().isoformat('T')
|
||||||
|
log.validate()
|
||||||
|
|
||||||
log.time = -1
|
log.time = -1
|
||||||
self.assertRaises(ValidationError, log.validate)
|
self.assertRaises(ValidationError, log.validate)
|
||||||
log.time = '1pm'
|
log.time = 'ABC'
|
||||||
self.assertRaises(ValidationError, log.validate)
|
self.assertRaises(ValidationError, log.validate)
|
||||||
|
|
||||||
def test_datetime_tz_aware_mark_as_changed(self):
|
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)
|
d1 = datetime.datetime(1970, 01, 01, 00, 00, 01)
|
||||||
log = LogEntry()
|
log = LogEntry()
|
||||||
log.date = d1
|
log.date = d1
|
||||||
|
log.validate()
|
||||||
log.save()
|
log.save()
|
||||||
|
|
||||||
for query in (d1, d1.isoformat(' ')):
|
for query in (d1, d1.isoformat(' ')):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user