计算两时间段的重合天/小时/分钟/秒数(末尾附完整代码)

说明:

有时候我们在计算时间时,有让获取两时间段重合的天数这种需求,小编也是遇到了这样的需求,就封装了一个工具类,希望能帮助到大家。

我们先进行分析

求两个时间段重合的天数,例如求(2022-05-02 00:00:00 至 2022-05-12 23:59:59) 时间段和(2022-05-04 00:00:00 至 2022-05-13 05:00:00)时间段重合(交叉)的天数。

通过我们脑力计算,可获得重合的时间段为 (2022-05-04 00:00:00 至 2022-05-12 23:59:59),也就相当于重合天数为9天。可是这只是一种情况,接下来。我们会对重合(交叉)的情况进行分析:

两个时间段分别是:(aStart -- aEnd), [bStart -- bEnd]
若不好理解,可认为[bStart -- bEnd]是固定时间段,则是计算[aStart -- aEnd]时间段与[bStart -- bEnd]交叉的天数
两个时间段之间的重合天数,有以下几种情况:
情况一:[bStart -- bEnd]在(aStart -- aEnd)时间段内 if(aStart <= bStart && bEnd <= aEnd)
    (aStart -- [bStart -- bEnd] -- aEnd)
情况二:(aStart -- aEnd)在[bStart -- bEnd]时间段内 if(bStart <= aStart && aEnd <= bEnd)
    [bStart -- (aStart -- aEnd) -- bEnd]
情况三:(aStart -- aEnd)部分时间在[bStart -- bEnd]时间段内 if(aStart <= bStart && aEnd <= bEnd)
    (aStart -- [bStart -- aEnd) -- bEnd]
情况四:(aStart -- aEnd)部分时间在[bStart -- bEnd]时间段内 if(bStart <= aStart && bEnd <= aEnd)
    [bStart -- (aStart -- bEnd] -- aEnd)

经分析,两时间段能重合(交叉)的情况只有这四种情况,其他不能重合(交叉)的情况我们都默认重合天数为0即可。

经分析,我们可以根据这四种情况进行着手计算!

开码

首先,我们需要定义一个方法将String类型的时间格式化成Date并返回转换成Date的时间戳(也就是毫秒值

/**
     * 时间格式化
     * @param dateStr String类型时间格式
     * @return 该时间的时间戳
     */
    public static Long formatDateStr(String dateStr) {
    
    
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
    
    
            date = sdf.parse(dateStr);
        } catch (ParseException e) {
    
    
            e.printStackTrace();
            System.out.println("时间格式化错误");
        }
        return date.getTime();
    }

之后,定义一个方法,根据标识(flag)计算两个long类型的时间戳之间的天/小时/分钟/秒数

其中flag标识为时间单位标识“d为天,h为小时,m为分钟,s为秒”

/**
     * 计算两时间之间的时间 天/小时/分钟/秒数
     * @param bStartLong 开始时间时间戳
     * @param bEndLong 结束时间时间戳
     * @param flag 单位标识 d为天,h为小时,m为分钟,s为秒
     * @return 两时间之间的时间 天/小时/分钟/秒数
     */
    private static Double calcTime(Long bStartLong, Long bEndLong, String flag) {
    
    
        Double result = 0d;
        Long num = (bEndLong - bStartLong); // 毫秒
        BigDecimal tempNum = new BigDecimal(num);
        if ("d".equals(flag)) {
    
    
            // 天
            result = tempNum.divide(new BigDecimal("86400000"), 2, RoundingMode.HALF_UP).doubleValue(); // 24*60*60秒 = 1天
        } else if ("h".equals(flag)) {
    
    
            // 小时
            result = tempNum.divide(new BigDecimal("3600000"), 2, RoundingMode.HALF_UP).doubleValue(); // 60*60秒 = 1小时
        } else if ("m".equals(flag)) {
    
    
            // 分钟
            result = tempNum.divide(new BigDecimal("60000"), 2, RoundingMode.HALF_UP).doubleValue(); // 60秒 = 1分钟
        } else if ("s".equals(flag)) {
    
    
            // 秒
            result = tempNum.divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP).doubleValue();
        }
        return result;
    }

最后,对开头分析的四种情况进行判断即可。

