Python脚本异常:从字符串提取指定格式的起止日期时间
从多格式字符串提取日期时间的Python解决方案
看起来你在处理多种格式的日期时间字符串提取时遇到了麻烦,从你给出的测试用例来看,这些格式的多样性确实容易让普通的分割和解析逻辑出问题——有的是完整的日期时间区间,有的只有单个日期/时间,还有的是日期时间加单独的结束时间。我帮你完善了代码,能覆盖所有这些场景:
from datetime import datetime, timedelta def extract_datetimes(date_time_str): # 定义所有可能用到的日期时间格式 full_dt_format = "%a %b %d %Y at %I:%M %p" date_only_format = "%a %b %d %Y" time_only_format = "%I:%M %p" # 用" to "分割字符串,区分单段(无结束时间)和两段(有时间区间)的情况 parts = date_time_str.split(' to ') start_dt = None end_dt = None # 处理只有单个日期/时间的情况 if len(parts) == 1: part = parts[0].strip() # 先尝试解析完整日期时间 try: start_dt = datetime.strptime(part, full_dt_format) end_dt = start_dt # 无结束时间时默认与开始时间一致,可根据需求调整 except ValueError: # 尝试解析仅日期格式 try: start_dt = datetime.strptime(part, date_only_format) end_dt = start_dt except ValueError: print(f"无法解析的格式:{part}") return None, None # 处理包含时间区间的情况 elif len(parts) == 2: start_part = parts[0].strip() end_part = parts[1].strip() # 解析开始部分 try: start_dt = datetime.strptime(start_part, full_dt_format) except ValueError: try: start_dt = datetime.strptime(start_part, date_only_format) except ValueError: print(f"无法解析开始部分:{start_part}") return None, None # 解析结束部分:先试完整日期时间,再试仅时间(复用开始日期),最后试仅日期 try: end_dt = datetime.strptime(end_part, full_dt_format) except ValueError: try: time_obj = datetime.strptime(end_part, time_only_format) end_dt = start_dt.replace(hour=time_obj.hour, minute=time_obj.minute) # 处理跨天情况:如果结束时间早于开始时间,自动加一天 if end_dt < start_dt: end_dt += timedelta(days=1) except ValueError: try: end_dt = datetime.strptime(end_part, date_only_format) except ValueError: print(f"无法解析结束部分:{end_part}") return None, None return start_dt, end_dt # 测试你给出的所有用例 test_cases = [ 'Sun Apr 22 2018 at 02:00 pm to Sun May 13 2018 at 02:00 pm', 'Sun Apr 22 2018 at 02:00 pm', 'Sat Apr 28 2018 at 05:00 pm to 07:00 am', 'Fri Oct 15 2021', 'Sat Aug 01 2020', 'Wed Jan 22 2020 at 01:30 pm', 'Wed Jan 01 2020 to Thu Jan 02 2020' ] for case in test_cases: start, end = extract_datetimes(case) print(f"输入:{case}") print(f"开始时间:{start.strftime('%Y-%m-%d %H:%M:%S') if start else '解析失败'}") print(f"结束时间:{end.strftime('%Y-%m-%d %H:%M:%S') if end else '解析失败'}") print("-"*50)
关键细节说明:
- 格式覆盖:预先定义了三种核心格式,完美匹配你给出的所有测试场景;
- 容错解析:用
try-except依次尝试不同格式,避免因为格式不匹配直接抛出异常; - 跨天处理:针对
下午5点到早上7点这种跨天场景,自动给结束时间加一天,符合实际逻辑; - 灵活调整:如果不需要默认结束时间等于开始时间,可以把对应位置改成
end_dt = None,按需调整即可。
你原代码里delim = 'to' if del...的截断部分,应该是最初尝试判断分隔符的逻辑,这里直接用split(' to ')更简洁,也能准确区分是否存在时间区间。
内容的提问来源于stack exchange,提问作者Deba




