Flask学习笔记:时间与日期

1. 做好准备工作
  • 进入项目主目录
  • 激活虚拟环境


2. 时区

在服务器上用Python来渲染时间和日期不是个好主意。比如我在2017年9月28日下午4:06写这篇文章。此时我的时区是PDT。在Python解释器中运行得到如下输出:

>>> from datetime import datetime
>>> str(datetime.now())
'2017-09-28 16:06:30.439388'
>>> str(datetime.utcnow())
'2017-09-28 23:06:51.406499'

调用 datetime.now() 得到了我本地的正确时间输出,而调用 datetime.utcnow() 则返回 UTC 时间。如果我让世界其他地方的人与我同时运行 datetime.now() 函数,每个人的返回结果都是不同的,但运行 datetime.utcnow() 会返回同样的时间。

显然服务器必须管理与未知以置且独立的时间。由于UTC是最常用的统一时区,并且 datetime 类支持它,所以我会使用UTC时间。

但这种方法有一个问题,对于不同时区的用户来说,他们没办法判断帖子到底是什么时候发布的。


3. 时区转换

解决这个问题是方法是把存储的UTC时间转换成各个用户的本地时间。这使得服务器用UTC保持了时间的一致性,又通过针对不同用户的实时转换解决了可用性问题。这个方案的棘手部分是了解每个用户的位置。

事实上, web浏览器知道用户的时区,并通过标准的时间和日期 JavaScript API公开它,实际上有两种方法来利用JavaScript提供的时区信息:

  • 一种是让web浏览器在用户第一次登录应用的时候将时区信息发送给服务器。这可以用AJAX调用来完成,或者用meta refresh tag来完成。一旦服务器知道了时区,它就可以将其保存到用户的session中,或者将其写入数据库中的用户条目中,然后在呈现模板是调整所有时间戳。
  • 另一种是不改变服务器中的信息,用JavaScript在客户端将UTC转换为本地时区。

两种选择都有用,但第二个更好。知道用户所在的时区并不足以以用户期望的格式来显示日期和时间。浏览器还可以访问系统区域设置,该配置指定诸如12小时制还是24小时制,DD/MM/YYYY 还是 MM/DD/YYYY 或其他风格的方式。

如果这还不够,后者还有个有时。有个开源库可以完成这些工作。


4. Moment.js 和 Flask-Moment

Moment.js 是一个小型的开源JavaScript库,可以将时间和日期转换为其他格式。Miguel创建了Flask-Moment,这是非小型的Flask拓展,方便将moment.js 合并入Flask应用。

下面安装Flask-Moment:

(venv) $ pip install flask-moment

将拓展加入Flask应用:

app/__init__.py

# ...
from flask_moment import Moment

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

不行其他应用, Flask-Moment与moment.js 一起工作,所以模板必须要包括这个库。我将它加入base模板,方法有两种,一种是显式的添加 <script> 标签,还有一种是用 moment.include_moment() 函数来生成 <script>标签。这里我用了super()语句, super() 可以使在基模板此块中定义的内容不丢失。


5. 使用 Moment.js

Moment.js 使 moment 类可用于浏览器。渲染时间戳的第一步是创建一个类对象,以 ISO 8601 格式传递所需的时间戳,下面是一个示例:

t = moment('2017-09-28T21:45:23Z')
ISO 8601时间和日期的标准格式如下:{{ year }}-{{ month }}-{{ day }}T{{ hour }}:{{ minute }}:{{ second }}{{ timezone }}

moment 对象为不同的渲染选项提供了多种方法。由于我们选择用UTC时间,所以最后一位会是Z,在ISO 8601中代表UTC。下面是最常用的几种选项:

moment('2017-09-28T21:45:23Z').format('L')
"09/28/2017"
moment('2017-09-28T21:45:23Z').format('LL')
"September 28, 2017"
moment('2017-09-28T21:45:23Z').format('LLL')
"September 28, 2017 2:45 PM"
moment('2017-09-28T21:45:23Z').format('LLLL')
"Thursday, September 28, 2017 2:45 PM"
moment('2017-09-28T21:45:23Z').format('dddd')
"Thursday"
moment('2017-09-28T21:45:23Z').fromNow()
"7 hours ago"
moment('2017-09-28T21:45:23Z').calendar()
"Today at 2:45 PM"

本例的初始事件之是UTC时区2017年9月28日下午9点45分。上面的示例中,最终时间都转换为了UTC-7,这是我电脑上设置的时区。

format() 可以控制输字符串的格式, 和Python中的strftime函数差不多,fromNow() 和 calendar() 方法渲染的时间与现在的时间有关, 所以输出会是 “一分钟以前”,“两小时内”等。

像下面这样渲染时间戳:

app/templates/user.html

{% if user.last_seen %}
                <p>Last seen on: {{ moment(user.last_seen).format('LLL') }}</p>
                {% endif %}

_post.html 子模版中也加入 moment.js:

app/templates/_posts.html

                <a href="{{ url_for('user', username=post.author.username) }}">
                    {{ post.author.username }}
                </a>
                said {{ moment(post.timestamp).fromNow() }}:
                <br>
                {{ post.body }}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值