【Flask/跟着学习】Flask大型教程项目#11:日期

14 篇文章 3 订阅

跟着学习(新版):https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xii-dates-and-times
回顾上一章:https://blog.csdn.net/weixin_41263513/article/details/85092856

本章内容

  • 时区转换
  • Moment.js和Flask-Moment
  • 使用Moment.js

时区转换

在datetime这个包内,datetime.now()调用返回我的位置的正确时间,而datetime.utcnow()调用返回UTC时区的时间,如果我可以让生活在世界不同地区的很多人在同一时间与我一起运行上述代码,datetime.now()函数将为每个人返回不同的结果,但datetime.utcnow()将始终返回同一个时间,因此,服务器必须管理一致且独立于位置的时间。

我不希望每个服务器在不同时区向数据库写入时间戳,这样管理起来会非常混乱,由于UTC是最常用的统一时区,,并且在datetime类中受支持,所以UTC将会是最棒的选择。但这种方法存在一个重要问题。对于不同时区的用户,如果他们在UTC时区看到时间,那么很难弄清楚发布帖子的时间,服务器的角度将时间戳标准化为UTC很有意义,但这会给用户带来体验上的问题。本章的目标是解决此问题。

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

我们可以从客户的计算机中获取时区信息,从而在他们看不见的地方悄咪咪的把UTC单位转换为他们的本地时间。以下内容相当专业,可以适当了解

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

“old school”方法是在用户首次登录应用程序时让Web浏览器以某种方式将时区信息发送到服务器。这可以通过Ajax调用完成,或者更简单地使用元刷新标记完成。一旦服务器知道时区,它就可以将其保存在用户的会话中,或者将其写入数据库中的用户条目,然后在渲染模板时用它调整所有时间戳。
“new school”的方法是不改变服务器中的东西,并允许使用JavaScript在客户端中进行从UTC到本地时区的转换。
这两个选项都是有效的,但第二个选项有很大的优势。知道用户的时区并不总是足以以用户期望的格式呈现日期和时间。浏览器还可以访问系统区域设置配置,该配置指定AM / PM与24小时制,DD / MM / YYYY与MM / DD / YYYY以及许多其他文化或区域样式之类的内容。

如果这还不够,那么new school方法还有一个优势。有一个开源库可以完成所有这些工作!

Moment.js和Flask-Moment

Moment.js是一个小型的开源JavaScript库,它可以将日期和时间渲染到一种格式。 前段时间我们创建了Flask-Moment,这是一个小型Flask扩展,可以很容易地将moment.js合并到应用程序中。记得别忘了pip install flask-moment

这个扩展要像其他flask的应用程序一样先初始化
文件:/app/–init–.py

# ...
from flask_moment import Moment

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

与其他扩展不同,Flask-Moment与moment.js一起使用,因此应用程序的所有模板都必须包含此库。 为确保此库始终可用,我将在base.html中添加它。 这可以通过两种方式完成。 最直接的方法是显式添加导入库的

...

{% block scripts %}
    {{ super() }}
    {{ moment.include_moment() }}
{% endblock %}

我在这里添加的block是由Flask-Bootstrap的基本模板导出的另一个块。 这是包含JavaScript导入的地方。 此块与以前的块不同,因为它已经在基本模板中定义了一些内容。 我想要做的就是添加moment.js库,而不会丢失基本内容。 这是通过super()语句实现的,该语句保留了base.html中的内容。 如果在模板中定义块而不使用super(),则基本模板中为此块定义的任何内容都将丢失

使用Moment.js

Moment.js为浏览器提供了一个时刻类。渲染时间戳的第一步是创建此类的对象,以下是日期和时间的ISO 8601标准格式:
{{year}} - {{month}} - {{day}} T {{hour}}:{{minute} }:{{second}} {{timezone}}。
我已经决定我只使用UTC时区,所以最后一部分总是Z,它代表ISO 8601标准中的UTC。

moment对象为不同的渲染选项提供了几种方法。 以下是一些最常见的选项:

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

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"

此示例创建一个时刻对象,初始化时间为2017年9月28日UTC时间下午9:45。您可以看到我在上面尝试的所有选项都以UTC-7呈现

请注意不同方法如何创建不同的表示。使用format(),您可以使用格式字符串控制输出的格式,类似于Python中的strftime函数。 fromNow()和calendar()方法很有趣,因为它们呈现了与当前时间相关的时间戳,因此您可以获得诸如“a minute ago”或“in two hours”等输出。

Flask-Moment扩展通过在模板中启用类似于JavaScript的时刻对象,极大地简化了moment.js的使用

我们来看一下配置文件页面中显示的时间戳。当前的user.html模板允许Python生成时间的字符串表示。我现在可以使用Flask-Moment渲染此时间戳
文件:/app/templates/user.html

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

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

我可以利用Flask-Moment和moment.js的第二个地方是_post.html子模板,它是从index和user页面调用的
文件:/app/templates/_post.html

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

这章其实非常简单,但也十分有必要,让我们来看看效果把!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值