diff --git a/scrapy/contrib_exp/newitem/fields.py b/scrapy/contrib_exp/newitem/fields.py index 5e6da037b..c0f1c5266 100644 --- a/scrapy/contrib_exp/newitem/fields.py +++ b/scrapy/contrib_exp/newitem/fields.py @@ -1,10 +1,11 @@ import datetime import decimal import re +import time -__all__ = ['MultiValuedField', 'BooleanField', 'DateField', 'DecimalField', - 'FloatField', 'IntegerField', 'StringField'] +__all__ = ['MultiValuedField', 'BooleanField', 'DateField', 'DateTimeField', + 'DecimalField', 'FloatField', 'IntegerField', 'StringField'] class FieldValueError(Exception): @@ -79,6 +80,43 @@ class DateField(Field): raise FieldValueError("Invalid date: %s" % str(e)) +class DateTimeField(Field): + def to_python(self, value): + if value is None: + return value + if isinstance(value, datetime.datetime): + return value + if isinstance(value, datetime.date): + return datetime.datetime(value.year, value.month, value.day) + + # Attempt to parse a datetime: + value = str(value) + # split usecs, because they are not recognized by strptime. + if '.' in value: + try: + value, usecs = value.split('.') + usecs = int(usecs) + except ValueError: + raise FieldValueError('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.') + else: + usecs = 0 + kwargs = {'microsecond': usecs} + try: # Seconds are optional, so try converting seconds first. + return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6], + **kwargs) + + except ValueError: + try: # Try without seconds. + return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5], + **kwargs) + except ValueError: # Try without hour/minutes/seconds. + try: + return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3], + **kwargs) + except ValueError: + raise FieldValueError('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.') + + class DecimalField(Field): def to_python(self, value): if value is None: diff --git a/scrapy/tests/test_newitem.py b/scrapy/tests/test_newitem.py index 34da14c62..203fa332a 100644 --- a/scrapy/tests/test_newitem.py +++ b/scrapy/tests/test_newitem.py @@ -56,6 +56,30 @@ class NewItemFieldsTest(unittest.TestCase): i.field = '2009-05-21' assert i.field == datetime.date(2009, 5, 21) + def test_datetime_field(self): + class TestItem(Item): + field = DateTimeField() + + i = TestItem() + + dt_today = datetime.datetime.today() + i.field = dt_today + assert i.field == dt_today + + d_today = datetime.date.today() + i.field = d_today + assert i.field == datetime.datetime(d_today.year, d_today.month, + d_today.day) + + i.field = '2009-05-21 11:08:10' + assert i.field == datetime.datetime(2009, 5, 21, 11, 8, 10) + + i.field = '2009-05-21 11:08' + assert i.field == datetime.datetime(2009, 5, 21, 11, 8) + + i.field = '2009-05-21' + assert i.field == datetime.datetime(2009, 5, 21) + def test_decimal_field(self): class TestItem(Item): field = DecimalField()