¿Cómo formateo una fecha en Jinja2?

183

Usando Jinja2, ¿cómo formateo un campo de fecha? Sé que en Python simplemente puedo hacer esto:

print(car.date_of_manufacture.strftime('%Y-%m-%d'))

Pero, ¿cómo formateo la fecha en Jinja2?

Ambrosio
fuente

Respuestas:

327

Hay dos maneras de hacerlo. El enfoque directo sería simplemente llamar (e imprimir) el método strftime () en su plantilla, por ejemplo

{{ car.date_of_manufacture.strftime('%Y-%m-%d') }}

Otro enfoque visualmente mejor sería definir su propio filtro, por ejemplo:

from flask import Flask
import babel

app = Flask(__name__)

@app.template_filter()
def format_datetime(value, format='medium'):
    if format == 'full':
        format="EEEE, d. MMMM y 'at' HH:mm"
    elif format == 'medium':
        format="EE dd.MM.y HH:mm"
    return babel.dates.format_datetime(value, format)

(Este filtro se basa en babel por razones relacionadas con i18n, pero también puede usar strftime). La ventaja del filtro es que puedes escribir

{{ car.date_of_manufacture|datetime }}
{{ car.date_of_manufacture|datetime('full') }}

que se ve mejor y es más fácil de mantener. Otro filtro común es también el filtro "timedelta", que se evalúa como "escrito hace 8 minutos". Puede usar babel.dates.format_timedeltapara eso y registrarlo como filtro similar al ejemplo de fecha y hora que se proporciona aquí.

tux21b
fuente
2
¿realmente intentaste eso? llamarlo directamente da como resultado: 'time.struct_time object' no tiene atributo 'strftime'
Karl P
77
Según su pregunta, está hablando de algo diferente. Inicialmente, este hilo trataba sobre formatear un datetimeobjeto desde el módulo de Python datetime, pero está intentando formatear un struct_timeobjeto desde el timemódulo de bajo nivel . struct_timelos objetos no tienen un strftime()método, aunque puede haber un strftime()método global en el paquete de tiempo. Pero te recomiendo que uses el datetimepaquete de alto nivel (independiente de la plataforma) .
tux21b
2
Creo que te refieresbabel.dates.format_datetime(value, format)
johnboiles 01 de
2
definir un nuevo filtro, no es mejor de ninguna manera. Más código para escribir = más código para mantener = más código para analizar, almacenar en caché de bits (si se usa) e interpretar. Una de las grandes ventajas de usar Jinja2 es la capacidad de escribir código python pequeño dentro de la plantilla. Algunas de las ganancias de rendimiento, en comparación con el sistema de plantillas de Django, provienen de eso.
StefanNch
44
@StefanNch "definir un nuevo filtro, no es mejor de ninguna manera". Puede ser: si se llama al filtro muchas veces en las plantillas, esto evita repetir la cadena de formato y puede resultar en escribir menos código. Y aún más importante, código menos repetido , al agregar una abstracción.
jacquev6
21

Aquí está el filtro que terminé usando durante el tiempo de ejecución en Jinja2 y Flask

@app.template_filter('strftime')
def _jinja2_filter_datetime(date, fmt=None):
    date = dateutil.parser.parse(date)
    native = date.replace(tzinfo=None)
    format='%b %d, %Y'
    return native.strftime(format) 

Y luego usas el filtro así:

{{car.date_of_manufacture|strftime}}
Raj
fuente
2
¿Por qué son dateutily native?
GWG
15

Si se trata de un objeto de tiempo de nivel inferior (a menudo solo uso números enteros), y no quiero escribir un filtro personalizado por el motivo que sea, un enfoque que uso es pasar la función strftime a la plantilla como una variable, donde se puede llamar donde lo necesite.

Por ejemplo:

import time
context={
    'now':int(time.time()),
    'strftime':time.strftime }  # Note there are no brackets () after strftime
                                # This means we are passing in a function, 
                                # not the result of a function.

self.response.write(jinja2.render_template('sometemplate.html', **context))

Que luego se puede usar dentro de sometemplate.html:

<html>
    <body>
        <p>The time is {{ strftime('%H:%M%:%S',now) }}, and 5 seconds ago it was {{ strftime('%H:%M%:%S',now-5) }}.
    </body>
</html>
Olly FG
fuente
7

Puede usarlo así en la plantilla sin ningún filtro

{{ car.date_of_manufacture.strftime('%Y-%m-%d') }}
Zaytsev Dmitry
fuente
0

en matraz, con babel, me gusta hacer esto:

@app.template_filter('dt')
def _jinja2_filter_datetime(date, fmt=None):
    if fmt:
        return date.strftime(fmt)
    else:
        return date.strftime(gettext('%%m/%%d/%%Y'))

utilizado en la plantilla con {{mydatetimeobject|dt}}

así que no, con babel puede especificar sus diversos formatos en mensajes.po como este, por ejemplo:

#: app/views.py:36
#, python-format
msgid "%%m/%%d/%%Y"
msgstr "%%d/%%m/%%Y"
euri10
fuente