Skip to content

Commit

Permalink
first version
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed Oct 24, 2013
1 parent 8fbba07 commit cedaa5a
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 0 deletions.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include README.md LICENSE
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,52 @@
Flask-Moment
============

This extension enhances Jinja2 templates with formatting of dates and times using [moment.js](http://momentjs.com/).

Quick Start
-----------

Step 1: Initialize the extension:

from flask.ext.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>

Note that jQuery is required. If you are already including it on your own then you can remove the `include_jquery()` line.

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 <u>must be "naive" objects given in UTC timezone</u>. See the [documentation](http://docs.python.org/2/library/datetime.html) for a discussion of naive date and time objects. As an example, `now` can be set as follows:

now = datetime.utcnow()

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.

The supported list of display functions is shown below:

- `moment(timestamp = None).format(format_string)`
- `moment(timestamp = None).fromNow(no_suffix = False)`
- `moment(timestamp = None).fromTime(another_timesatmp, no_suffix = False)`
- `moment(timestamp = None).calendar()`
- `moment(timestamp = None).valueOf()`
- `moment(timestamp = None).unix()`

Consult the [moment.js documentation](http://momentjs.com/) for details on these functions.

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.

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.lang("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.
15 changes: 15 additions & 0 deletions example/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from datetime import datetime
from flask import Flask, render_template
from flask.ext.moment import Moment

app = Flask(__name__)
moment = Moment(app)

@app.route('/')
def index():
now = datetime.utcnow()
midnight = datetime(now.year, now.month, now.day, 0, 0, 0)
return render_template('index.html', now = now, midnight = midnight)

if __name__ == '__main__':
app.run(debug = True)
6 changes: 6 additions & 0 deletions example/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Flask==0.10.1
Flask-Moment==0.1.0
Jinja2==2.7.1
MarkupSafe==0.18
Werkzeug==0.9.4
itsdangerous==0.23
18 changes: 18 additions & 0 deletions example/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<html>
<head>
<title>Flask-Moment example app</title>
{{ moment.include_jquery() }}
{{ moment.include_moment() }}
</head>
<body>
<p>The current date and time is: {{ moment().format('MMMM Do YYYY, h:mm:ss a') }}.</p>
<p>
{{ moment(midnight).fromTime(now) }} it was midnight in the UTC timezone.
That was {{ moment(midnight).calendar() }} in your local time.
</p>
<p>
This page was rendered on {{ moment(now).format('LLL') }},
which was {{ moment(now).fromNow(refresh = True) }}.
</p>
</body>
</html>
78 changes: 78 additions & 0 deletions flask_moment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from datetime import datetime
import json
from jinja2 import Markup
from flask import current_app

class _moment(object):
@staticmethod
def include_moment(version = '2.3.1'):
if version is not None:
js = '<script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/%s/moment-with-langs.min.js"></script>\n' % version
return Markup('''%s<script>
function flask_moment_render(elem) {
$(elem).text(eval('moment("' + $(elem).data('timestamp') + '").' + $(elem).data('format') + ';'));
}
$(document).ready(function() {
$('.flask-moment').each(function() {
flask_moment_render(this);
if ($(this).data('refresh')) {
(function(elem, interval) { setInterval(function() { flask_moment_render(elem) }, interval); })(this, $(this).data('refresh'));
}
})
})
</script>''' % js)

@staticmethod
def include_jquery(version = '1.10.1'):
return Markup('<script src="http://code.jquery.com/jquery-%s.min.js"></script>' % version)

@staticmethod
def lang(language):
return Markup('<script>\nmoment.lang("%s");\n</script>' % language)

def __init__(self, timestamp = None):
if timestamp is None:
timestamp = datetime.utcnow()
self.timestamp = timestamp

def _timestamp_as_iso_8601(self, timestamp):
return timestamp.strftime('%Y-%m-%dT%H:%M:%SZ')

def _render(self, format, refresh = False):
t = self._timestamp_as_iso_8601(self.timestamp)
return Markup('<span class="flask-moment" data-timestamp="%s" data-format="%s" data-refresh="%d">%s</span>' % (t, format, int(refresh) * 60000, t))

def format(self, fmt, refresh = False):
return self._render("format('%s')" % fmt, refresh)

def fromNow(self, no_suffix = False, refresh = False):
return self._render("fromNow(%s)" % int(no_suffix), refresh)

def fromTime(self, timestamp, no_suffix = False, refresh = False):
return self._render("from(moment('%s'),%s)" % (self._timestamp_as_iso_8601(timestamp),int(no_suffix)), refresh)

def calendar(self, refresh = False):
return self._render("calendar()", refresh)

def valueOf(self, refresh = False):
return self._render("valueOf()", refresh)

def unix(self, refresh = False):
return self._render("unix()", refresh)

class Moment(object):
def __init__(self, app = None):
if app is not None:
self.init_app(app)

def init_app(self, app):
if not hasattr(app, 'extensions'):
app.extensions = {}
app.extensions['moment'] = _moment
app.context_processor(self.context_processor)

@staticmethod
def context_processor():
return {
'moment': current_app.extensions['moment']
}
36 changes: 36 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""
Flask-Moment
------------
Formatting of dates and times in Flask templates using moment.js.
"""
from setuptools import setup


setup(
name='Flask-Moment',
version='0.1.0',
url='http://github.com/miguelgrinberg/flask-moment/',
license='MIT',
author='Miguel Grinberg',
author_email='[email protected]',
description='Formatting of dates and times in Flask templates using moment.js.',
long_description=__doc__,
py_modules=['flask_moment'],
zip_safe=False,
include_package_data=True,
platforms='any',
install_requires=[
'Flask'
],
classifiers=[
'Environment :: Web Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
'Topic :: Software Development :: Libraries :: Python Modules'
]
)

0 comments on commit cedaa5a

Please sign in to comment.