使用Cookie传递客户端时区给Flask

使用Flask开发是遇到一个场景,需要在网页上以客户端时区展示时间。

优雅的处理办法是把原始GMT时间传递给前端,然后使用Moment.js库自动渲染本地时间

问题

然而这个项目中,时间需要通过Flask-Table在服务端渲染(Server Side Rendering),无法使用Moment.js库,因此只能使用古老的办法:让前端把时区传递给后端。

传递方法有很多种:

  1. 通过特定的API向客户端发送时区,这样做的麻烦在需要增加一个新的endpoint,维护麻烦
  2. 通过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的方法可能存在着隐私风险。

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据