Formatting of dates and times in Flask templates using moment.js.

Overview

Flask-Moment

Build Status

This extension enhances Jinja2 templates with formatting of dates and times using moment.js.

Quick Start

Step 1: Initialize the extension:

from flask_moment import Moment
moment = Moment(app)

Step 2: In your <head> section of your base template add the following code:

<head>
    {{ moment.include_jquery() }}
    {{ moment.include_moment() }}
</head>

This extension also supports the Flask application factory pattern by allowing you to create a Moment object and then separately initialize it for an app:

    moment = Moment()

    def create_app(config):
        app = Flask(__name__)
        app.config.from_object(config)
        # initialize moment on the app within create_app()
        moment.init_app(app)

    app = create_app(prod_config)

Note that jQuery is required. If you are already including it on your own then you can remove the include_jquery() line. Secure HTTP is always used to request the external js files..

The include_jquery() and include_moment() methods take some optional arguments. If you pass a version argument to any of these two calls, then the requested version will be loaded from the default CDN. If you pass local_js, then the given local path will be used to load the library. The include_moment() argument takes a third argument no_js that when set to True will assume that the Moment JavaScript library is already loaded and will only add the JavaScript code that supports this extension.

Step 3: Render timestamps in your template. For example:

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

In the second and third examples template variables then and now are used. These must be instances of Python's datetime class, and must be "naive" objects. See the documentation for a discussion of naive date and time objects. As an example, now can be set as follows:

now = datetime.utcnow()

By default the timestamps will be converted from UTC to the local time in each client's machine before rendering. To disable the conversion to local time pass local=True.

Note that even though the timestamps are provided in UTC the rendered dates and times will be in the local time of the client computer, so each users will always see their local time regardless of where they are located.

Function Reference

The supported list of display functions is shown below:

  • moment(timestamp=None, local=False).format(format_string=None)
  • moment(timestamp=None, local=False).fromNow(no_suffix=False)
  • moment(timestamp=None, local=False).fromTime(another_timesatmp, no_suffix=False)
  • moment(timestamp=None, local=False).toNow(no_suffix=False)
  • moment(timestamp=None, local=False).toTime(another_timesatmp, no_suffix=False)
  • moment(timestamp=None, local=False).calendar()
  • moment(timestamp=None, local=False).valueOf()
  • moment(timestamp=None, local=False).unix()

Consult the moment.js documentation for details on these functions.

Auto-Refresh

All the display functions take an optional refresh argument that when set to True will re-render timestamps every minute. This can be useful for relative time formats such as the one returned by the fromNow() or fromTime() functions. By default refreshing is disabled.

Default Format

The format() function can be invoked without arguments, in which case a default format of ISO8601 defined by the moment.js library is used. If you want to set a different default, you can set the MOMENT_DEFAULT_FORMAT variable in the Flask configuration. Consult the moment.js format documentation for a list of accepted tokens.

Internationalization

By default dates and times are rendered in English. To change to a different language add the following line in the <head> section after the include_moment() line:

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

The above example sets the language to Spanish. Moment.js supports a large number of languages, consult the documentation for the list of languages and their two letter codes.

The extension also supports auto-detection of the client's browser language:

{{ moment.locale(auto_detect=True) }}

Custom locales can also be included as a dictionary:

{{ moment.locale(customizations={ ... }) }}

See the Moment.js locale customizations documentation for details on how to define a custom locale.

Ajax Support

It is also possible to create Flask-Moment timestamps in Python code, for cases where a template is not used. This is the syntax:

timestamp = moment.create(datetime.utcnow()).calendar()

The moment variable is the Moment instance that was created at initialization time.

A timestamp created in this way is an HTML string that can be returned as part of a response. For example, here is how a timestamp can be returned in a JSON object:

return jsonify({ 'timestamp': moment.create(datetime.utcnow()).format('L') })

The Ajax callback in the browser needs to call flask_moment_render_all() each time an element containing a timestamp is added to the DOM. The included application demonstrates how this is done.

Subresource Integrity(SRI)

SRI is a security feature that enables browsers to verify that resources they fetch are not maliciously manipulated. To do so a cryptographic hash is provided that proves integrity.

SRI is enabled by default. If you wish to use another version or want to host your own javascript, a separate hash can be provided. Just add sri=<YOUR-HASH> when calling either moment.include_moment() or moment.include_jquery(). If no sri hash is provided and you choose to use a non default version of javascript, no sri hash will be added.

You can always choose to disable sri. To do so just set sri=False.

Development

Currently the tests are written using pytest.

pip install pytest

To run the tests from the root directory use: py.test.

Reports on coverage with missing line numbers can be generated using pytest-cov:

pip install pytest-cov

And then running: py-test --cov-report term-missing --cov=flask_moment

