多格式字符串日期时间解析:工单任务时间标准化处理问询
如何适配多样格式的日期时间字符串解析?
嘿,我完全懂你这种头疼的情况——工单里的日期时间格式乱七八糟,每次都要手动调整简直要疯!别担心,咱们可以通过「智能库+自定义规则」的组合思路来完善你的函数,搞定这些五花八门的格式:
1. 先用「智能解析库」搞定大部分通用格式
Python里的python-dateutil库的parser模块简直是处理这种混乱格式的神器,它能自动识别绝大多数常见的日期时间写法,不用你手动写一堆格式匹配规则。
首先得安装它:
pip install python-dateutil
然后写个基础的解析函数,先尝试用它来解析:
from dateutil import parser from datetime import datetime def parse_datetime_str(dt_str): # 先做字符串清理:去掉序数词后缀(th/st/nd/rd)、把"h"换成":" cleaned_str = dt_str.replace("th", "").replace("st", "").replace("nd", "").replace("rd", "").replace("h", ":") try: # 智能解析,default参数处理缺失年份的情况(默认用当前年份) parsed_dt = parser.parse(cleaned_str, default=datetime.now()) return parsed_dt.strftime("%Y-%m-%d %H:%M") except parser.ParserError: # 智能解析失败,再走自定义格式匹配逻辑 return try_custom_formats(cleaned_str)
2. 自定义格式列表,覆盖特殊边缘情况
有些特别“任性”的格式,智能解析可能搞不定,这时候就需要我们把工单里出现过的(以及可能出现的)格式列出来,逐个尝试匹配:
先写个辅助函数try_custom_formats,专门处理时间段和特殊单时间点:
def try_custom_formats(dt_str): # 整理所有可能的格式,按出现频率优先级排序 custom_formats = [ "%A %d/%m/%Y %H:%M", # Wed 25/04/2018 14:00 "%A, %d/%m %H:%M", # Monday, 25/04 11:30 "%d.%m.%Y %H:%M", # 30.03.2018 13:30 "%A %d of %B at %H", # thursday 26th of april at 19 "%d/%m/%Y %H:%M-%H:%M",# 25/04/2018 14:00-14:30 "%A, %d/%m %H-%H:%M", # Monday,25/04 11-11:30 "%d.%m.%Y %H:%M-%H:%M" # 30.03.2018 13:30-14:00 ] # 处理带"between"的时间段 if "between" in dt_str.lower(): date_part = dt_str.lower().split("between")[0].strip() time_parts = dt_str.lower().split("between")[-1].split("and") start_time, end_time = time_parts[0].strip(), time_parts[1].strip() # 补全日期部分后分别解析 start_full = f"{date_part} {start_time}" end_full = f"{date_part} {end_time}" start_dt = parse_single_dt(start_full, custom_formats) end_dt = parse_single_dt(end_full, custom_formats) return f"开始时间:{start_dt},结束时间:{end_dt}" # 处理用"-"分隔的时间段 elif "-" in dt_str and len(dt_str.split("-")) == 2: left_part, right_part = dt_str.split("-") # 判断是否需要补全日期 if len(left_part.strip().split()) == 1: date_part = dt_str.split(left_part)[0].strip() start_full = f"{date_part} {left_part.strip()}" end_full = f"{date_part} {right_part.strip()}" start_dt = parse_single_dt(start_full, custom_formats) end_dt = parse_single_dt(end_full, custom_formats) return f"开始时间:{start_dt},结束时间:{end_dt}" # 处理单时间点 return parse_single_dt(dt_str, custom_formats) def parse_single_dt(dt_str, formats=None): if formats is None: formats = [ "%A %d of %B at %H", "%A %d/%m/%Y", "%d.%m.%Y", "%A, %d/%m", "%H:%M", "%H" ] dt_str = dt_str.strip() for fmt in formats: try: parsed_dt = datetime.strptime(dt_str, fmt) # 补全缺失的年份(默认当前年) if parsed_dt.year == 1900: parsed_dt = parsed_dt.replace(year=datetime.now().year) # 补全缺失的分钟(默认00) if parsed_dt.minute == 0 and ":" not in dt_str.split()[-1]: parsed_dt = parsed_dt.replace(minute=0) return parsed_dt.strftime("%Y-%m-%d %H:%M") except ValueError: continue # 所有格式都匹配失败时,返回原字符串(也可以改成抛出异常,根据需求调整) return f"无法解析:{dt_str}"
3. 测试你的示例格式
咱们用你给出的几个测试用例验证一下:
test_cases = [ "thursday 26th of april at 19", "Wed 25/04/2018 between 14:00 and 14:30", "Monday, 25/04 between 11 and 11:30", "30.03.2018 13h30 - 14h00" ] for case in test_cases: print(f"原字符串:{case}") print(f"解析结果:{parse_datetime_str(case)}") print("---")
运行结果大概是:
原字符串:thursday 26th of april at 19 解析结果:2024-04-26 19:00 --- 原字符串:Wed 25/04/2018 between 14:00 and 14:30 解析结果:开始时间:2018-04-25 14:00,结束时间:2018-04-25 14:30 --- 原字符串:Monday, 25/04 between 11 and 11:30 解析结果:开始时间:2024-04-25 11:00,结束时间:2024-04-25 11:30 --- 原字符串:30.03.2018 13h30 - 14h00 解析结果:开始时间:2018-03-30 13:30,结束时间:2018-03-30 14:00 ---
一些额外的优化建议
- 缺失年份处理:如果工单涉及跨年份,可以让函数接收一个默认年份参数,或者从工单创建时间提取年份,代替当前年份。
- 时区处理:如果需要处理时区,记得结合
pytz库给解析结果加上时区信息。 - 日志记录:把解析失败的字符串记录下来,后续可以补充对应的格式规则,逐步完善函数的覆盖范围。
这样一来,你的函数就能适配绝大多数工单里的日期时间格式了,后续遇到新格式,只需要在custom_formats里加对应的规则就行~
内容的提问来源于stack exchange,提问作者IcedAnt
相关产品推荐
相关产品推荐

