基于Python開發(fā)一個(gè)有趣的工作時(shí)長計(jì)算器
概述
隨著遠(yuǎn)程辦公和彈性工作制的興起,個(gè)人及團(tuán)隊(duì)對于工作時(shí)長的準(zhǔn)確統(tǒng)計(jì)需求日益增長。雖然市面上有眾多復(fù)雜的考勤軟件,但對于簡單的時(shí)間計(jì)算需求,一個(gè)輕量級且界面友好的桌面應(yīng)用更具實(shí)用性和便利性。
本文介紹的“工作時(shí)長計(jì)算器”基于Python的PyQt5庫開發(fā),體積小巧,界面簡潔,支持用戶輸入上下班時(shí)間,一鍵計(jì)算出當(dāng)天工作時(shí)長,并可將結(jié)果復(fù)制到剪貼板,方便粘貼到日報(bào)、考勤系統(tǒng)或聊天工具中。
功能介紹
輸入上下班時(shí)間(HH:MM格式)
自動(dòng)計(jì)算并顯示工作時(shí)長,支持跨天工作時(shí)段
復(fù)制工作時(shí)長到剪貼板,一鍵分享
窗口置頂功能,方便隨時(shí)查看和操作
友好的錯(cuò)誤提示,避免無效時(shí)間格式輸入
自定義窗口圖標(biāo)與樣式美化,提升用戶體驗(yàn)
界面展示
1. 主界面

圖1:工作時(shí)長計(jì)算器主界面,簡潔明了,支持鍵盤輸入與按鈕操作
2. 計(jì)算結(jié)果顯示與復(fù)制反饋