Comments
  • Add basic docs with Sphinx and Flask-Sphinx-Themes

    Add basic docs with Sphinx and Flask-Sphinx-Themes

    Hey, Miguel. This is a start for adding in docs and addressing #22. I have not worked with Sphinx very much, so any advice you can give me about how to best document this project will be appreciated, and I'll gladly make changes. For example I am not sure how to use these :code:, :class:, or :func: tags and I am also not sure how to use "autodoc". I'm thinking those tags and autodoc probably are work together somehow.

    I used the sphinx-quickstart and based the remaining configuration off of how Flask-Misaka did their docs. As you'll see all I've done is copy the readme into index.rst.

    I figure at this point I should try to get some feedback before going forward. In meantime, I'll look some more into Sphinx.

    Oh, and building the docs should work with:

    pip install sphinx
    pip install Flask-Sphinx-Themes
    make html
    
    question auto-closed 
    opened by wgwz 18
  • Problem using Flask-Moment in IE11 and Edge

    Problem using Flask-Moment in IE11 and Edge

    Hi -

    I'm learning Python Flask and I've built my first simple website. In one of the HTML templates I've included the line: <p>The current date and time is: {{ moment().format('MMMM Do YYYY, h:mm:ss a') }}.</p>

    My init.py file contains the lines: from flask_moment import Moment

    moment = Moment(app)

    My base.html file contains: {% block scripts %} {{ super() }} {{ moment.include_moment() }} {{ moment.locale(auto_detect=True) }} {% endblock %}

    This works fine in Firefox and Chrome, but returns no datetime information in IE11 or Edge.

    I'm running the Flask app on localhost:5000.

    I've attached screenshots from the four browsers to illustrate the problem.

    I'm running MS Windows 10 Home (64-bit) on a Lenovo ThinkPad laptop with Python 3.8.2 (32-bit) and Flask 1.1.2. I'm using Flask_Bootstrap4 4.0.2.

    Apologies if this isn't the right place to raise this question, but I've searched extensively online (stackoverflow, etc) and I haven't been able to find any information that has helped me to resolve it.

    Please let me know if you need any further information.

    Many thanks

    Firefox Firefox Chrome Chrome IE11 IE11 Edge Edge

    question 
    opened by evilocku 14
  • CSP

    CSP

    I added Talisman to my Flask project and tried to properly configure TALISMAN_SECURITY_POLICY but I can't figure out how to get Moment scripts accepted.

    I got the following message(s): Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline' cdnjs.cloudflare.com maxcdn.bootstrapcdn.com code.jquery.com 'nonce-gOu5h3Vkvkid_uTOnxjYsw'". Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.

    I tried to investigate things a bit further and it looks like it comes from moment.include_jquery() and moment.include_moment(). I wonder if someone (@miguelgrinberg ?) could add an option to include a SHA or a nonce to the script tag (if that's the proper way to do it) or let me know how to circumvent the issue(s).

    question 
    opened by cdruet 14
  • Allow users to optionally supply a CSP nonce to generated inline script

    Allow users to optionally supply a CSP nonce to generated inline script

    If the user has set up a CSP like:

    Content-Security-Policy:
      script-src 'nonce-{random}'
      script-src-elem 'nonce-{random}'
    

    The random is substituted with the provided nonce.

    It is recommended that the user use an extension like Flask-Talisman and set it up as:

    talisman = Talisman()
    
    CSP = {
        # your preferred CSP goes here
    }
    
    talisman.init_app(
        app,
        csp=CSP,
        content_security_policy_nonce_in=["script-src-elem"],
        # ...
    )
    

    and then load Flask-Moment like:

    {% block scripts %}
    {# ... #}
    {{ moment.include_moment(csp_nonce=csp_nonce()) }}
    {# ... #}
    {% endblock %}
    

    Valuable resources:

    question 
    opened by arunanshub 13
  • Safari (13.0.2) doesn't seem to like sri=True

    Safari (13.0.2) doesn't seem to like sri=True

    I'm not sure whether this is properly an error in flask-moment. Apologies if this is the wrong place.

    Using an extremely simple app, I can't seem to get dates to display properly in Safari (13.0.2) with flask-moment (0.9.0) unless I set sri to False in include_moment(). Otherwise, moment.js fails to load and no dates display. In the JavaScript console I see errors related to Access-Control-Allow-Origin, but setting that header manually doesn't have any impact.

    The errors I see:

    [Error] Cross-origin redirection to http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js denied by Cross-Origin Resource Sharing policy: Origin http://localhost:5000 is not allowed by Access-Control-Allow-Origin.
    [Error] Failed to load resource: Cross-origin redirection to http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js denied by Cross-Origin Resource Sharing policy: Origin http://localhost:5000 is not allowed by Access-Control-Allow-Origin. (moment-with-locales.min.js, line 0)
    [Error] Cross-origin script load denied by Cross-Origin Resource Sharing policy.
    [Error] ReferenceError: Can't find variable: moment
    Global Code (localhost:15)
    [Error] Cross-origin script load denied by Cross-Origin Resource Sharing policy.
    [Error] ReferenceError: Can't find variable: moment
    Global Code (localhost:49)
    

    The code I used:

    main.py:

    from flask_bootstrap import Bootstrap
    from flask_moment import Moment
    from flask import Flask, render_template, make_response
    from datetime import datetime
    
    app = Flask(__name__)
    bootstrap = Bootstrap(app)
    moment = Moment(app)
    
    @app.route("/")
    def index():
        return render_template('index.html', current_time=datetime.utcnow())
    
    if __name__ == '__main__':
        app.run()
    

    base.html:

    {% extends "bootstrap/base.html" %}
    {% block head %}
    {{ super() }}
      {% block scripts %}
      {{ super() }}
      {{ moment.include_moment() }}
      {% endblock %}
    {% endblock %}
    
    {% block content %}
      {% block page_content %}
      {% endblock %}
    {% endblock %}
    

    index.html:

    {% extends 'base.html' %}
    
    {% block page_content %}
    Current time: {{ moment(current_time).format('LLL') }}.
    {% endblock %}
    
    investigate 
    opened by cunningjames 7
  • Adds live option + custom refresh

    Adds live option + custom refresh

    • Changes in this commit allow for the use of a 'live' timestamp. See the example file for a live demo.
    • Prevents starting multiple timers for a single object
    • Refresh now allows for other values (like every second).
    • Adds a toNow function
    • All changes are backwards compatible.
    enhancement 
    opened by javl 7
  • Remove use of JavaScript eval() (Closes #60)

    Remove use of JavaScript eval() (Closes #60)

    Pull request of the change proposed here, allowing to remove the use of the eval() JavaScript function. Would also fix #43 and allow to work with a Content-Security-Policy (CSP) that doesn't require unsafe-eval for any JavaScript page on the entire webpage (since that doesn't apply just to the bits from Flask-Moment)

    bug 
    opened by e2jk 6
  • add methods for moment.js subtract, add, diff

    add methods for moment.js subtract, add, diff

    Had trouble with adding .format() to the end of subtract, and add because of render statements being parsed in-between. For this reason these methods expect a format parameter which will be added to the aforementioned moment.js render call.

    Issue #35

    enhancement 
    opened by antmurph 6
  • Setting a default format

    Setting a default format

    I found in using this in my app I use the same string format in all my web pages. When adding new dates in new pages I would have a hard time remembering what exactly that format was. This solves that problem by setting a config variable to the format needed without needing to register a new jinja variable.

    enhancement 
    opened by jacobthetechy 6
  • Eliminate eval, convert to vanilla js

    Eliminate eval, convert to vanilla js

    So for this conversion (regarding eval) I discovered that it was mostly a lot easier than I expected (after initially believing it would be a lot harder than I expected).

    The primary problem presented in this case is regarding the parameters called to the moment. This is why the fromNow exists.

    I thought just a minute ago about how it would be possible to, instead of rendering each parameter as a dataset attribute, simply render a csv string of the parameters and then split on the commas. This becomes more complicated as we start dealing with datatypes (string vs bool vs int, etc.) but I think I could manage it.

    The one point at which I don't think I could manage it anymore is with regard to from as we need to create a new moment.

    It would theoretically be possible to write a getArgs() function that took a type-annotated csv string, e.g. moment:<timestamp>,int:<int> which would then parse those into the correct datatypes. Heck, I could just use JSON I would think, but at that point we're really writing a parser.

    Wow I just noticed I still have a console logger there and a random return. Sorry will clean immediately.

    As regards elimination of JQuery, I think this did it.

    Opinions?

    opened by mas-4 6
  • How to customize fromNow output ?

    How to customize fromNow output ?

    I am displaying time data was received using flask Moment.fromNow. Typically it outputs 'a few seconds ago' but sometimes the sender's clock is a little off and it displays ' in a few seconds' - which makes no sense to the user. To fix this I want to change ' in a few seconds' to 'current' but this does not seem easy using Moment customization so I thought I could simply change the output in jinja2 but cannot see how to capture the output string to change it: Code: {% set moment_text = moment(value.lastupdated).fromNow(no_suffix = False) %}

        {% if moment_text == "in a few seconds"  %}
            {% set moment_text = "current" %}
        {% endif %}
    

    This never fires because moment_text is still a date and not a string. How can I get the output string of Flask Moment so I can test it and change it? Thanks Bill

    enhancement 
    opened by MrBillium 6
  • I keep getting errors trying to format a duration

    I keep getting errors trying to format a duration

    I'd like to format a number of seconds e.g. 150 seconds -> 00:02:30 using Flask-Moment

    I think this should work:

    {{ moment().startOf('day').seconds(s).format('H:mm:ss'); }}
    

    but I get an error jinja2.exceptions.UndefinedError: 'flask_moment._moment object' has no attribute 'startOf'

    question 
    opened by alxcnwy 1
Owner
Miguel Grinberg
Miguel Grinberg
A flask template with Bootstrap 4, asset bundling+minification with webpack, starter templates, and registration/authentication. For use with cookiecutter.

cookiecutter-flask A Flask template for cookiecutter. (Supports Python ≥ 3.6) See this repo for an example project generated from the most recent vers

null 4.3k Dec 29, 2022
flask-apispec MIT flask-apispec (🥉24 · ⭐ 520) - Build and document REST APIs with Flask and apispec. MIT

flask-apispec flask-apispec is a lightweight tool for building REST APIs in Flask. flask-apispec uses webargs for request parsing, marshmallow for res

Joshua Carp 617 Dec 30, 2022
Beautiful Interactive tables in your Flask templates.

flask-tables Beautiful interactive tables in your Flask templates Resources Video demonstration: Go to YouTube video. Learn how to use this code: Go t

Miguel Grinberg 209 Jan 5, 2023
flask-reactize is a boostrap to serve any React JS application via a Python back-end, using Flask as web framework.

flask-reactize Purpose Developing a ReactJS application requires to use nodejs as back end server. What if you want to consume external APIs: how are

Julien Chomarat 4 Jan 11, 2022
Flask-Rebar combines flask, marshmallow, and swagger for robust REST services.

Flask-Rebar Flask-Rebar combines flask, marshmallow, and swagger for robust REST services. Features Request and Response Validation - Flask-Rebar reli

PlanGrid 223 Dec 19, 2022
Brandnew-flask is a CLI tool used to generate a powerful and mordern flask-app that supports the production environment.

Brandnew-flask is still in the initial stage and needs to be updated and improved continuously. Everyone is welcome to maintain and improve this CLI.

brandonye 4 Jul 17, 2022
Flask pre-setup architecture. This can be used in any flask project for a faster and better project code structure.

Flask pre-setup architecture. This can be used in any flask project for a faster and better project code structure. All the required libraries are already installed easily to use in any big project.

Ajay kumar sharma 5 Jun 14, 2022
Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application.

Flask-Bcrypt Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application. Due to the recent increased prevelance of

Max Countryman 310 Dec 14, 2022
Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application.

Flask-Bcrypt Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application. Due to the recent increased prevelance of

Max Countryman 282 Feb 11, 2021
Flask-Starter is a boilerplate starter template designed to help you quickstart your Flask web application development.

Flask-Starter Flask-Starter is a boilerplate starter template designed to help you quickstart your Flask web application development. It has all the r

Kundan Singh 259 Dec 26, 2022
Flask Project Template A full feature Flask project template.

Flask Project Template A full feature Flask project template. See also Python-Project-Template for a lean, low dependency Python app. HOW TO USE THIS

Bruno Rocha 96 Dec 23, 2022
A Fast API style support for Flask. Gives you MyPy types with the flexibility of flask

Flask-Fastx Flask-Fastx is a Fast API style support for Flask. It Gives you MyPy types with the flexibility of flask. Compatibility Flask-Fastx requir

Tactful.ai 18 Nov 26, 2022
Flask-app scaffold, generate flask restful backend

Flask-app scaffold, generate flask restful backend

jacksmile 1 Nov 24, 2021
Pf-flask-rest-com - Flask REST API Common Implementation by Problem Fighter Library

In the name of God, the Most Gracious, the Most Merciful. PF-Flask-Rest-Com Docu

Problem Fighter 3 Jan 15, 2022
Flask-Discord-Bot-Dashboard - A simple discord Bot dashboard created in Flask Python

Flask-Discord-Bot-Dashboard A simple discord Bot dashboard created in Flask Pyth

Ethan 8 Dec 22, 2022
Open-source Flask Sample built on top of flask-dance library

Open-source Flask Sample built on top of flask-dance library. The project implements the social login for Github and Twitter - Originally coded by TestDriven.IO.

App Generator 4 Jul 26, 2022
Flask-redmail - Email sending for Flask

Flask Red Mail: Email Sending for Flask Flask extension for Red Mail What is it?

Mikael Koli 11 Sep 23, 2022
Flask Sitemapper is a small Python 3 package that generates XML sitemaps for Flask applications.

Flask Sitemapper Flask Sitemapper is a small Python 3 package that generates XML sitemaps for Flask applications. This allows you to create a nice and

null 6 Jan 6, 2023
Flask-template - A simple template for make an flask api

flask-template By GaGoU :3 a simple template for make an flask api notes: you ca

GaGoU 2 Feb 17, 2022