使用Flask开发是遇到一个场景,需要在网页上以客户端时区展示时间。
优雅的处理办法是把原始GMT时间传递给前端,然后使用Moment.js库自动渲染本地时间
问题
然而这个项目中,时间需要通过Flask-Table在服务端渲染(Server Side Rendering),无法使用Moment.js库,因此只能使用古老的办法:让前端把时区传递给后端。
传递方法有很多种:
- 通过特定的API向客户端发送时区,这样做的麻烦在需要增加一个新的endpoint,维护麻烦
- 通过Cookie传递。这是最终选择的方案,不需要服务端做任何事情,只需要在前端增加代码将客户的时区写入Cookie即可
解决方案
首先在前端页面(Flask的某个Template)增加以下代码:
<script>
var offset = new Date().getTimezoneOffset();
document.cookie = `timezoneOffset=${offset}; path=/`;
</script>
在我的项目中直接放到了所有页面,也就是所有页面执行时都会设置一次时区
然后在后端Flask 脚本里需要的地方使用以下代码来获取时区对应的offset:
from flask import request
.......
timezoneOffset = request.cookies.get('timezoneOffset')
........
这里得到的变量timezoneOffset是UTC-0时区时间与本地时间之间的相差的分钟数。如果是负数,说明是东半球;正数就是西半球。比如如果在中国北京时区,这里的timezoneOffset就会是-480(负8小时),具体信息可以查看这里的文档
有了客户时区以后,就可以按照自己的需求处理数据了
讨论
这个解决方案仍然不够优雅,主要的问题是
- 用户每次打开任意页面,都会刷新时区
- 用户每次发起网络连接,都会携带这个cookie
考虑到timezoneOffset仅仅只是一个整数数据,增加的传输和计算量可以忽略不计。 这里的解决方案肯定不能用来传递其他大规模的用户个人信息。
此外,随着各个国家都有互联网公司收集用户信息的严格管制,使用cookie的方法可能存在着隐私风险。