Re: worse date converter

Christopher Singley <[email protected]> Sat, 6 Sep 2008 21:09:10 -0500
Newsgroups gmane.comp.python.formencode
Message-ID <[email protected]>
Matthew,

In ascending order of significance:

First, starting with 2.5, you don't need to import the time module.  You can 
just write "return datetime.datetime.strptime(value, datefmt).date()".

Second, it looks like your from_python() is broken as written.

Third, I usually prefer to extend validators.DateConverter, rather than 
replace it, in keeping with other parts of FormEncode.  For this I employ the 
builtin super() command, e.g.:

<code>
class WorseDateConverter(validators.DateConverter):
    """
    Accepts '-' or '/' as delimiters.
    """
    month_style = 'dd/mm/yyyy'

    def _to_python(self, value, state):
        value = value.replace('-', '/')
        return super(WorseDateConverter, self)._to_python(value, state)
</code>

This allows me just to free-ride on more robustly tested code (i.e. said 
enormous regexes).

Fourth, I too have wondered at DateConverter's lack of support for ISO 8601 
format.  I've knocked up stuff like this:

<code>
class IsoFormatDateConverter(validators.DateConverter):
    """
    Like formencode.validators.DateConverter, but accepts ISO 8601 YYYY-mm-dd
    """
    month_style = 'dd/mm/yyyy'
    regex = re.compile('\d{8,8}')

    def _to_python(self, value, state):
        # Transform from extended to basic format (yyyymmdd...)
        value = value.replace('-', '')
        try:
            value = value[:8]
            assert self.regex.match(value)
        except:
            raise Invalid(("Input must be ISO 8601 format, not %s" % value), 
value, state)
        # Transform to 'dd/mm/yyyy'
        value = '/'.join((value[6:8], value[4:6], value[:4]))
        # Run superclass validation on preprocessed value
        return super(IsoFormatDateConverter, self)._to_python(value, state)
</code>
On Saturday 06 September 2008 19:45:34 Matthew Wilson wrote:
> Hi, I needed a way to convert some strings into dates, but the strings
> wouldn't be in the formats acceptable to the current dateconverter
> validator.
>
> Originally, I tried looking into the dateconverter so I could add
> another date format that it could support, but then I got scared by
> those enormous regular expressions and decided to go with this
> approach.  Anyhow, feedback is welcome.
>
> from time import strptime
> from formencode import Invalid
> from formencode.validators import FancyValidator
>
> class WorseDateConverter(FancyValidator):
>
>     """
>     Requires a list of valid date format strings.
>
>         >>> wdc = WorseDateConverter(['%m-%d-%Y',  '%m/%d/%Y', '%Y-%m-%d'])
>         >>> wdc.to_python('09-06-2008')
>
>         datetime.date(2008, 9, 6)
>
>         >>> wdc.to_python('09/06/2008')
>
>         datetime.date(2008, 9, 6)
>
>         >>> wdc.to_python('2008-09-06')
>
>         datetime.date(2008, 9, 6)
>
>         >>> wdc.to_python('2008/09/06') # slashes instead of dashes.
>
>         Traceback (most recent call last):
>             ...
>         Invalid: I couldn't parse 2008/09/06 with any of my formats!
>     """
>
>     def __init__(self, dateformats):
>         self.dateformats = dateformats
>
>     def to_python(self, value, state=None):
>
>         for datefmt in self.dateformats:
>
>             try:
>                 tt = strptime(value, datefmt)
>                 return date(tt.tm_year, tt.tm_mon, tt.tm_mday)
>
>             except ValueError:
>                 pass
>
>         else:
>             msg = ("I couldn't parse %s with any of my formats!"
>                 % (value))
>
>             raise Invalid(msg, value, state)
>
>     def from_python(self, value, state=None):
>         return value.strftime(self.datefmt)



-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/