圖2:計(jì)算完成后顯示時(shí)長,點(diǎn)擊復(fù)制按鈕彈出提示
軟件使用步驟說明
啟動(dòng)程序:運(yùn)行python work_time_calculator.py
輸入上班時(shí)間:如08:30
輸入下班時(shí)間:如17:45
點(diǎn)擊“計(jì)算工作時(shí)長”按鈕,顯示工作時(shí)長,例如08:15
點(diǎn)擊“復(fù)制時(shí)長”按鈕,將結(jié)果復(fù)制到剪貼板,方便粘貼
勾選“窗口置頂”,保持程序界面在最前端
如輸入格式錯(cuò)誤,彈出錯(cuò)誤提示框,請按提示修改時(shí)間格式
代碼詳解
1.窗口初始化與布局
class WorkTimeCalculator(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("工作時(shí)長計(jì)算器")
self.setFixedSize(320, 380)
# 設(shè)置窗口圖標(biāo)
icon_path = self.resource_path("time.ico")
self.setWindowIcon(QIcon(icon_path))
# 窗口置頂屬性
self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
self.duration_str = ""
self.init_ui()
- QWidget是PyQt中最基礎(chǔ)的窗口類。
- 固定窗口大小,保證UI布局一致性。
- 使用自定義圖標(biāo)美化程序。
- 通過Qt.WindowStaysOnTopHint保持窗口置頂。
UI組件布局采用QVBoxLayout垂直堆疊控件,樣式使用QFont和setStyleSheet增強(qiáng)視覺體驗(yàn)。
2.工作時(shí)長計(jì)算核心邏輯
def calculate_time(self):
start_text = self.input_start.text().strip()
end_text = self.input_end.text().strip()
try:
start_time = datetime.strptime(start_text, "%H:%M")
end_time = datetime.strptime(end_text, "%H:%M")
if end_time < start_time:
end_time = end_time.replace(day=start_time.day + 1)
duration = end_time - start_time
total_minutes = duration.seconds // 60
hours = total_minutes // 60
minutes = total_minutes % 60
self.duration_str = f"{hours:02}:{minutes:02}"
self.result_label.setText(f"?? 工作時(shí)長:{self.duration_str}")
except ValueError:
QMessageBox.warning(self, "? 錯(cuò)誤", "請輸入有效時(shí)間格式,如 09:00")
使用datetime.strptime解析輸入時(shí)間。
處理跨天工作(如夜班,結(jié)束時(shí)間小于開始時(shí)間時(shí),自動(dòng)視為第二天)。
計(jì)算時(shí)間差,轉(zhuǎn)換成小時(shí)和分鐘。
結(jié)果格式化為HH:MM,更新界面標(biāo)簽顯示。
異常處理避免程序崩潰,彈出錯(cuò)誤提示框。
3.剪貼板復(fù)制與狀態(tài)提示
def copy_duration(self):
if self.duration_str:
QApplication.clipboard().setText(self.duration_str)
self.show_status_message(f"?? 時(shí)長 {self.duration_str} 已復(fù)制到剪貼板", 1200)
else:
QMessageBox.warning(self, "?? 無數(shù)據(jù)", "請先計(jì)算工作時(shí)長")
def show_status_message(self, message, timeout=1000):
self.status_label.setText(message)
self.status_label.setVisible(True)
QTimer.singleShot(timeout, lambda: self.status_label.setVisible(False))
復(fù)制時(shí)長字符串到系統(tǒng)剪貼板。
使用狀態(tài)欄顯示短暫提示,提升用戶交互體驗(yàn)。
未計(jì)算前復(fù)制操作給出警告提示。
4.窗口置頂功能
def toggle_topmost(self, state):
if state == Qt.Checked:
self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
else:
self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)
self.show()
通過QCheckBox切換窗口置頂屬性。
動(dòng)態(tài)刷新窗口狀態(tài),確保設(shè)置生效。
源碼下載
import sys
import os
from PyQt5.QtWidgets import (
QApplication, QWidget, QLabel, QLineEdit, QPushButton,
QVBoxLayout, QMessageBox, QCheckBox
)
from PyQt5.QtGui import QFont, QIcon
from PyQt5.QtCore import Qt, QTimer
from datetime import datetime
class WorkTimeCalculator(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("工作時(shí)長計(jì)算器")
self.setFixedSize(320, 380)
# 設(shè)置窗口圖標(biāo)
icon_path = self.resource_path("time.ico")
self.setWindowIcon(QIcon(icon_path))
self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
self.duration_str = ""
self.init_ui()
def init_ui(self):
font = QFont("Arial", 12)
self.label_start = QLabel("????? 上班時(shí)間 (HH:MM):")
self.label_start.setFont(font)
self.input_start = QLineEdit()
self.input_start.setPlaceholderText("如:08:30")
self.input_start.setFont(font)
self.input_start.setStyleSheet("""
QLineEdit {
border: 2px solid #ccc;
border-radius: 10px;
padding: 6px 10px;
}
""")
self.label_end = QLabel("?? 下班時(shí)間 (HH:MM):")
self.label_end.setFont(font)
self.input_end = QLineEdit()
self.input_end.setPlaceholderText("如:17:45")
self.input_end.setFont(font)
self.input_end.setStyleSheet("""
QLineEdit {
border: 2px solid #ccc;
border-radius: 10px;
padding: 6px 10px;
}
""")
self.button_calc = QPushButton("? 計(jì)算工作時(shí)長")
self.button_calc.setFont(font)
self.button_calc.setStyleSheet("""
QPushButton {
background-color: #4CAF50;
color: white;
border: none;
border-radius: 10px;
padding: 8px;
}
QPushButton:hover {
background-color: #45a049;
}
QPushButton:pressed {
background-color: #3e8e41;
}
""")
self.button_calc.clicked.connect(self.calculate_time)
self.result_label = QLabel("?? 工作時(shí)長:--:--")
self.result_label.setFont(QFont("Arial", 13, QFont.Bold))
self.copy_button = QPushButton("?? 復(fù)制時(shí)長")
self.copy_button.setFont(font)
self.copy_button.setStyleSheet("""
QPushButton {
background-color: #2196F3;
color: white;
border: none;
border-radius: 10px;
padding: 8px;
}
QPushButton:hover {
background-color: #1e88e5;
}
QPushButton:pressed {
background-color: #1976d2;
}
""")
self.copy_button.clicked.connect(self.copy_duration)
self.checkbox_topmost = QCheckBox("?? 窗口置頂")
self.checkbox_topmost.setFont(font)
self.checkbox_topmost.setChecked(True)
self.checkbox_topmost.stateChanged.connect(self.toggle_topmost)
self.status_label = QLabel("")
self.status_label.setFont(QFont("Arial", 10))
self.status_label.setStyleSheet("color: white; background-color: #444; padding: 4px; border-radius: 4px;")
self.status_label.setAlignment(Qt.AlignCenter)
self.status_label.setVisible(False)
layout = QVBoxLayout()
layout.setSpacing(8)
layout.setContentsMargins(16, 16, 16, 16)
layout.addWidget(self.label_start)
layout.addWidget(self.input_start)
layout.addWidget(self.label_end)
layout.addWidget(self.input_end)
layout.addWidget(self.button_calc)
layout.addWidget(self.result_label)
layout.addWidget(self.copy_button)
layout.addWidget(self.checkbox_topmost)
layout.addWidget(self.status_label)
self.setLayout(layout)
def calculate_time(self):
start_text = self.input_start.text().strip()
end_text = self.input_end.text().strip()
try:
start_time = datetime.strptime(start_text, "%H:%M")
end_time = datetime.strptime(end_text, "%H:%M")
if end_time < start_time:
end_time = end_time.replace(day=start_time.day + 1)
duration = end_time - start_time
total_minutes = duration.seconds // 60
hours = total_minutes // 60
minutes = total_minutes % 60
self.duration_str = f"{hours:02}:{minutes:02}"
self.result_label.setText(f"?? 工作時(shí)長:{self.duration_str}")
except ValueError:
QMessageBox.warning(self, "? 錯(cuò)誤", "請輸入有效時(shí)間格式,如 09:00")
def copy_duration(self):
if self.duration_str:
QApplication.clipboard().setText(self.duration_str)
self.show_status_message(f"?? 時(shí)長 {self.duration_str} 已復(fù)制到剪貼板", 1200)
else:
QMessageBox.warning(self, "?? 無數(shù)據(jù)", "請先計(jì)算工作時(shí)長")
def show_status_message(self, message, timeout=1000):
self.status_label.setText(message)
self.status_label.setVisible(True)
QTimer.singleShot(timeout, lambda: self.status_label.setVisible(False))
def toggle_topmost(self, state):
if state == Qt.Checked:
self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
else:
self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)
self.show()
def resource_path(self, relative_path):
"""解決打包后資源路徑問題"""
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setStyle("Fusion")
window = WorkTimeCalculator()
window.show()
sys.exit(app.exec_())
總結(jié)與展望
本文詳細(xì)介紹了基于PyQt5的“工作時(shí)長計(jì)算器”的開發(fā)過程,涵蓋了窗口設(shè)計(jì)、時(shí)間處理邏輯、交互細(xì)節(jié)及用戶體驗(yàn)優(yōu)化。該工具簡單實(shí)用,適合日常辦公人員快速統(tǒng)計(jì)工作時(shí)長。
未來可以拓展的功能有:
- 支持批量導(dǎo)入多天時(shí)間記錄,自動(dòng)生成日報(bào)
- 增加午休、加班等特殊時(shí)段計(jì)算支持
- 導(dǎo)出統(tǒng)計(jì)報(bào)表(Excel、PDF等格式)
- 美化UI,支持多語言切換和主題模式
到此這篇關(guān)于基于Python開發(fā)一個(gè)有趣的工作時(shí)長計(jì)算器的文章就介紹到這了,更多相關(guān)Python工作時(shí)長計(jì)算器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python中l(wèi)ist循環(huán)語句用法實(shí)例
這篇文章主要介紹了python中l(wèi)ist循環(huán)語句用法,以實(shí)例形式詳細(xì)介紹了Python針對list的解析,包含各種常見的遍歷操作及原理分析,需要的朋友可以參考下2014-11-11
python實(shí)現(xiàn)FFT快速傅立葉變換算法案例
FFT(快速傅里葉變換)是計(jì)算DFT及其逆變換的一種算法,其基本思想是利用DFT的對稱性和周期性,通過分而治之的策略將DFT分解為更小的DFT,從而降低計(jì)算復(fù)雜度,FFT的算法步驟包括選擇分解、重新排序、蝶形運(yùn)算和逐層計(jì)算,在Python中2024-10-10
python+selenium識別驗(yàn)證碼并登錄的示例代碼
本篇文章主要介紹了python+selenium識別驗(yàn)證碼并登錄的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12
Python實(shí)現(xiàn)爬取網(wǎng)頁中動(dòng)態(tài)加載的數(shù)據(jù)
這篇文章主要介紹了Python實(shí)現(xiàn)爬取網(wǎng)頁中動(dòng)態(tài)加載的數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08