/**
     * 获取两时间段的重合时间
     * @param aStartStr 时间段1开始时间
     * @param aEndStr 时间段1结束时间
     * @param bStartStr 时间段2开始时间
     * @param bEndStr 时间段2结束时间
     * @param flag 单位标识 d为天,h为小时,m为分钟,s为秒
     * @return 重合时间 天/小时/分钟/秒数
     */
    public static Double getIntersectDays(String aStartStr, String aEndStr, String bStartStr, String bEndStr, String flag) {
    
    
        // 时间段1
        Long aStartLong = formatDateStr(aStartStr);
        Long aEndLong = formatDateStr(aEndStr);
        // 时间段2
        Long bStartLong = formatDateStr(bStartStr);
        Long bEndLong = formatDateStr(bEndStr);

        Double num = 0d; // 默认重合(相交)为0
        // 当符合常规条件时,才进行判断计算
        if ((aStartLong < aEndLong) && (bStartLong < bEndLong)) {
    
    
            // 四种情况判断
            if ((aStartLong <= bStartLong) && (bEndLong <= aEndLong)) {
    
    
                // 情况一:只需要计算[bStart -- bEnd]之间的时间即可
                num = calcTime(bStartLong, bEndLong, flag);
            } else if ((bStartLong <= aStartLong) && (aEndLong <= bEndLong)) {
    
    
                // 情况二:只需要计算(aStart -- aEnd)之间的时间即可
                num = calcTime(aStartLong, aEndLong, flag);
            } else if ((aStartLong <= bStartLong) && (aEndLong <= bEndLong)) {
    
    
                // 情况三:只需要计算(bStart -- aEnd)之间的时间即可
                num = calcTime(bStartLong, aEndLong, flag);
            } else if ((bStartLong <= aStartLong) && (bEndLong <= aEndLong)) {
    
    
                // 情况四:只需要计算(bStart -- aEnd)之间的时间即可
                num = calcTime(aStartLong, bEndLong, flag);
            } else {
    
    
                // 其他情况,不相交,或者时间组合不符合 默认0
            }
        }
        return num;
    }
最后进行测试:
	public static void main(String[] args) {
    
    
        String aStartStr = "2022-05-02 00:00:00";
        String aEndStr = "2022-05-12 23:59:59";
        String bStartStr = "2022-05-04 00:00:00";
        String bEndStr = "2022-05-13 05:00:00";
        Double days = getIntersectDays(aStartStr, aEndStr, bStartStr, bEndStr, "d");
        Double hour = getIntersectDays(aStartStr, aEndStr, bStartStr, bEndStr, "h");
        Double min = getIntersectDays(aStartStr, aEndStr, bStartStr, bEndStr, "m");
        Double second = getIntersectDays(aStartStr, aEndStr, bStartStr, bEndStr, "s");
        System.out.println(days + " 天");
        System.out.println(hour + " 小时");
        System.out.println(min + " 分钟");
        System.out.println(second + " 秒");
    }

测试结果:
测试结果

总结:

如果想要计算两时间段的重合的工作日时间,可参考小编的另一篇博文(使用Java的Calendar类计算两段时间之间的工作日的天/小时/分钟/秒数)进行结合封装接口。

完整代码:
package fit.clover.blog.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Title: 计算两时间段的重合天数
 * @Author: Sophia
 * #Description: DateUtil
 * #Date: 2022/6/7 09:34
 */
public class CalcIntersectUtil {
    
    
    /**
     * 两个时间段分别是:(aStart -- aEnd), [bStart -- bEnd]
     * 若不好理解,可认为[bStart -- bEnd]是固定时间段,则是计算[aStart -- aEnd]时间段与[bStart -- bEnd]交叉的天数
     * 两个时间段之间的重合天数,有以下几种情况:
     *  情况一:[bStart -- bEnd]在(aStart -- aEnd)时间段内 if(aStart <= bStart && bEnd <= aEnd)
     *      (aStart -- [bStart -- bEnd] -- aEnd)
     *  情况二:(aStart -- aEnd)在[bStart -- bEnd]时间段内 if(bStart <= aStart && aEnd <= bEnd)
     *      [bStart -- (aStart -- aEnd) -- bEnd]
     *  情况三:(aStart -- aEnd)部分时间在[bStart -- bEnd]时间段内 if(aStart <= bStart && aEnd <= bEnd)
     *      (aStart -- [bStart -- aEnd) -- bEnd]
     *  情况四:(aStart -- aEnd)部分时间在[bStart -- bEnd]时间段内 if(bStart <= aStart && bEnd <= aEnd)
     *      [bStart -- (aStart -- bEnd] -- aEnd)
     *  经过分析,两时间段相交有这4中情况,所以我们可以根据这四种情况进行着手计算
     */

