flask入门和进阶九(时间和日期Dates and times)

本文探讨了Web应用中处理时区差异的策略,特别是在服务器与全球用户交互时。介绍了如何使用Flask-Moment和Moment.js在Python Flask应用中实现时区转换,以提供用户友好的本地化时间显示。

时区差别

在服务器上用Python去呈现日期和时间,在Web浏览器上以这种方式渲染给用户可不是一个好主意。如示例,在Python解释器中运行如下内容:

调用datetime.now()将返回当前所在时区的时间(东八区),而调用datetime.utcnow()将返回世界统一时间(或者也叫作世界标准时间)。如果我能让生活在世界不同地区的许多人同时一起运行上述代码,datetime.now()函数将为每个人返回不同的结果,但datetime.utcnow()无论地理位置在哪,都将返回相同的时间。那么你认为哪一个更适合一个很可能让用户遍布全球的Web应用程序中使用?

很明显,服务器必须管理 一致且独立于位置的时间。如果这个应用程序增长到世界各地需要多个生产服务器的程序,当然就不希望每个服务器在不同时区写入数据库的时间戳,因为这样就无法使用这些时间。由于UTC是最常用的统一时区,并且在datetime类中受支持,因此在此将使用它。

虽然从服务器的角度上,将时间戳标准化很有意义,这会用户带来可用性问题。本章的目标是解决这个问题,同时保持服务器以UTC格式管理的所有时间戳

时区转换

这个问题显而易见的解决方案是:将所有时间戳 从存储的UTC单位转换为每个用户的本地时间。这允许服务器继续使用UTC来保持一致性,同时为每个用户量身定制地即时转换解决可用性问题。这个解决方案的棘手部分 是了解每个用户的位置。

许多网站都有一个配置页面,用户可以在其中指定时区。这将要求我添加一个带表单的新页面,这个表单中,我可以向用户显示带有时区列表的下拉列表。作为注册的一部分,用户可以在第一次访问网站时要求输入他们的时区。

虽然这是解决问题的一个不错解决方案,但要求用户输入他们已在其操作系统中配置的信息有点奇怪。如果能从他们的计算机中获取时区设置似乎会更有效率。

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

1,“老派”方法是在用户首次登陆应用程序时,让Web浏览器以某种方式将时区信息发送到服务器。这可以通过Ajax调用完成,或更简单地使用 meta refresh tag。一旦服务器知道时区,它就可以将其保存在用户的会话中,或将其写入数据库中的用户条目,然后在渲染模板时用它调整所有时间戳。

2,新派”方法是不改变服务器中的东西,而在客户端中使用JavaScript在客户端中进行从UTC到本地时区的转换

介绍Moment.js和flask-moment

[Moment.js](http://momentjs.com/)是一个小型开源JavaScript库,它将日期和时间渲染成另一个级别,因为它提供每一个可想象的格式化选项。不久前,建立了Flask-Moment,它是一个小型Flask扩展,它可以轻易地将`moment.js`合并到应用程序中。
首先,安装Flask-Moment:版本0.6.0
 

pip install flask-moment

以常规方式添加到flask应用程序中

与其他扩展不同,flask-moment 与moment.js一起使用,因此应用程序的多有模板都必须包含这个库。为了确保这个库始终可用,将在 基础模板中添加它。这可通过两种方式完成。最直接的方法是显示地以导入库的方式添加一个<script>标签,但Flask-Moment使其变得更容易,即通过公开一个moment.include_moment()函数,它会生成<script>标签。

在这添加的scripts块Flask-Bootstrap的基础模板导出的另一个块。这是包含JavaScript导入的地方。这个块与之前的块不同,因为它已经在基础模板中定义了一些内容。我想的是 添加moment.js库,而不会失去基本内容。这是通过super()语句实现的,这个语句将保留基础模板中的内容。如果在没有使用super()的情况下,在你的模板中定义一个块,那么在基础模板中,为这个块定义的任何内容都将失去。

Moment.js介绍

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

t = moment('2017-09-28T21:45:23Z')

如果你不熟悉日期和时间的ISO 8601标准格式,格式如:{{ year }}-{{ month }}-{{ day }}T{{ hour }}:{{ minute }}:{{ second }}{{ timezone }}。我已经决定只用UTC时区,所以最后一部分将始终是Z,它代表ISO 8601标准中的UTC。

上述示例 创建了一个时刻对象,初始化为 2017年9月28日晚上9:45 UTC。注意不同方法是如何创建不同的表示的。使用format(),可以控制字符串的输出格式,类似Python中的strftime()函数。

fromNow()calendar()方法很有趣,因为它们会根据当前时间显示时间戳,所以会得到如“一分钟前”或“两个小时内”的输出。

如果直接使用JavaScript,那么上述调用将返回具有呈现时间戳的字符串。然后,可将此文本插入页面上的适当位置,遗憾的是,需要JavaScript与DOM配合使用。Flask-Moment在模板中启用类似于JavaScript的对象,极大地简化moment.js的使用。

我们来看一下 个人资料页面 中显示的时间戳。当前 user.html模板允许使用Python生成时间的字符串表示。现在使用Flask-Moment渲染这个时间戳,如下:

Flask-Moment使用的语法类似于 JavaScript库的语法,一个区别是 moment()的参数现在是一个Python datetime对象,而不是一个ISO 8601字符串。moment()从模板发出的调用还会自动生成所需的JavaScript代码,以将呈现的时间戳插入到DOM的适当位置。

可以利用Flask-Momentmoment.js的第二个地方是_post.html子模板,它是从/index/user页面中调用的。在当前版本的模板中,每个帖子前面都有一个“username says:”行。现在添加一个fromNow()时间戳:

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值