fix: 昨天的时间戳不再被误判为今天未来的21:14
- 在_ocr_text_has_fresh_timestamp中提取日期信息(如2026/8/2) - 如果日期是过去的(昨天或更早),跳过未来时间戳拦截 - 修改_is_timestamp_old函数,添加skip_future_check参数 - 解决问题:OCR文本包含2026/8/2 21:14:38,被误判为今天未来的21:14
This commit is contained in:
+60
-2
@@ -3390,6 +3390,31 @@ class MessageMonitor:
|
||||
normalized = re.sub(r'(\d{1,2})[.;](\d{2})(?:[.;](\d{2}))?', r'\1:\2:\3', text)
|
||||
timestamps = re.findall(r'\d{1,2}:\d{1,2}(?::\d{1,2})?', normalized)
|
||||
logger.debug(f"[ocr] 提取到时间戳: {timestamps}")
|
||||
|
||||
# 提取日期信息(如2026/8/2、2026-08-02等),用于判断时间戳是否真的是"未来"
|
||||
dates = re.findall(r'\d{4}[/-]\d{1,2}[/-]\d{1,2}', text)
|
||||
# 标准化日期分隔符
|
||||
dates = [d.replace('-', '/') for d in dates]
|
||||
logger.debug(f"[ocr] 提取到日期: {dates}")
|
||||
|
||||
# 计算日期差:如果是过去的日期(昨天或更早),时间戳不应该是"未来时间戳"
|
||||
has_past_date = False
|
||||
if dates:
|
||||
today = datetime.now().date()
|
||||
for date_str in dates:
|
||||
try:
|
||||
# 解析日期:2026/8/2 或 2026/08/02
|
||||
parts = date_str.split('/')
|
||||
if len(parts) == 3:
|
||||
y, m, d = int(parts[0]), int(parts[1]), int(parts[2])
|
||||
date_obj = datetime(y, m, d).date()
|
||||
date_diff = (today - date_obj).days
|
||||
if date_diff > 0: # 昨天或更早
|
||||
has_past_date = True
|
||||
logger.debug(f"[ocr] 检测到过去日期: {date_str} (距今{date_diff}天)")
|
||||
break
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
if not timestamps:
|
||||
# ⭐ 无可见时间戳:仅超短中文消息(如"好的""嗯")视为可能的新消息放行;
|
||||
# 较长文本无时间戳 → 无法验证新鲜性,可能是不含时间戳的历史/UI噪声
|
||||
@@ -3418,6 +3443,36 @@ class MessageMonitor:
|
||||
return False
|
||||
logger.debug(f"[ocr] 过滤器1结果: 无时间戳且非超短消息,丢弃: {text[:80]!r}")
|
||||
return False
|
||||
# 如果检测到过去日期(昨天或更早),时间戳不应该是"未来时间戳"
|
||||
# 直接放行,让后续逻辑判断是否过期
|
||||
if has_past_date:
|
||||
logger.debug(f"[ocr] 检测到过去日期,跳过未来时间戳拦截,直接判断是否过期")
|
||||
# 检查是否有新鲜时间戳(≤300s)
|
||||
for ts in timestamps:
|
||||
try:
|
||||
if not self._is_timestamp_old(ts, 300, skip_future_check=True):
|
||||
logger.debug(f"[ocr] 过滤器1结果: 过去日期+新鲜时间戳{ts}(≤300s),放行")
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
# 检查最新时间戳是否在300-600s之间
|
||||
newest_fresh_enough = False
|
||||
for ts in timestamps:
|
||||
try:
|
||||
if not self._is_timestamp_old(ts, 600, skip_future_check=True):
|
||||
newest_fresh_enough = True
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
if not newest_fresh_enough:
|
||||
logger.debug(f"[ocr] 过滤器1结果: 过去日期+最新时间戳已过期≥600s,丢弃: {text[:80]!r}")
|
||||
return False
|
||||
# 最新时间戳在 300-600s 之间,且文本含明确新鲜特征 → 放行
|
||||
if self._looks_fresh_content(text):
|
||||
logger.debug(f"[ocr] 过滤器1结果: 过去日期+时间戳全过期但最新≤600s且含新鲜特征,放行: {text[:80]!r}")
|
||||
return True
|
||||
logger.debug(f"[ocr] 过滤器1结果: 过去日期+时间戳全过期且无新鲜特征,丢弃: {text[:80]!r}")
|
||||
return False
|
||||
# 有新鲜时间戳 → 确定有新消息
|
||||
for ts in timestamps:
|
||||
try:
|
||||
@@ -3451,13 +3506,15 @@ class MessageMonitor:
|
||||
_TS_FUTURE_TOLERANCE_S = 15
|
||||
|
||||
@staticmethod
|
||||
def _is_timestamp_old(ts_str: str, max_age: int = 300) -> bool:
|
||||
def _is_timestamp_old(ts_str: str, max_age: int = 300, skip_future_check: bool = False) -> bool:
|
||||
"""检查 HH:MM 或 HH:MM:SS 时间戳是否超过 max_age 秒。
|
||||
处理跨午夜边界:如果 diff > 12h 说明是昨天的时间戳。
|
||||
未来时间戳硬拦截:同日内 diff < -容差 = 时间未到来(系统14:40不可能有16:00),丢弃。
|
||||
OCR 误读兜底:15:31→5:31(`1`笔画细被吞),若 h<12,尝试 h+10/h+12
|
||||
取 diff 最小者,若 < max_age 则视为 OCR 误读,放行。
|
||||
返回 True = 时间戳太老,应跳过。
|
||||
|
||||
skip_future_check: 如果为True,则跳过未来时间戳拦截(用于已检测到过去日期的情况)。
|
||||
"""
|
||||
ts = ts_str.strip()
|
||||
if not ts:
|
||||
@@ -3487,7 +3544,8 @@ class MessageMonitor:
|
||||
diff = (now - parsed).total_seconds()
|
||||
# 未来时间戳硬拦截(用户反馈:系统14:40 不能把 16:00 未到来的时间判为新鲜):
|
||||
# 跨午夜调整后仍为负 = 同日内未来时间,必为 OCR 误读/异常,直接丢弃
|
||||
if diff < -MessageMonitor._TS_FUTURE_TOLERANCE_S:
|
||||
# skip_future_check=True 时跳过此检查(用于已检测到过去日期的情况)
|
||||
if diff < -MessageMonitor._TS_FUTURE_TOLERANCE_S and not skip_future_check:
|
||||
logger.debug(f"[ts] 未来时间戳拦截: {ts} 比系统时间 {now.strftime('%H:%M:%S')} 晚 {-diff:.0f}s,未到来,丢弃")
|
||||
return True
|
||||
# OCR 误读兜底:h<12 且判定为老 → 尝试 h+10 / h+12(OCR 丢失前导1:15→5)
|
||||
|
||||
Reference in New Issue
Block a user