    /**
     * 获取两时间段的重合时间
     * @param aStartStr 时间段1开始时间
     * @param aEndStr 时间段1结束时间
     * @param bStartStr 时间段2开始时间
     * @param bEndStr 时间段2结束时间
     * @param flag 单位标识 d为天,h为小时,m为分钟,s为秒
     * @return 重合时间 天/小时/分钟/秒数
     */
    public static Double getIntersectDays(String aStartStr, String aEndStr, String bStartStr, String bEndStr, String flag) {
    
    
        // 时间段1
        Long aStartLong = formatDateStr(aStartStr);
        Long aEndLong = formatDateStr(aEndStr);
        // 时间段2
        Long bStartLong = formatDateStr(bStartStr);
        Long bEndLong = formatDateStr(bEndStr);

        Double num = 0d; // 默认重合(相交)为0
        // 当符合常规条件时,才进行判断计算
        if ((aStartLong < aEndLong) && (bStartLong < bEndLong)) {
    
    
            // 四种情况判断
            if ((aStartLong <= bStartLong) && (bEndLong <= aEndLong)) {
    
    
                // 情况一:只需要计算[bStart -- bEnd]之间的时间即可
                num = calcTime(bStartLong, bEndLong, flag);
            } else if ((bStartLong <= aStartLong) && (aEndLong <= bEndLong)) {
    
    
                // 情况二:只需要计算(aStart -- aEnd)之间的时间即可
                num = calcTime(aStartLong, aEndLong, flag);
            } else if ((aStartLong <= bStartLong) && (aEndLong <= bEndLong)) {
    
    
                // 情况三:只需要计算(bStart -- aEnd)之间的时间即可
                num = calcTime(bStartLong, aEndLong, flag);
            } else if ((bStartLong <= aStartLong) && (bEndLong <= aEndLong)) {
    
    
                // 情况四:只需要计算(bStart -- aEnd)之间的时间即可
                num = calcTime(aStartLong, bEndLong, flag);
            } else {
    
    
                // 其他情况,不相交,或者时间组合不符合 默认0
            }
        }
        return num;
    }

    /**
     * 计算两时间之间的时间 天/小时/分钟/秒数
     * @param bStartLong 开始时间时间戳
     * @param bEndLong 结束时间时间戳
     * @param flag 单位标识 d为天,h为小时,m为分钟,s为秒
     * @return 两时间之间的时间 天/小时/分钟/秒数
     */
    private static Double calcTime(Long bStartLong, Long bEndLong, String flag) {
    
    
        Double result = 0d;
        Long num = (bEndLong - bStartLong); // 毫秒
        BigDecimal tempNum = new BigDecimal(num);
        if ("d".equals(flag)) {
    
    
            // 天
            result = tempNum.divide(new BigDecimal("86400000"), 2, RoundingMode.HALF_UP).doubleValue(); // 24*60*60秒 = 1天
        } else if ("h".equals(flag)) {
    
    
            // 小时
            result = tempNum.divide(new BigDecimal("3600000"), 2, RoundingMode.HALF_UP).doubleValue(); // 60*60秒 = 1小时
        } else if ("m".equals(flag)) {
    
    
            // 分钟
            result = tempNum.divide(new BigDecimal("60000"), 2, RoundingMode.HALF_UP).doubleValue(); // 60秒 = 1分钟
        } else if ("s".equals(flag)) {
    
    
            // 秒
            result = tempNum.divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP).doubleValue();
        }
        return result;
    }

    /**
     * 时间格式化
     * @param dateStr String类型时间格式
     * @return 该时间的时间戳
     */
    public static Long formatDateStr(String dateStr) {
    
    
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
    
    
            date = sdf.parse(dateStr);
        } catch (ParseException e) {
    
    
            e.printStackTrace();
            System.out.println("时间格式化错误");
        }
        return date.getTime();
    }

    public static void main(String[] args) {
    
    
        String aStartStr = "2022-05-02 00:00:00";
        String aEndStr = "2022-05-12 23:59:59";
        String bStartStr = "2022-05-04 00:00:00";
        String bEndStr = "2022-05-13 05:00:00";
        Double days = getIntersectDays(aStartStr, aEndStr, bStartStr, bEndStr, "d");
        Double hour = getIntersectDays(aStartStr, aEndStr, bStartStr, bEndStr, "h");
        Double min = getIntersectDays(aStartStr, aEndStr, bStartStr, bEndStr, "m");
        Double second = getIntersectDays(aStartStr, aEndStr, bStartStr, bEndStr, "s");
        System.out.println(days + " 天");
        System.out.println(hour + " 小时");
        System.out.println(min + " 分钟");
        System.out.println(second + " 秒");
    }
}

希望对你有所帮助!

猜你喜欢

转载自blog.csdn.net/qq_42320934/article/details/125198214