Flask学习之十三 日期和时间

英文博客地址:http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xiii-dates-and-times

中文翻译地址:http://www.pythondoc.com/flask-mega-tutorial/dateandtime.html备注:开源社区的好像是只翻译到十二部分,剩下的我就找不到了。

一、时间戳问题

到目前为止,我们使用 Python 本身去渲染在我们 UserPost 对象中的 datetime 对象,但并不是完全没有问题的。

now() 调用返回本地时区的正确的时间,然而 utcnow() 调用返回 UTC 单位的时间。

UTC是Coordinated Universal Time- 世界协调时间,又称世界统一时间,中国时区是CST,UTC+8

如果我们所有的时间戳都使用 now(),我们将会在数据库中存储服务器运行本地的时间。如果有一天我们想把服务器迁移到不同时区的地方,那么所有数据库中的时间戳必须在服务器重启之前修改成当地的正确时间。

而且不同时区的用户很难清楚知道 blog 的发布时间,因为他们看到的是在服务器所在时区的时间。他们需要提前知道服务器的时区是什么时区才能做出适当的调整。

用 UCT 时区标准化了时间戳解决了迁移服务器的问题。但是日期和时间在世界上的任何地方都会以 UTC 形式呈献给用户。这会显得非常奇怪。

二、用户特定的时间戳

最解决问题的方案就是为每一个用户单独把时间戳从 UTC 转换到当地时区。这也允许我们接着在数据库中使用 UTC 时区。

知道用户时区的方法,可以让用户注册的时候选择时区,不过比较累赘。如果能知道电脑上的时间会方便点,不过出于安全原因这是不被允许的。

其实网页浏览器知道用户的时区,并且可以通过标准的 Javascript APIs 导出。有两种方式通过 Javascript 来利用可用的时区配置:

  • “老派” 的方式就是让网页浏览器在某时候发送时区信息当用户第一次登录到服务器。这可以通过 Ajax 调用,或者 一个 刷新标记。一旦服务器知道了时区会把它保存到用户的会话中,当模板渲染的时候会去调整时间。
  • “新派” 的方式就是不会在服务器上改变任何东西,会继续把 UTC 时间戳发送到客户端浏览器上。从 UTC 到当地时区的转换是通过 Javascript 在客户端实现的。

两种方式都不错,但是第二种更加不错。浏览器是最有能力根据系统时区配置来渲染时间的。更有吸引力的是,第二种方式有现成的。

三、介绍 moment.js

Moment.js 是一个小型的,自由的,开源的 Javascript 库,它能够渲染日期和时间。它提供了富有想象的格式化选项。

下载以及介绍直接点链接看官网就好了,很清晰。

四、整合使用moment.js

首先,把下载下来的 moment.min.js 放入到 /app/static/js 文件夹,这样它就能作为一个静态文件提供给客户端。(我下载下来的文件名字是moment.js)

接着,在我们的基础模板中添加对这个库的引用(文件 app/templates/base.html):

<script src="/static/js/moment.min.js"></script>

接下来我们可以在模板里面添加 <script> 标签,写相关操作。不过把它放到一个文件封装起来,然后在文件中调用会更好。

我们的封装是一个很简单的 Python 类(文件 app/momentjs.py):

from jinja2 import Markup

class momentjs(object):
    def __init__(self, timestamp):
        self.timestamp = timestamp

    def render(self, format):
        return Markup("<script>\ndocument.write(moment(\"%s\").%s);\n</script>" % (self.timestamp.strftime("%Y-%m-%dT%H:%M:%S Z"), format))

    def format(self, fmt):
        return self.render("format(\"%s\")" % fmt)

    def calendar(self):
        return self.render("calendar()")

    def fromNow(self):
        return self.render("fromNow()")

注意 render 方法并不直接返回字符串而是把它放入了 Jinja2 提供的 Markup 对象中。原因是 Jinja2 默认情况下会自动转义,例如,我们的 <script> 标签是不可能到达到客户端,因为转义成 &lt;script&gt;。把字符串包裹在 Markup 对象里就是告诉 Jinja2 这个字符串是不需要转义的。

既然我们有了一个封装的类,我们需要跟 Jinja2 绑定,这样模块就可以使用它(文件 app/__init__.py):

from .momentjs import momentjs
app.jinja_env.globals[‘momentjs‘] = momentjs

面的代码就是告诉 Jinja2 导入我们的类作为所有模板的一个全局变量。

现在我们准备修改模版。在我们应用程序中有两个地方显示日期和时间。一个就是用户信息页,那里有最后一次登录时间。对于这个时间戳,我们将会使用 calendar() 格式(文件 app/templates/user.html):

{% if user.last_seen %}
<p><em>Last seen: {{ momentjs(user.last_seen).calendar() }}</em></p>
{% endif %}

第二个地方就是在 post 子模板,它是被首页,用户信息页以及搜索页调用。在这里我们将会使用 fromNow() 格式,因为一篇 blog 的撰写时间和它离现在有多久了是一样重要的。我们需要修改子模板使得所有使用它的页面都有效(文件 app/templates/post.html):

