如何在Python中将带时区的字符串字面量转为datetime对象
问题:从repr格式的字符串还原带时区的datetime对象
日志中的时间戳字符串是Python datetime对象的repr输出,格式如下:
... timestamp=datetime.datetime(2023, 2, 25, 15, 59, 21, 410787, tzinfo=tzlocal()), ...
我用自定义的chop函数提取出括号内的内容:
timestamp_str = chop(line, 'timestamp=datetime.datetime(', '),') timestamp_chunks = timestamp_str.split(', ')
提取前7个数字构造datetime对象,能成功但会丢失时区信息:
dt_list = [int(x) for x in timestamp_chunks[0:7]] dt = datetime.datetime(*dt_list)
尝试直接把时区字符串加入列表再解包,会触发报错:
dt_list.append(timestamp_chunks[7]) dt = datetime.datetime(*dt_list)
报错信息:
tzinfo argument must be None or of a tzinfo subclass, not type 'str'
试过dateutil.parser,但因为格式非标准无法识别;也考虑过转成Unix时间戳,但还是解决不了时区问题。希望找到方法直接从这种repr格式的字符串还原带时区的datetime对象。
解决方案
方法1:使用eval(注意安全风险)
因为该字符串本身就是Python datetime对象的构造语句,直接提取完整语句后用eval执行是最直接的方式,前提是你完全信任日志内容,避免恶意代码注入。
示例代码:
import datetime from tzlocal import get_localzone # 日志中用到tzlocal(),需提前导入对应模块 # 提取完整的datetime构造表达式 full_dt_expr = chop(line, 'timestamp=', '),') dt = eval(full_dt_expr)
如果日志中使用的是其他时区类(如pytz时区),需要确保对应模块已提前导入,否则eval会报错。
方法2:手动解析时区信息
如果不想用eval,可以针对日志中的时区格式手动处理,以tzlocal()为例:
import datetime from tzlocal import get_localzone timestamp_str = chop(line, 'timestamp=datetime.datetime(', '),') timestamp_chunks = timestamp_str.split(', ') # 解析前7个时间参数 dt_args = [int(x) for x in timestamp_chunks[:7]] # 处理时区部分 tz_part = timestamp_chunks[7] if tz_part == 'tzinfo=tzlocal()': tz = get_localzone() else: # 若日志出现其他时区格式,可在此扩展处理逻辑 tz = None dt = datetime.datetime(*dt_args, tzinfo=tz)
补充说明
如果日志中存在多种时区类型,需要根据实际格式补充对应的解析逻辑;使用eval时一定要确保日志来源安全,避免执行恶意代码。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

