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

JavaFX应用中如何判断工作时长是否属于白天/夜间时段

嘿,咱们一步步来解决这个问题。你已经拿到了工作的开始/结束时间,也算出了总时长,现在需要把它拆分成白天(6:00-22:00)和夜间时段,尤其是像凌晨3点到晚上11点这种跨时段的复杂情况对吧?我给你整理了一套可行的方案:

核心思路

不管工作时段跨不跨天,我们都可以把整个时间段拆成三部分处理:

  • 第一天的剩余时段(从开始时间到当天结束)
  • 中间完整的整天(如果有的话)
  • 最后一天的起始时段(从当天开始到结束时间)

对于每个部分,单独计算其中属于白天的时长,最后加起来就是总白天时长,总时长减去白天时长就是夜间时长。

代码实现(兼容你现有逻辑)

我基于你给出的代码片段,补充了白天/夜间时长的计算逻辑,还处理了跨天的场景:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Calendar;

public class WorkTimeHandler {
    // 定义白天时段的边界:6:00到22:00
    private static final int DAY_START = 6;
    private static final int DAY_END = 22;
    // 常量:1小时、1天的毫秒数
    private static final long HOUR_MILLIS = 3600000L;
    private static final long DAY_MILLIS = 86400000L;

    public void CalculNbreJourTravaille() {
        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm");
        try {
            // 这里替换成你从JavaFX控件获取的开始/结束时间
            Date startTime = format.parse("03/10/2024 03:00");
            Date endTime = format.parse("03/10/2024 23:00");

            long totalWorkMillis = endTime.getTime() - startTime.getTime();
            if (totalWorkMillis <= 0) {
                System.out.println("结束时间不能早于开始时间,请检查输入!");
                return;
            }

            // 计算白天和夜间时长
            long dayWorkMillis = calculateDayTimeDuration(startTime, endTime);
            long nightWorkMillis = totalWorkMillis - dayWorkMillis;

            // 转换为更易读的小时格式
            double dayHours = dayWorkMillis / (double)HOUR_MILLIS;
            double nightHours = nightWorkMillis / (double)HOUR_MILLIS;

            // 这里可以把结果绑定到JavaFX的UI控件上,比如Label
            // dayTimeLabel.setText(String.format("白天时长:%.2f小时", dayHours));
            // nightTimeLabel.setText(String.format("夜间时长:%.2f小时", nightHours));
            System.out.printf("统计结果:白天%.2f小时,夜间%.2f小时%n", dayHours, nightHours);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 计算两个时间之间的白天总时长(毫秒)
    private long calculateDayTimeDuration(Date start, Date end) {
        Calendar startCal = Calendar.getInstance();
        startCal.setTime(start);
        Calendar endCal = Calendar.getInstance();
        endCal.setTime(end);

        long totalDayMillis = 0;

        // 情况1:开始和结束在同一天
        if (isSameDay(startCal, endCal)) {
            return calculateSameDayDayTime(startCal, endCal);
        }

        // 情况2:跨天,先算第一天的白天时长
        Calendar dayEndOfFirstDay = (Calendar) startCal.clone();
        dayEndOfFirstDay.set(Calendar.HOUR_OF_DAY, DAY_END);
        dayEndOfFirstDay.set(Calendar.MINUTE, 0);
        dayEndOfFirstDay.set(Calendar.SECOND, 0);
        dayEndOfFirstDay.set(Calendar.MILLISECOND, 0);

        Calendar dayStartOfFirstDay = (Calendar) startCal.clone();
        dayStartOfFirstDay.set(Calendar.HOUR_OF_DAY, DAY_START);
        dayStartOfFirstDay.set(Calendar.MINUTE, 0);
        dayStartOfFirstDay.set(Calendar.SECOND, 0);
        dayStartOfFirstDay.set(Calendar.MILLISECOND, 0);

        long firstDaySegmentStart = Math.max(start.getTime(), dayStartOfFirstDay.getTime());
        long firstDaySegmentEnd = Math.min(end.getTime(), dayEndOfFirstDay.getTime());
        if (firstDaySegmentStart < firstDaySegmentEnd) {
            totalDayMillis += firstDaySegmentEnd - firstDaySegmentStart;
        }

        // 计算中间完整的整天的白天时长(每天白天固定16小时)
        startCal.add(Calendar.DAY_OF_YEAR, 1);
        while (!isSameDay(startCal, endCal)) {
            totalDayMillis += (DAY_END - DAY_START) * HOUR_MILLIS;
            startCal.add(Calendar.DAY_OF_YEAR, 1);
        }

        // 计算最后一天的白天时长
        Calendar dayStartOfLastDay = (Calendar) endCal.clone();
        dayStartOfLastDay.set(Calendar.HOUR_OF_DAY, DAY_START);
        dayStartOfLastDay.set(Calendar.MINUTE, 0);
        dayStartOfLastDay.set(Calendar.SECOND, 0);
        dayStartOfLastDay.set(Calendar.MILLISECOND, 0);

        Calendar dayEndOfLastDay = (Calendar) endCal.clone();
        dayEndOfLastDay.set(Calendar.HOUR_OF_DAY, DAY_END);
        dayEndOfLastDay.set(Calendar.MINUTE, 0);
        dayEndOfLastDay.set(Calendar.SECOND, 0);
        dayEndOfLastDay.set(Calendar.MILLISECOND, 0);

        long lastDaySegmentStart = Math.max(startCal.getTime(), dayStartOfLastDay.getTime());
        long lastDaySegmentEnd = Math.min(end.getTime(), dayEndOfLastDay.getTime());
        if (lastDaySegmentStart < lastDaySegmentEnd) {
            totalDayMillis += lastDaySegmentEnd - lastDaySegmentStart;
        }

        return totalDayMillis;
    }

    // 判断两个Calendar是否是同一天
    private boolean isSameDay(Calendar cal1, Calendar cal2) {
        return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)
                && cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR);
    }

