公司可能给外包人员,或者计算某项目工作一共时长多少,再或者某人请假导致工时计算非常费劲(如果不是整点请假则更复杂),网上没有找到此类工具,写了python程序,封装成EXE小工具供大家下载使用,如果不方便可以把工作起止时间外置到json或者ini记事本这种里,这样外侧修改不用重复封装(实在不会改可以留言让我改,新人新一次发帖)
兼容了多种复杂时间输入,比如2025.1.1 8:00 和2025/1/1 8:00等等,图中日期年月和时分之间有一个换行符也兼容
可以设置详细时分来计算,保留两位小数点
下载:蓝奏云 密码:dbm7
可能360会报毒但python程序无问题,不放心可以自己封装
import tkinter as tk
from tkinter import ttk
from datetime import datetime, timedelta
from dateutil import parser
import re
am_start = 8
am_end = 12
pm_start = 13
pm_end = 18
# 定义每天的工作时间段
WORK_PERIODS = [
(timedelta(hours=am_start), timedelta(hours=am_end)),
(timedelta(hours=pm_start), timedelta(hours=pm_end)),
]
def calculate_work_hours(start_time: datetime, end_time: datetime) -> float:
if end_time <= start_time:
return 0.00
total_work_hours = 0.00
current_day = start_time.date()
while current_day <= end_time.date():
for period_start, period_end in WORK_PERIODS:
work_start = datetime.combine(current_day, datetime.min.time()) + period_start
work_end = datetime.combine(current_day, datetime.min.time()) + period_end
# 计算当前时间段与工作时间段的交集
actual_start = max(start_time, work_start)
actual_end = min(end_time, work_end)
if actual_end > actual_start:
delta = actual_end - actual_start
total_work_hours += delta.total_seconds() / 3600
current_day += timedelta(days=1)
return total_work_hours
def preprocess_datetime_input(dt_str):
dt_str = dt_str.strip()
# 适配多种复杂输入时间情况
# 把换行符(或多个空白字符)替换为单个空格
dt_str = re.sub(r'\s+', ' ', dt_str)
# 修复没有空格连接日期和时间的情况,例如 2025.02.2508:00
dt_str = re.sub(r'(\d{4}[./-]?\d{2}[./-]?\d{2})(\d{2}:\d{2})', r'\1 \2', dt_str)
return dt_str
# 调用使用
def run(start,end,other_data):
try:
start_dt = parser.parse(start)
end_dt = parser.parse(end)
except Exception as e:
print("解析时间失败,请检查输入格式!")
exit(1)
worked_hours = calculate_work_hours(start_dt, end_dt)
# 转换额外工时为 float,如果失败就设为 0
try:
extra = float(other_data) if other_data else 0.00
except ValueError:
extra = 0.00
return worked_hours + extra
# 创建主窗口
root = tk.Tk()
root.title("工时计算器")
root.geometry("300x300") # 设置窗口大小
root.resizable(False, False) # 禁止调整窗口大小
# 创建主框架,设置内边距以美化布局
main_frame = ttk.Frame(root, padding="10")
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# 第一框:自定义的只读值
label1 = ttk.Label(main_frame, text="上午上班时间:")
label1.grid(row=0, column=0, pady=5, sticky=tk.W)
entry1 = ttk.Entry(main_frame, width=20)
entry1.insert(0, f"{am_start}点~{am_end}点") # 设置默认值
entry1.config(state='readonly') # 设置为只读
entry1.grid(row=0, column=1, pady=5)
# 第二框:自定义的只读值
label2 = ttk.Label(main_frame, text="下午上班时间")
label2.grid(row=1, column=0, pady=5, sticky=tk.W)
entry2 = ttk.Entry(main_frame, width=20)
entry2.insert(0, f"{pm_start}点~{pm_end}点") # 设置默认值
entry2.config(state='readonly') # 设置为只读
entry2.grid(row=1, column=1, pady=5)
# 第三框:输入日期
label3 = ttk.Label(main_frame, text="输入开始日期:")
label3.grid(row=2, column=0, pady=5, sticky=tk.W)
entry3 = ttk.Entry(main_frame, width=20)
entry3.grid(row=2, column=1, pady=5)
# 第四框:输入日期
label4 = ttk.Label(main_frame, text="输入结束日期:")
label4.grid(row=3, column=0, pady=5, sticky=tk.W)
entry4 = ttk.Entry(main_frame, width=20)
entry4.grid(row=3, column=1, pady=5)
# 第五框:输入数值
label5 = ttk.Label(main_frame, text="选填额外工时:")
label5.grid(row=4, column=0, pady=5, sticky=tk.W)
entry5 = ttk.Entry(main_frame, width=20)
entry5.grid(row=4, column=1, pady=5)
# 第六框:清空按钮
def clear_entries():
entry3.delete(0, tk.END)
entry4.delete(0, tk.END)
entry5.delete(0, tk.END)
result_entry.config(state='normal') # 临时解除只读状态
result_entry.delete(0, tk.END)
result_entry.config(state='readonly') # 恢复只读状态
# 第六框:按钮行(清空 和 计算)
clear_button = ttk.Button(main_frame, text="清空", command=clear_entries)
clear_button.grid(row=5, column=0, pady=10)
def calculate_work_hours2():
start_date = entry3.get()
end_date = entry4.get()
extra_hours = entry5.get()
# 调用你自己的计算函数,例如:
try:
result = run(start_date, end_date, extra_hours)
result = round(result, 2) # 保留两位小数
except Exception as e:
result = "输入错误!"
# 显示结果
result_entry.config(state='normal')
result_entry.delete(0, tk.END)
result_entry.insert(0, result)
result_entry.config(state='readonly')
run_button = ttk.Button(main_frame, text="计算", command=calculate_work_hours2)
run_button.grid(row=5, column=1, pady=10)
# 第七框:显示结果
label_result = ttk.Label(main_frame, text="计算工时结果:")
label_result.grid(row=6, column=0, pady=5, sticky=tk.W)
result_entry = ttk.Entry(main_frame, width=20)
result_entry.config(state='normal') # 设置为只读,换成了普通,只读不能重复计算
result_entry.grid(row=6, column=1, pady=5)
# 运行主循环
root.mainloop()
以上大致逻辑,使用tkinter创建几个框,复制粘贴进入时间后,扔给后台计算函数求出工时(两位小数点)如果额外有加班等工时,可以在额外工时内写入数值或者负数,汇总成一个总数。