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

如何用Python检测员工在不同地点的重叠打卡记录

识别同一员工跨门店重叠考勤记录的Python实现方案

下面提供两种可行的实现方案,分别基于你熟悉的Pandas工具,以及你考虑使用的DateTimeRange库:

方案一:用Pandas原生工具实现

步骤1:数据读取与预处理

先把考勤数据转换成DataFrame,再将日期和时间字段合并成完整的datetime时间戳,这是判断时间重叠的基础:

import pandas as pd

# 加载考勤数据(实际场景可替换为pd.read_csv读取文件)
data = {
    'store': ['store1', 'store1', 'store2', 'store2'],
    'name': ['reese', 'john', 'reese', 'bill'],
    'day': ['Mon', 'Mon', 'Mon', 'Mon'],
    'date': ['8/8/2022', '8/8/2022', '8/8/2022', '8/8/2022'],
    'clockin': ['8:55:32 AM', '8:55:27 AM', '9:00:00 AM', '12:36:35 PM'],
    'clockout': ['11:12:35 AM', '11:59:34 AM', '12:00:00 PM', '5:02:31 PM']
}
df = pd.DataFrame(data)

# 合并日期与打卡时间,转换为datetime类型
df['start_time'] = pd.to_datetime(df['date'] + ' ' + df['clockin'])
df['end_time'] = pd.to_datetime(df['date'] + ' ' + df['clockout'])

步骤2:分组检查时间重叠

按「员工姓名+日期」分组,对每组内的记录两两比对:判断是否属于不同门店,且时间区间存在重叠(重叠逻辑为区间A的开始时间 < 区间B的结束时间,且区间B的开始时间 < 区间A的结束时间):

def check_overlapping(group):
    # 遍历组内所有记录对
    for i in range(len(group)):
        row1 = group.iloc[i]
        for j in range(i+1, len(group)):
            row2 = group.iloc[j]
            # 不同门店+时间重叠触发标记
            if row1['store'] != row2['store']:
                if row1['start_time'] < row2['end_time'] and row2['start_time'] < row1['end_time']:
                    return pd.Series([True, row1, row2])
    return pd.Series([False, None, None])

# 分组执行检查
result = df.groupby(['name', 'date']).apply(check_overlapping)
result.columns = ['has_overlap', 'record1', 'record2']

# 筛选出有重叠的异常记录
overlapping_records = result[result['has_overlap'] == True]
print(overlapping_records)

方案二:用DateTimeRange库实现

DateTimeRange封装了时间区间的常用操作,无需自己写重叠判断逻辑,代码更直观:

步骤1:安装并导入库

pip install DateTimeRange

步骤2:数据预处理+重叠检查

预处理逻辑和Pandas方案一致,用DateTimeRange对象封装时间区间,调用内置的is_intersection方法判断重叠:

import pandas as pd
from datetimerange import DateTimeRange

# 同样先加载并预处理数据
data = {
    'store': ['store1', 'store1', 'store2', 'store2'],
    'name': ['reese', 'john', 'reese', 'bill'],
    'day': ['Mon', 'Mon', 'Mon', 'Mon'],
    'date': ['8/8/2022', '8/8/2022', '8/8/2022', '8/8/2022'],
    'clockin': ['8:55:32 AM', '8:55:27 AM', '9:00:00 AM', '12:36:35 PM'],
    'clockout': ['11:12:35 AM', '11:59:34 AM', '12:00:00 PM', '5:02:31 PM']
}
df = pd.DataFrame(data)
df['start_time'] = pd.to_datetime(df['date'] + ' ' + df['clockin'])
df['end_time'] = pd.to_datetime(df['date'] + ' ' + df['clockout'])

def check_overlap_with_dtr(group):
    # 为每条记录创建DateTimeRange对象
    range_list = []
    for idx, row in group.iterrows():
        time_range = DateTimeRange(row['start_time'], row['end_time'])
        range_list.append((row, time_range))
    
    # 遍历检查记录对
    for i in range(len(range_list)):
        row1, range1 = range_list[i]
        for j in range(i+1, len(range_list)):
            row2, range2 = range_list[j]
            if row1['store'] != row2['store'] and range1.is_intersection(range2):
                return pd.Series([True, row1, row2])
    return pd.Series([False, None, None])

# 分组执行并筛选结果
result = df.groupby(['name', 'date']).apply(check_overlap_with_dtr)
result.columns = ['has_overlap', 'record1', 'record2']
overlapping_records = result[result['has_overlap'] == True]
print(overlapping_records)

额外注意事项

  • 如果实际考勤数据的日期时间格式有差异,可以给pd.to_datetime指定format参数(比如format="%m/%d/%Y %I:%M:%S %p"),避免解析错误。
  • 若数据量很大,双重循环效率较低,可以先对每组的start_time排序,只检查相邻记录,能大幅提升性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 06:24:02