    // 计算同一天内的白天时长
    private long calculateSameDayDayTime(Calendar start, Calendar end) {
        Calendar dayStart = (Calendar) start.clone();
        dayStart.set(Calendar.HOUR_OF_DAY, DAY_START);
        dayStart.set(Calendar.MINUTE, 0);
        dayStart.set(Calendar.SECOND, 0);
        dayStart.set(Calendar.MILLISECOND, 0);

        Calendar dayEnd = (Calendar) start.clone();
        dayEnd.set(Calendar.HOUR_OF_DAY, DAY_END);
        dayEnd.set(Calendar.MINUTE, 0);
        dayEnd.set(Calendar.SECOND, 0);
        dayEnd.set(Calendar.MILLISECOND, 0);

        // 取重叠区间的起始和结束时间
        long segmentStart = Math.max(start.getTimeInMillis(), dayStart.getTimeInMillis());
        long segmentEnd = Math.min(end.getTimeInMillis(), dayEnd.getTimeInMillis());

        return segmentStart < segmentEnd ? segmentEnd - segmentStart : 0;
    }

    // 测试用主方法
    public static void main(String[] args) {
        new WorkTimeHandler().CalculNbreJourTravaille();
    }
}
额外建议

如果你的项目使用Java 8及以上版本,强烈建议替换成java.timeAPI(比如LocalDateTime、Duration),旧的Date和Calendar不仅难用,还存在线程安全问题。用新API的话,代码会更简洁易懂,比如判断同一天可以直接用LocalDate.from(startTime).isEqual(LocalDate.from(endTime))。

另外,把计算结果集成到JavaFX界面时,直接把格式化后的字符串绑定到UI控件的textProperty()就可以了,比如:

Label dayTimeLabel = new Label();
dayTimeLabel.setText(String.format("白天时长:%.2f小时", dayHours));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:45:07