Python:如何判断输入是否包含年月日成分的有效日期?
解决dateutil parser过于宽松的日期检测问题
针对你遇到的dateutil parser误判时间范围为日期的问题,有两种可行的解决方向:
一、给dateutil parser添加严格验证逻辑
无需更换库,通过自定义规则过滤仅含时分的输入,确保只有包含年月日成分的内容被判定为日期:
基础验证:强制输入提供年月日信息
设置一个固定的基准默认日期,对比解析结果的年月日是否与基准一致——如果一致,说明输入未提供有效年月日,判定为非日期:
from dateutil import parser from datetime import datetime def is_valid_date_with_ymd(input_str): default_date = datetime(1900, 1, 1) try: parsed_date = parser.parse(input_str, default=default_date, fuzzy=False) # 检查解析后的年月日是否来自输入而非默认值 if parsed_date.year != default_date.year or parsed_date.month != default_date.month or parsed_date.day != default_date.day: return True, parsed_date return False, None except (parser.ParserError, ValueError): return False, None # 测试示例 print(is_valid_date_with_ymd("2023-08-22T12:00:00")) # (True, datetime.datetime(2023, 8, 22, 12, 0)) print(is_valid_date_with_ymd("12/08/2023")) # (True, datetime.datetime(2023, 8, 12, 0, 0)) print(is_valid_date_with_ymd("12:00-16:00")) # (False, None)
进阶验证:过滤带时间范围的日期输入
如果需要排除像2023-08-22 12:00-16:00这类带时间范围的内容,可以结合fuzzy_with_tokens获取未解析的部分,判断是否包含时间范围格式:
def is_valid_date_with_full_ymd(input_str): default_date = datetime(1900, 1, 1) try: parsed_date, tokens = parser.parse(input_str, default=default_date, fuzzy_with_tokens=True) # 先验证年月日非默认值 if parsed_date.year == default_date.year and parsed_date.month == default_date.month and parsed_date.day == default_date.day: return False, None # 检查未解析部分是否为时间范围 for token in tokens: token_str = token.strip() parts = token_str.split("-") if len(parts) == 2 and all(t.count(":") == 1 for t in parts): return False, None return True, parsed_date except (parser.ParserError, ValueError): return False, None # 测试示例 print(is_valid_date_with_full_ymd("2023-08-22 12:00-16:00")) # (False, None) print(is_valid_date_with_full_ymd("2023-08-22 12:00")) # (True, datetime.datetime(2023, 8, 22, 12, 0))
二、使用更严格的第三方库
如果不想写过多自定义逻辑,以下两个库可以直接实现严格的日期解析:
1. pendulum
pendulum的解析器支持strict模式,仅接受包含完整日期成分的输入,仅时间的内容会直接抛出错误:
import pendulum def is_valid_date_pendulum(input_str): try: parsed_date = pendulum.parse(input_str, strict=True) return True, parsed_date except pendulum.parsing.exceptions.ParseError: return False, None # 测试示例 print(is_valid_date_pendulum("2023-08-22T12:00:00")) # (True, DateTime(2023, 8, 22, 12, 0, 0, tzinfo=Timezone('UTC'))) print(is_valid_date_pendulum("12:00-16:00")) # (False, None)
2. dateparser
通过settings参数强制要求输入包含年、月、日三个部分,仅时间的输入会返回None:
from dateparser import parse def is_valid_date_dateparser(input_str): parsed_date = parse(input_str, settings={'REQUIRE_PARTS': ['year', 'month', 'day']}) return parsed_date is not None, parsed_date # 测试示例 print(is_valid_date_dateparser("2023-08-22")) # (True, datetime.datetime(2023, 8, 22, 0, 0)) print(is_valid_date_dateparser("12:00")) # (False, None)
内容的提问来源于stack exchange,提问作者ThrawnCA
相关产品推荐
相关产品推荐

