admiralobvious admiralobvious - 1 month ago 19
Python Question

"TypeError: must be string, not datetime.datetime" in Jinja2 template when using strftime

I'm trying to format dates generated with

datetime.datetime.utcnow()
(using this because it's the equivalent of
ISODate()
in MongoDB which is the database my app uses) in my Flask application but Jinja2 won't render them.

I have the following function in my app:

def format_isodate(timestamp):
"""Format a ISODate time stamp for display."""
date = datetime.datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S.%f")
return date.strftime('%Y-%m-%d @ %H:%M:%S')


The dates look like this:

"2013-07-04 20:06:05.088000"


And I have the following filter:

app.jinja_env.filters['isodateformat'] = format_isodate


But when I try to format the timestamp in templates:

{{ change.submit_date|isodateformat }}


I get this error:


"TypeError: must be string, not datetime.datetime"


I don't understand why I am getting this error. Doesn't
strftime()
convert dates to string?

Answer

The problem is that utcnow() returns a datetime.datetime object, not a string. If you check the line number in the exception, it’s likely the strptime call that’s failing—it can parse a string into a date, but it can’t parse a date.

Example:

#!/usr/bin/env python2.7

import datetime

import jinja2

def format_isodate(timestamp):
    """Format a ISODate time stamp for display."""
    date = datetime.datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S.%f")
    return date.strftime('%Y-%m-%d @ %H:%M:%S')

e = jinja2.Environment()
e.filters['isodateformat'] = format_isodate

t = e.from_string('{{ change.submit_date|isodateformat }}')
print t.render(change={'submit_date': "2013-07-04 20:06:05.088000"})
print t.render(change={'submit_date': datetime.datetime.now()})

The first print of a string succeeds, but the second one fails with TypeError: must be string, not datetime.datetime.

Comments