<p><a href="{{ url_for(‘user‘, nickname=post.author.nickname)}}">{{ post.author.nickname }}</a> said {{ momentjs(post.timestamp).fromNow() }}:</p>
<p><strong>{{ post.body }}</strong></p>

效果:

备注:

其实我觉得如果熟悉前端的,也许直接写js会更简单一点?

时间: 2024-11-08 09:06:00

Flask学习之十三 日期和时间的相关文章

Flask学习之十三——提供 API

1. REST API 1.1 资源 资源是 REST 架构方式的核心概念.在 REST 架构中,资源是程序中你要着重关注的事物.例如,在博客程序中,用户.博客文章和评论都是资源. 每个资源都要使用唯一的 URL 表示.还是以博客程序为例,一篇博客文章可以使用 URL /api/posts/12345 表示,其中 12345 是这篇文章的唯一标识符,使用文章在数据库中的主键表示.URL 的格式或内容无关紧要,只要资源的 URL 只表示唯一的一个资源即可.某一类资源的集合也要有一个 URL.博客文

《Javascript权威指南》学习笔记之十三:处理日期和时间

一.创建Date实例 1.Date类的方法和属性很多不是静态的,因此,在应用Date类的属性和方法之前,必须创建Date类的实例. var date = new Date();  //以当前日期和时间创建实例. var date = new Date(value);  //value是必选项,如果是数值,value表示指定日期与1970.1.1午夜之间的毫秒数:如果是字符串,value则按照parse()方法中的规则进行解析.全局的Date()函数完成与new Date(value)相同的功能

Flask从入门到精通之Flask-Moment本地化日期和时间

Moment.js 是一个简单易用的轻量级JavaScript日期处理类库,提供了日期格式化.日期解析等功能.它支持在浏览器和NodeJS两种环境中运行.此类库能够 将给定的任意日期转换成多种不同的格式,具有强大的日期计算功能,同时也内置了能显示多样的日期形式的函数.Flask-Moment是一个集成moment.js到Jinja2模板的Flask扩展.安装Flask-Moment的方式如下: pip install Flask-Moment 初始化Flask-Moment from flask

Flask 教程 第十二章:日期和时间

本文翻译自The Flask Mega-Tutorial Part XII: Dates and Times 这是Flask Mega-Tutorial系列的第十二部分,我将告诉你如何以适配所有用户的方式处理日期和时间,无论他们身处地球上的何处. 显示日期和时间是Microblog应用中长期被忽略的其中一个方面. 直到现在,我也只是让Python渲染了User模型中的datetime对象,并且完全忽略了Post模型中的datetime对象. 本章的GitHub链接为:Browse, Zip, D

《Javascript权威指南》13号学习笔记:使用日期和时间

一.创Date示例 1.Date类的方法和属性是非常不静,故,申请书Date属性和方法之前.必须创建Date类的实例. var date = new Date();  //以当前日期和时间创建实例. var date = new Date(value);  //value是必选项,假设是数值.value表示指定日期与1970.1.1午夜之间的毫秒数.假设是字符串.value则依照parse()方法中的规则进行解析. 全局的Date()函数完毕与new Date(value)同样的功能 var d

Python学习笔记十:日期和时间

日期和时间处理是经常会遇到的事情. 什么是Tick? 时间间隔是以秒为单位的浮点小数. 每个时间戳都以自从1970年1月1日午夜(历元)经过了多长时间来表示. Python附带的受欢迎的time模块下有很多函数可以转换常见日期格式.如函数time.time()用ticks计时单位返回从12:00am, January 1, 1970(epoch) 开始的记录的当前操作系统时间, 如下实例: 1 #!/usr/bin/python 2 import time; # This is required

Python学习进程(11)日期和时间

    本节介绍Python应用程序处理时间和日期的方式.其中转换日期格式是最常用的功能.     (1)获取时间戳: Python 提供了一个 time 和 calendar 模块可以用于格式化日期和时间. 函数time.time()用于获取当前时间戳: >>> import time >>> tickets=time.time() >>> print "当前时间戳是:",tickets 当前时间戳是: 1469240559.05

【转】Pro Android学习笔记(十七):用户界面和控制(5):日期和时间控件

目录(?)[-] DatePicker和TimePicker控件 DigitalClock和AnalogClock控件 DatePicker和TimePicker控件 使用DatePicker和TimePicker,故名思议,用户可以对时间进行选择.XML代码如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout ...... >     <TextView ......  an

SQLServer学习笔记&lt;&gt;日期和时间数据的处理(cast转化格式、日期截取、日期的加减)和 case表达式

日期和时间数据的处理. (1)字符串日期 ‘20080301’,这一串为字符串日期,但必须保证为四位的年份,两位的月份,两位的日期.例如,查询订单表日期大于‘20080301’.可以这样写: 1 select * from sales.orders 2 where orderdate>'20080301' 结果如图所示: (2)cast进行转化.例如,可以讲‘20080301’转化为时间类型.其结果跟上图一样. 1 select * from sales.orders 2 where order