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:
youpaishidifu
2026-08-03 15:20:28 +08:00
parent b07fc75d99
commit 2162a49068
+60 -2
View File
@@ -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)