人力资源应用开发:MySQL考勤加班计算与时间格式化实现咨询
嘿,我来帮你搞定这两个核心需求!先从你提到的格式化时间输入框问题入手,再聊MySQL里考勤加班时长的计算逻辑。
一、修复并优化JFormattedTextField的时间输入限制
你当前的代码里createFormatter(" ##:##:##")的掩码配置不够严谨,而且缺少合法时间的验证逻辑(比如小时不能超过23,分钟/秒不能超过59)。这里给你一套完整的初始化方案,用MaskFormatter严格限制HH:mm:ss格式,同时确保输入的时间合法:
首先实现一个靠谱的createFormatter方法:
private MaskFormatter createFormatter(String mask) throws ParseException { MaskFormatter formatter = new MaskFormatter(mask); formatter.setPlaceholderCharacter('0'); // 用0填充未输入的空位,确保格式完整 formatter.setValidCharacters("0123456789"); // 只允许输入数字 // 添加自定义验证器,确保输入的是合法的HH:mm:ss时间 formatter.setValidator(new javax.swing.JFormattedTextField.AbstractFormatter() { @Override public Object stringToValue(String text) throws ParseException { // 用正则匹配合法的时间格式 if (!text.matches("([01]\\d|2[0-3]):([0-5]\\d):([0-5]\\d)")) { throw new ParseException("请输入合法的HH:mm:ss格式时间", 0); } return text; } @Override public String valueToString(Object value) throws ParseException { return value != null ? value.toString() : "00:00:00"; } }); return formatter; }
然后是初始化时间输入框和日期输入框的完整代码:
private void initInputComponents() { try { // 初始化时间输入框(严格限制HH:mm:ss格式) jFormattedTextField1 = new JFormattedTextField(createFormatter("##:##:##")); // 设置默认值为当前系统时间 Date currentDate = new Date(); SimpleDateFormat timeFormatter = new SimpleDateFormat("HH:mm:ss"); jFormattedTextField1.setValue(timeFormatter.format(currentDate)); // 设置提示文本,引导用户输入 jFormattedTextField1.setToolTipText("请输入HH:mm:ss格式的时间"); // 添加输入合法性监听,非法输入时高亮提示 jFormattedTextField1.addPropertyChangeListener("value", evt -> { if (jFormattedTextField1.isEditValid()) { jFormattedTextField1.setBackground(Color.WHITE); } else { jFormattedTextField1.setBackground(Color.PINK); } }); // 初始化日期输入框(示例:yyyy-MM-dd格式) JFormattedTextField dateInput = new JFormattedTextField(new SimpleDateFormat("yyyy-MM-dd")); dateInput.setValue(currentDate); dateInput.setToolTipText("请输入yyyy-MM-dd格式的日期"); // 记得将dateInput添加到你的界面容器中(比如JPanel) } catch (ParseException ex) { ex.printStackTrace(); JOptionPane.showMessageDialog(null, "输入框初始化失败:" + ex.getMessage()); } }
二、MySQL中基于考勤数据计算加班时长
假设你的考勤表结构大致如下(可以根据实际业务调整字段):
CREATE TABLE attendance ( id INT PRIMARY KEY AUTO_INCREMENT, emp_id INT NOT NULL COMMENT '员工ID', work_date DATE NOT NULL COMMENT '考勤日期', clock_in DATETIME NOT NULL COMMENT '上班打卡时间', clock_out DATETIME NOT NULL COMMENT '下班打卡时间', normal_daily_hours DECIMAL(5,2) DEFAULT 8.0 COMMENT '每日标准工作时长(小时)' );
1. 基础加班时长计算(单位:小时)
核心思路是先计算实际工作时长,再减去标准时长,正数即为加班时长(避免出现负数值):
SELECT emp_id, work_date, clock_in, clock_out, normal_daily_hours, -- 计算实际工作时长(转换为小时) TIMESTAMPDIFF(SECOND, clock_in, clock_out) / 3600 AS actual_work_hours, -- 计算加班时长,若实际时长≤标准时长则加班为0 GREATEST(0, TIMESTAMPDIFF(SECOND, clock_in, clock_out) / 3600 - normal_daily_hours) AS overtime_hours FROM attendance;
2. 格式化加班时长为HH:mm:ss格式
如果需要把加班时长转换成HH:mm:ss的可读格式,可以用嵌套查询实现:
SELECT emp_id, work_date, CONCAT( LPAD(FLOOR(overtime_seconds / 3600), 2, '0'), ':', LPAD(FLOOR((overtime_seconds % 3600) / 60), 2, '0'), ':', LPAD(overtime_seconds % 60, 2, '0') ) AS overtime_duration FROM ( SELECT emp_id, work_date, -- 计算加班总秒数 GREATEST(0, TIMESTAMPDIFF(SECOND, clock_in, clock_out) - normal_daily_hours * 3600) AS overtime_seconds FROM attendance ) AS overtime_calc;
3. 进阶:区分工作日/休息日加班
如果需要区分工作日和休息日加班(比如休息日加班按1.5倍计算),可以结合DAYOFWEEK函数判断日期是否为周末:
SELECT emp_id, work_date, -- 判断是否为周末(周日=1,周六=6) CASE WHEN DAYOFWEEK(work_date) IN (1,6) THEN '休息日' ELSE '工作日' END AS work_type, -- 基础加班时长 GREATEST(0, TIMESTAMPDIFF(SECOND, clock_in, clock_out) / 3600 - normal_daily_hours) AS base_overtime, -- 调整后的加班时长(休息日按1.5倍计算) GREATEST(0, TIMESTAMPDIFF(SECOND, clock_in, clock_out) / 3600 - normal_daily_hours) * CASE WHEN DAYOFWEEK(work_date) IN (1,6) THEN 1.5 ELSE 1 END AS adjusted_overtime FROM attendance;
内容的提问来源于stack exchange,提问作者Abdallah zoubi
相关产品推荐
相关产品推荐

