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

11,067

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.

Share:
11,067
alexferl
Author by

alexferl

Updated on June 04, 2022

Comments

  • alexferl
    alexferl almost 2 years

    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?

  • alexferl
    alexferl almost 11 years
    Thank you! I understand now. I inserted my date with datetime.datetime.utcnow() which MongoDB via PyMongo understood is a date object (ISODate()) so it saved it as a date object. So when I query the document for the date, I get a date object returned to me as well. For the record, I fixed it by replacing the last two rows of my function with this line: return timestamp.replace(tzinfo=pytz.utc).strftime("%Y-%m-%d @ %H:%M:%S")