本文目录导读:

我来帮你设计一个考勤统计脚本,以下是几种常见实现方式:
基础版 - Python 脚本
import pandas as pd
from datetime import datetime, time
import os
class AttendanceStats:
def __init__(self, data_file):
"""
初始化考勤统计
:param data_file: 考勤数据文件路径(CSV格式)
"""
self.data_file = data_file
self.df = pd.read_csv(data_file)
self._preprocess_data()
def _preprocess_data(self):
"""预处理数据"""
# 转换时间列
self.df['打卡时间'] = pd.to_datetime(self.df['打卡时间'])
self.df['日期'] = self.df['打卡时间'].dt.date
self.df['时间'] = self.df['打卡时间'].dt.time
def set_work_time(self, start_time="09:00", end_time="18:00"):
"""设置工作时间"""
self.work_start = datetime.strptime(start_time, "%H:%M").time()
self.work_end = datetime.strptime(end_time, "%H:%M").time()
def classify_attendance(self, time_record):
"""分类考勤状态"""
if time_record <= self.work_start:
return "正常"
elif time_record <= datetime.strptime("09:30", "%H:%M").time():
return "迟到"
else:
return "严重迟到"
def calculate_daily_stats(self):
"""计算每日统计"""
daily_stats = []
for date, group in self.df.groupby('日期'):
# 找出第一次和最后一次打卡
first_punch = group['时间'].min()
last_punch = group['时间'].max()
# 计算工作时长
if last_punch >= self.work_end:
work_hours = (datetime.combine(date, last_punch) -
datetime.combine(date, first_punch)).seconds / 3600
else:
work_hours = 0
daily_stats.append({
'日期': date,
'姓名': group['姓名'].iloc[0],
'上班打卡': first_punch,
'下班打卡': last_punch,
'状态': self.classify_attendance(first_punch),
'工作时长(小时)': round(work_hours, 2)
})
return pd.DataFrame(daily_stats)
def generate_monthly_report(self, month=None):
"""生成月度报告"""
if month:
self.df = self.df[self.df['打卡时间'].dt.month == month]
daily_stats = self.calculate_daily_stats()
# 汇总统计
report = []
for employee in self.df['姓名'].unique():
employee_data = daily_stats[daily_stats['姓名'] == employee]
report.append({
'姓名': employee,
'出勤天数': len(employee_data),
'迟到次数': len(employee_data[employee_data['状态'] != '正常']),
'平均工作时长': round(employee_data['工作时长(小时)'].mean(), 2),
'加班天数': len(employee_data[employee_data['工作时长(小时)'] > 8])
})
return pd.DataFrame(report)
def export_to_excel(self, output_file="考勤统计报告.xlsx"):
"""导出到Excel"""
monthly_report = self.generate_monthly_report()
with pd.ExcelWriter(output_file) as writer:
# 写入月度报告
monthly_report.to_excel(writer, sheet_name='月度统计', index=False)
# 写入每日明细
daily_stats = self.calculate_daily_stats()
daily_stats.to_excel(writer, sheet_name='每日明细', index=False)
print(f"报表已生成:{output_file}")
# 使用示例
if __name__ == "__main__":
# 准备测试数据
test_data = {
'姓名': ['张三', '张三', '李四', '李四'],
'打卡时间': [
'2024-01-15 08:55:00',
'2024-01-15 18:30:00',
'2024-01-15 09:15:00',
'2024-01-15 17:45:00'
]
}
# 创建测试文件
pd.DataFrame(test_data).to_csv('考勤数据.csv', index=False)
# 执行统计
stats = AttendanceStats('考勤数据.csv')
stats.set_work_time("09:00", "18:00")
stats.export_to_excel()
Shell 脚本版本(Linux)
#!/bin/bash
# 考勤统计脚本(适用于文本格式的打卡记录)
# 使用方法: ./attendance_stats.sh [数据文件] [月份]
DATA_FILE="${1:-attendance.txt}"
MONTH="${2:-$(date +%m)}"
OUTPUT_FILE="attendance_report_${MONTH}.txt"
# 检查文件是否存在
if [ ! -f "$DATA_FILE" ]; then
echo "错误: 数据文件 $DATA_FILE 不存在"
echo "用法: $0 [数据文件] [月份]"
exit 1
fi
# 初始化统计变量
declare -A attendance_count
declare -A late_count
declare -A absent_count
echo "====== 考勤统计报告 ======" > "$OUTPUT_FILE"
echo "月份: $MONTH" >> "$OUTPUT_FILE"
echo "生成时间: $(date)" >> "$OUTPUT_FILE"
echo "===========================" >> "$OUTPUT_FILE"
# 处理考勤数据(假设格式:姓名 日期 打卡时间)
while IFS=' ' read -r name date punch_time; do
# 只处理指定月份的数据
record_month=$(echo $date | cut -d'-' -f2)
if [ "$record_month" != "$MONTH" ]; then
continue
fi
# 计数
((attendance_count[$name]++))
# 判断迟到(假设上班时间是9:00)
if [[ "$punch_time" > "09:15" ]]; then
((late_count[$name]++))
fi
done < "$DATA_FILE"
# 生成报告
echo -e "\n出勤统计:" >> "$OUTPUT_FILE"
printf "%-10s %-10s %-10s %-10s\n" "姓名" "出勤" "迟到" "缺勤" >> "$OUTPUT_FILE"
echo "----------------------------------------" >> "$OUTPUT_FILE"
# 获取所有员工
employee_list=$(awk '{print $1}' "$DATA_FILE" | sort -u)
for employee in $employee_list; do
attendance=${attendance_count[$employee]:-0}
late=${late_count[$employee]:-0}
absent=$((20 - attendance)) # 假设每月工作日20天
printf "%-10s %-10d %-10d %-10d\n" \
"$employee" "$attendance" "$late" "$absent" >> "$OUTPUT_FILE"
done
echo -e "\n报告已生成: $OUTPUT_FILE"
数据库版本(SQL)
-- 创建考勤表
CREATE TABLE attendance (
id INT PRIMARY KEY AUTO_INCREMENT,
employee_id INT NOT NULL,
punch_time DATETIME NOT NULL,
punch_type ENUM('上班', '下班') DEFAULT '上班',
INDEX idx_employee_date (employee_id, punch_time)
);
-- 插入示例数据
INSERT INTO attendance (employee_id, punch_time, punch_type) VALUES
(1, '2024-01-15 08:50:00', '上班'),
(1, '2024-01-15 18:10:00', '下班'),
(2, '2024-01-15 09:20:00', '上班'),
(2, '2024-01-15 17:50:00', '下班');
-- 考勤统计查询
SELECT
e.name AS 姓名,
DATE(a.punch_time) AS 日期,
MIN(CASE WHEN a.punch_type = '上班' THEN a.punch_time END) AS 上班时间,
MAX(CASE WHEN a.punch_type = '下班' THEN a.punch_time END) AS 下班时间,
CASE
WHEN TIME(MIN(CASE WHEN a.punch_type = '上班' THEN a.punch_time END)) <= '09:00:00'
THEN '正常'
ELSE '迟到'
END AS 状态,
TIMESTAMPDIFF(
HOUR,
MIN(CASE WHEN a.punch_type = '上班' THEN a.punch_time END),
MAX(CASE WHEN a.punch_type = '下班' THEN a.punch_time END)
) AS 工作时长
FROM attendance a
JOIN employees e ON a.employee_id = e.id
WHERE MONTH(a.punch_time) = 1 -- 指定月份
GROUP BY e.name, DATE(a.punch_time);
-- 月度统计汇总
SELECT
e.name AS 姓名,
COUNT(DISTINCT DATE(a.punch_time)) AS 出勤天数,
SUM(CASE
WHEN TIME(MIN(CASE WHEN a.punch_type = '上班' THEN a.punch_time END)) > '09:00:00'
THEN 1 ELSE 0
END) AS 迟到次数,
AVG(TIMESTAMPDIFF(
HOUR,
MIN(CASE WHEN a.punch_type = '上班' THEN a.punch_time END),
MAX(CASE WHEN a.punch_type = '下班' THEN a.punch_time END)
)) AS 平均工作时长
FROM attendance a
JOIN employees e ON a.employee_id = e.id
WHERE MONTH(a.punch_time) = 1
GROUP BY e.name;
使用建议
- 数据准备:确保考勤数据格式统一,包含姓名、日期、打卡时间等信息
- 定时执行:可以使用 cron 定时任务自动执行统计
- 异常处理:添加缺失打卡、重复打卡等异常情况的处理
- 可视化:结合 matplotlib 等库生成图表
- 扩展功能:添加加班统计、请假处理等
根据你的具体需求(数据格式、系统环境、统计要求),选择最适合的实现方式。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播