Python Flask中存入session的datetime对象时区信息丢失问题如何解决
问题成因
- 绝大多数Web框架的session默认使用JSON格式做序列化持久化,而JSON原生不支持Python的时区感知datetime对象(带tzinfo属性的datetime实例)。序列化时框架会默认把这类对象转换为不带时区的 naive datetime 或者纯时间字符串,反序列化读取时就会丢失时区信息。
- 你赋值后立即打印时区正常,是因为此时还未触发session的序列化流程;调用装饰器后框架自动执行session的持久化存储,经过序列化-反序列化流程后时区信息就被抹除了。
解决方案
下面提供3种常用的可落地方案:
方案1:存储为ISO时间字符串(最通用,无额外配置)
存储时直接把时区感知datetime转为标准ISO格式字符串,读取时再转回datetime对象即可保留全部时区信息:
# 存入session的逻辑 import datetime from pytz import timezone utc = timezone('utc') session['login_time'] = datetime.datetime.now(utc).isoformat() # 读取session的逻辑 login_time = datetime.datetime.fromisoformat(session['login_time']) # 此时login_time为带UTC时区的datetime对象,输出为2021-06-11 23:56:00.161971+00:00
方案2:存储为Unix时间戳(存储体积最小,适合数值比对场景)
存储时转为秒级时间戳,读取时再绑定UTC时区即可:
# 存入session的逻辑 utc = timezone('utc') session['login_time'] = datetime.datetime.now(utc).timestamp() # 读取session的逻辑 login_time = datetime.datetime.fromtimestamp(session['login_time'], tz=timezone('utc'))
方案3:自定义session序列化器(适合项目中大量存储datetime对象的场景)
以Flask框架为例,你可以重写默认的JSON序列化器,让它自动处理时区感知datetime对象:
from flask import Flask from flask.json import JSONEncoder from datetime import datetime class CustomJSONEncoder(JSONEncoder): def default(self, obj): if isinstance(obj, datetime): return obj.isoformat() return super().default(obj) app = Flask(__name__) app.json_encoder = CustomJSONEncoder # 额外配置反序列化钩子即可实现存、取全流程自动转换,无需手动处理
内容的提问来源于stack exchange,提问作者user3525290
相关产品推荐
相关产品推荐

