pyramiddeformcolander

How to format dates in colander validator?


User Pyramid, Colander, and Deform, I've got a datetime widget.

datetime_event = colander.SchemaNode(
    colander.DateTime(),
    validator=colander.Range(
        min=datetime(
            2018, 1, 1, 0, 0,
            tzinfo=timezone.utc),
        min_err=(
            '${val} must be after ${min}'),
        max=datetime.now(timezone.utc),
        max_err=(
            '${val} is in the future, and must be less than ${max}')
    ),
)

I get this user-hostile validation error message.

2017-08-21 05:00:00-07:53 must be after 2018-01-01 00:00:00+00:00

I'd like to format the date without the timezone stuff:

2017-08-21 05:00:00 must be after 2018-01-01 00:00:00

Or better yet:

21 Aug 2017 5:00 AM must be after 1 Jan 2018 12:00 AM

If possible, how would I format the datetime objects in min_err and max_err?


Solution

  • Here's what I eventually used. The key was not to use the default variable ${val} and use plain old Python f-strings.

    tz = self.tz
    days_before = 28
    dtmin = local_days_before(tz, days_before)  # localized min date
    dtmax = datetime.now(utc).astimezone(tz)
    datetime_event = colander.SchemaNode(
        colander.DateTime(default_tzinfo=dtmax.tzinfo),
        widget=deform.widget.DateTimeInputWidget(
            date_options={'min': -days_before,
                          'max': True,
                          'format': 'yyyy-mm-dd'},
            time_options={'format': 'HH:i',
                          'formatLabel': 'HH:i'},
        ),
        validator=colander.Range(
            min=dtmin,
            min_err=(f"Datetime must be after "
                     f"{dtmin:%B %d, %Y, %-I:%M %p} "),
            max=dtmax,
            max_err=(f"Datetime must be before "
                     f"{dtmax: %B %d, %Y, %-I:%M %p}")
        ),
        title='Date and Time',
        description='Date and time when the event occurred'
    )
    

    This solution also implements formatting of the date and time, and min and max dates in the pickadate UI.