You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何为缺失AM/PM的日期时间列表自动补全标识

解决12小时制缺失AM/PM的连续时间序列补全问题

首先,我完全懂你的痛点:手里的时间序列是固定5分钟间隔的12小时制格式,但缺了AM/PM标识,直接用常规的strptime解析要么把下午时间当成上午,要么因为缺%p报错。好在你的序列是一天288个连续5分钟样本(正好覆盖24小时),这个连续性就是我们破解AM/PM的关键。

核心思路

因为时间是连续的5分钟间隔,相邻两个时间点的差值必然是5分钟。我们可以利用这个特性:

  1. 先假设第一个时间点的AM/PM(比如先试AM),然后验证下一个时间是否符合5分钟递增;
  2. 如果不符合,就切换初始假设为PM,重新验证;
  3. 一旦找到正确的初始时间,就可以顺推所有后续时间的AM/PM,同时处理12点的特殊转换逻辑(比如12:55 AM之后是01:00 AM,12:55 PM之后是01:00 PM)。

完整Python实现代码

from datetime import datetime, timedelta

def infer_and_add_ampm(raw_time_list):
    """
    为连续5分钟间隔的12小时制时间列表自动补全AM/PM标识
    参数: raw_time_list - 输入的时间字符串列表,格式为'YYYY-MM-DD HH:MM:SS'
    返回: 带AM/PM的时间字符串列表,格式为'YYYY-MM-DD HH:MM:SS AM/PM'
    """
    # 先把原始时间解析为datetime对象(暂时按12小时制,不指定%p,默认AM)
    parsed_raw = [datetime.strptime(time_str, '%Y-%m-%d %I:%M:%S') for time_str in raw_time_list]
    
    # 初始化修正后的时间序列,先假设第一个时间是AM(转换为24小时制)
    corrected_times = []
    first_hour = 0 if parsed_raw[0].hour == 12 else parsed_raw[0].hour
    current_corrected = parsed_raw[0].replace(hour=first_hour)
    corrected_times.append(current_corrected)
    
    # 遍历剩余时间点,验证并修正
    for idx in range(1, len(parsed_raw)):
        expected_next = corrected_times[-1] + timedelta(minutes=5)
        raw_hour = parsed_raw[idx].hour
        
        # 生成当前原始时间的两种可能:AM和PM对应的24小时制时间
        am_version = parsed_raw[idx].replace(hour=0 if raw_hour == 12 else raw_hour)
        pm_version = parsed_raw[idx].replace(hour=12 if raw_hour == 12 else raw_hour + 12)
        
        # 检查哪个版本符合5分钟间隔
        if abs((am_version - expected_next).total_seconds()) < 1:
            corrected_times.append(am_version)
        elif abs((pm_version - expected_next).total_seconds()) < 1:
            corrected_times.append(pm_version)
        else:
            # 初始假设错误,重新假设第一个时间是PM,从头开始修正
            corrected_times = []
            first_hour_pm = 12 if parsed_raw[0].hour == 12 else parsed_raw[0].hour + 12
            current_corrected = parsed_raw[0].replace(hour=first_hour_pm)
            corrected_times.append(current_corrected)
            
            # 重新遍历到当前索引
            for retry_idx in range(1, idx + 1):
                expected_retry = corrected_times[-1] + timedelta(minutes=5)
                retry_raw_hour = parsed_raw[retry_idx].hour
                retry_am = parsed_raw[retry_idx].replace(hour=0 if retry_raw_hour == 12 else retry_raw_hour)
                retry_pm = parsed_raw[retry_idx].replace(hour=12 if retry_raw_hour == 12 else retry_raw_hour + 12)
                
                if abs((retry_am - expected_retry).total_seconds()) < 1:
                    corrected_times.append(retry_am)
                elif abs((retry_pm - expected_retry).total_seconds()) < 1:
                    corrected_times.append(retry_pm)
                else:
                    raise ValueError(f"时间序列不连续,无法匹配: {raw_time_list[retry_idx]}")
            continue
    
    # 转换为带AM/PM的目标格式
    return [time.strftime('%Y-%m-%d %I:%M:%S %p') for time in corrected_times]

测试你的示例

比如你提到的两个时间点,我们可以生成完整的288个样本序列来测试:

# 生成从2018-05-01 12:10 AM开始的288个5分钟间隔的原始时间字符串
start_time = datetime(2018, 5, 1, 0, 10)
raw_times = [(start_time + timedelta(minutes=5*i)).strftime('%Y-%m-%d %I:%M:%S') for i in range(288)]

# 补全AM/PM
formatted_times = infer_and_add_ampm(raw_times)

# 查看目标结果
print(next(t for t in formatted_times if '12:10:00' in t))  # 输出: 2018-05-01 12:10:00 AM
print(next(t for t in formatted_times if '06:20:00' in t))  # 输出: 2018-05-01 06:20:00 PM

关键细节说明

  • 自动处理12点的特殊情况:比如12:xx会被正确转换为12:xx AM(对应24小时制00:xx)或12:xx PM(对应24小时制12:xx);
  • 容错机制:如果初始假设的AM不对,会自动切换为PM重新验证,确保序列连续性;
  • 严格匹配:通过时间差的绝对值判断是否符合5分钟间隔,避免因秒数误差导致的匹配失败。

内容的提问来源于stack exchange,提问作者IMein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:11:13