计算重叠时间段工具类


import lombok.Data;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 计算重叠时间段
 * author: zhangweida
 * date: 2023/12/05
 */
public class TimeCalculator {
    private static long calculateOverlapMinutes(String startTimeStr, String endTimeStr) {
        LocalDateTime startDateTime = LocalDateTime.parse(startTimeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime endDateTime = LocalDateTime.parse(endTimeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        LocalTime time0400 = LocalTime.of(4, 0,0);
        LocalTime time0420 = LocalTime.of(4, 20,0);
        LocalTime time1100 = LocalTime.of(11, 00,0);
        LocalTime time1200 = LocalTime.of(12, 00,0);
        LocalTime time1700 = LocalTime.of(17, 0,0);
        LocalTime time1800 = LocalTime.of(18, 0,0);
        LocalTime time1500 = LocalTime.of(15, 0,0);
        LocalTime time1520 = LocalTime.of(15, 20,0);
        LocalTime time2259 = LocalTime.of(22, 59,59);
        //这里为什么不是直接的00:00:00?因为是跨天的,如果是00:00:00会导致误差,所以往前推一秒,方便计算
        LocalTime time2359 = LocalTime.of(23, 59,59);

        long overlap = 0;

        /**
         * 新的
         * 04:00:00-04:20:00     0.33小时
         * 11:00:00-12:00:00     1小时
         * 15:00:00-15:20:00     0.33小时
         * 17:00:00-18:00:00     1小时
         * 22:59:59-23:59:59     1小时
         *
         * 旧的:
         * 重叠时间段1:11:20:00-12:20:00
         * 重叠时间段2:17:00:00-18:00:00
         * 重叠时间段3:22:59:59-23:59:59
         */
        LocalDateTime overlapStart0 = LocalDateTime.of(startDateTime.toLocalDate(), time0400);
        LocalDateTime overlapEnd0 = LocalDateTime.of(startDateTime.toLocalDate(), time0420);
        LocalDateTime overlapStart1 = LocalDateTime.of(startDateTime.toLocalDate(), time1100);
        LocalDateTime overlapEnd1 = LocalDateTime.of(startDateTime.toLocalDate(), time1200);
        LocalDateTime overlapStart2 = LocalDateTime.of(startDateTime.toLocalDate(), time1700);
        LocalDateTime overlapEnd2 = LocalDateTime.of(startDateTime.toLocalDate(), time1800);
        LocalDateTime overlapStart3 = LocalDateTime.of(startDateTime.toLocalDate(), time2259);
        LocalDateTime overlapEnd3 = LocalDateTime.of(endDateTime.toLocalDate(), time2359);
        LocalDateTime overlapStart4 = LocalDateTime.of(startDateTime.toLocalDate(), time1500);
        LocalDateTime overlapEnd4 = LocalDateTime.of(endDateTime.toLocalDate(), time1520);

        if (startDateTime.isBefore(overlapEnd0) && endDateTime.isAfter(overlapStart0)) {
            overlap += calculateOverlapMinutes(startDateTime, endDateTime, overlapStart0, overlapEnd0);
        }
        if (startDateTime.isBefore(overlapEnd1) && endDateTime.isAfter(overlapStart1)) {
            overlap += calculateOverlapMinutes(startDateTime, endDateTime, overlapStart1, overlapEnd1);
        }
        if (startDateTime.isBefore(overlapEnd2) && endDateTime.isAfter(overlapStart2)) {
            overlap += calculateOverlapMinutes(startDateTime, endDateTime, overlapStart2, overlapEnd2);
        }
        if (startDateTime.isBefore(overlapEnd3) && endDateTime.isAfter(overlapStart3)) {
            overlap += calculateOverlapMinutes(startDateTime, endDateTime, overlapStart3, overlapEnd3);
        }
        if (startDateTime.isBefore(overlapEnd4) && endDateTime.isAfter(overlapStart4)) {
            overlap += calculateOverlapMinutes(startDateTime, endDateTime, overlapStart4, overlapEnd4);
        }

        return overlap;
    }

    private static long calculateOverlapMinutes(LocalDateTime startDateTime, LocalDateTime endDateTime,
                                                LocalDateTime overlapStart, LocalDateTime overlapEnd) {
        LocalDateTime overlapStartMax = startDateTime.isBefore(overlapStart) ? overlapStart : startDateTime;
        LocalDateTime overlapEndMin = endDateTime.isAfter(overlapEnd) ? overlapEnd : endDateTime;
        return overlapStartMax.until(overlapEndMin, java.time.temporal.ChronoUnit.MINUTES);
    }

    public static List<TimeRange> splitTime(String startTime, String endTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date startDate = sdf.parse(startTime);
        Date endDate = sdf.parse(endTime);

        List<TimeRange> result = new ArrayList<>();

        Calendar startCal = Calendar.getInstance();
        startCal.setTime(startDate);
        Calendar endCal = Calendar.getInstance();
        endCal.setTime(endDate);

        if (startCal.get(Calendar.YEAR) == endCal.get(Calendar.YEAR)
                && startCal.get(Calendar.DAY_OF_YEAR) == endCal.get(Calendar.DAY_OF_YEAR)) {
            result.add(new TimeRange(startTime, endTime));
        } else {
            while (startCal.before(endCal)) {
                String s = sdf.format(startCal.getTime());
                startCal.set(Calendar.HOUR_OF_DAY, 23);
                startCal.set(Calendar.MINUTE, 59);
                startCal.set(Calendar.SECOND, 59);
                String e = sdf.format(startCal.getTime());

                if (startCal.get(Calendar.YEAR) == endCal.get(Calendar.YEAR)
                        && startCal.get(Calendar.DAY_OF_YEAR) == endCal.get(Calendar.DAY_OF_YEAR)) {
                    e = endTime;
                }

                result.add(new TimeRange(s, e));
                startCal.add(Calendar.DATE, 1);
                startCal.set(Calendar.HOUR_OF_DAY, 0);
                startCal.set(Calendar.MINUTE, 0);
                startCal.set(Calendar.SECOND, 0);
            }
        }

        return result;
    }

    public static long totalOverlapMinutes(String startTime,String endTime) throws ParseException {
        long overlapMinutes = 0;
        List<TimeRange> timeRanges = splitTime(startTime, endTime);
        for (int i = 0; i < timeRanges.size(); i++) {
            overlapMinutes += calculateOverlapMinutes(timeRanges.get(i).getStartTime(), timeRanges.get(i).getEndTime());
        }
        return overlapMinutes;
    }

    public static void main(String[] args) throws ParseException {
        long l = totalOverlapMinutes("2023-04-26 22:00:00", "2023-04-26 23:59:59");
        System.out.println(l);
    }
}

@Data
class TimeRange {
    private String startTime;
    private String endTime;

    public TimeRange(String startTime, String endTime) {
        this.startTime = startTime;
        this.endTime = endTime;
    }

    @Override
    public String toString() {
        return "{'startTime': '" + startTime + "', 'endTime': '" + endTime + "'}";
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值