Flask-Moment: Flask and Jinja2 Integration with moment.js

If you followed my Mega-Tutorial articles you may remember that I dedicated an entire article to the topic of rendering dates and times.

I needed to revisit this problem for my upcoming book, and this time I decided to package this functionality in an extension. That is how Flask-Moment was born.


As usual, you can install this extension with pip:

$ pip install flask-moment

Initialization and Configuration

Class Moment must be created to initialize the extension:

from flask import Flask
from flask.ext.moment import Moment
app = Flask(__name__)
moment = Moment(app)

The delayed initialization style with init_app() is also supported.

After that you have to include jquery.js and moment.js in your template(s). The template now has helper functions to make this easy:

        <title>Flask-Moment example app</title>
        {{ moment.include_jquery() }}
        {{ moment.include_moment() }}

Note that you can include the scripts at the bottom of the page as well.

Both javascript files are imported from a CDN. If you want to use a specific version of these files you can pass the full version number as a string argument into each function. If you already have jquery included in your page then you can omit the include_jquery() line, but note that the include_moment() line must be present.

If you work in a language that is not English, then you can also set the language in the <head> section:

        {{ moment.lang("es") }}


The usage in Jinja2 templates tries to mimic the style of the original APIs in Javascript.

For example, this will render the current time with a custom format string:

<p>The current date and time is: {{ moment().format('MMMM Do YYYY, h:mm:ss a') }}.</p>

If you want to render an instance of datetime instead of the current time then pass it as an argument to the moment() constructor:

<p>The current date and time is: {{ moment(timestamp).format('MMMM Do YYYY, h:mm:ss a') }}.</p>

Note that the timestamp argument must be a "naive" datetime instance expressed in UTC (see the datetime documentation for a discussion on naive date and time objects).

The rendered time will always be in the client's local time.

These are the render styles that are supported:

  • format(format_string): custom format.
  • fromNow(no_suffix = False): relative to current time (i.e. "N minutes ago", "in N hours", etc.).
  • fromTime(another_timesatmp, no_suffix = False): relative to the given timestamp.
  • calendar(): another format relative to current time ('last Monday 3PM", "Tomorrow 1:30AM", etc.).
  • valueOf(): number of milliseconds since Unix Epoch.
  • unix(): number of seconds since Unix Epoch.

The rendered dates and times can be refreshed periodically by passing a refresh = True argument to any of the above functions. This is useful for the relative formats, because they are updated as time passes. The refresh interval is fixed at one minute.


I hope you find this little extension useful. The source code is available on github, and a demo application is included.

If you have any ideas for improvements let me know below in the comments.



  • #1 Collin said 2013-10-24T13:11:42Z

    Great addition! I've spent the last day figuring out how to use python's datetime library, ended up having to get pytz. This looks a lot more intuitive.

  • #2 dowlf said 2013-10-26T13:58:21Z

    Miguel, thanks for another awesome contribution to the Flask community!

  • #3 Sam said 2013-11-22T12:10:04Z

    I may have this wrong but for performance reasons isn't it better to load scripts last? i.e just before </body> rather than in <head>?

  • #4 Miguel Grinberg said 2013-11-22T15:11:08Z

    @Sam: Yes, loading the scripts last seems to be preferred these days, because the loading happens after the page has been displayed. I will add a note to that effect above.

  • #5 Nedda Kaltcheva said 2014-12-22T12:42:31Z

    Thank you for the extension, added it to our project today - very handy and a lot prettier than writing custom Jinja filters!

Leave a Comment