package com.jsowell.common.util;

import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 时间工具类
 *
 * @author jsowell
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
    static Logger log = LoggerFactory.getLogger(DateUtils.class);

    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

    public static String YYYY_MM_DD = "yyyy-MM-dd";

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String YYYYMMDDHHMM = "yyyyMMddHHmm";

    public static String YYMMDDHHMMSS = "yyMMddHHmmss";

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    public static String RFC3339 = "yyyy-MM-dd'T'HH:mm:ssXXX";

    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    /**
     * 获取当前Date型日期
     *
     * @return Date() 当前日期
     */
    public static Date getNowDate() {
        return new Date();
    }

    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     *
     * @return String
     */
    public static String getDate() {
        return dateTimeNow(YYYY_MM_DD);
    }

    public static String getTime() {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }

    public static String dateTimeNow() {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }

    public static String dateTimeNow(final String format) {
        return parseDateToStr(format, new Date());
    }

    public static String dateTime(final Date date) {
        return parseDateToStr(YYYY_MM_DD, date);
    }

    public static String parseDateToStr(final String format, final Date date) {
        return new SimpleDateFormat(format).format(date);
    }


    public static String timeStampToRfc3339(long timeStamp) {
        Date date = new Date(timeStamp);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(RFC3339);
        String formatDate = simpleDateFormat.format(date);
        return formatDate;
    }

    public static LocalDateTime toLocalDateTime(String str, String format) {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        if (StringUtils.isBlank(format)) {
            format = YYYY_MM_DD_HH_MM_SS;
        }
        DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
        return LocalDateTime.parse(str, df);
    }

    public static Date dateTime(final String format, final String ts) {
        try {
            return new SimpleDateFormat(format).parse(ts);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static String datePath() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static String dateTime() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }

    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str) {
        if (str == null) {
            return null;
        }
        try {
            return parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    public static void main(String[] args) throws ParseException {
        // String str = "2023-01-07 11:17:12";
        // Date date = parseDate(str);
        // String str1 = parseDateToStr(YYYY_MM_DD_HH_MM_SS, date);
        // System.out.println(str1);
        //
        //
        // Date date1 = addMinute(new Date(), -15);
        // String s = parseDateToStr(YYYY_MM_DD_HH_MM_SS, date1);
        // System.out.println(s);
        //
        // String time = getDate();
        // System.out.println(time);
        //
        // System.out.println(dateTimeNow("yyyy-MM-dd HH:mm"));

        // String s2 = formatDateTime(new Date());
        // System.out.println(s2);

        String time = DateUtils.getTime();
        System.out.println(time);

        System.out.println(DateUtils.getDate());
        // String s = date2HexStr(new Date());
        // String s = BytesUtil.binary(bytes, 16);
        // System.out.println(s);

        String hexString = "9401270a1b0217";
        byte[] bytes1 = BytesUtil.hexStringToByteArray(hexString);
        // String s1 = toDateString(bytes1);
        // Date date = CP56Time2aToDate(bytes1);
        // System.out.println(s1);

        // String encodeCP56Time2a = DateUtils.encodeCP56Time2a(new Date());
        // byte[] bytes = BytesUtil.hexString2Bytes(encodeCP56Time2a);
        // String s4 = CP56Time2aToDateStr(bytes);
        // // byte[] msg = BytesUtil.str2Bcd("88000000000021" + encodeCP56Time2a);
        // // Date date1 = toDate(bytes);
        // // String s3 = formatDateTime(date1);
        // // System.out.println(s3);
        // System.out.println(s4);
        long chargingTime = DateUtils.intervalTime("2023-02-24 16:00:00", "2023-02-24 17:03:06");
        System.out.println(chargingTime);


        String dateToStr = DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS, new Date());
        System.out.println(dateToStr);

        String poorDays = getPoorDays(addDay(new Date(), -7), new Date());
        System.out.println(poorDays);
    }

    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate() {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 计算相差天数（不会显示负值）
     */
    public static int differentDaysByMillisecond(Date beginDate, Date endDate) {
        return Math.abs((int) ((endDate.getTime() - beginDate.getTime()) / (1000 * 3600 * 24)));
    }

    /**
     * 计算相差天数 (会显示负值)
     *
     * @param endDate
     * @param nowDate
     * @return
     */
    public static String getPoorDays(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long diff = endDate.getTime() - nowDate.getTime();
        long day = diff / nd;
        StringBuilder sb = new StringBuilder();
        if (day != 0) {
            sb.append(day);
        }
        return sb.toString();
    }

    /**
     * 计算两个时间差
     */
    public static String getDatePoor(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        long sec = diff % nd % nh % nm / ns;

        StringBuilder sb = new StringBuilder();
        if (day != 0) {
            sb.append(day).append("天");
        }
        if (hour != 0) {
            sb.append(hour).append("小时");
        }
        if (min != 0) {
            sb.append(min).append("分");
        }
        if (sec != 0) {
            sb.append(sec).append("秒");
        }
        return sb.toString();
    }

    /**
     * LocalDateTime转Date
     *
     * @param localDateTime
     * @return
     */
    public static Date localDateTime2Date(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return null;
        }
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        return Date.from(instant);
    }

    public static Date localDate2Date(LocalDate localDate) {
        if (localDate == null) {
            return null;
        }
        LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.of(0, 0, 0));
        return localDateTime2Date(localDateTime);
    }

    /**
     * Date转LocalDateTime
     */
    public static LocalDateTime date2LocalDateTime(Date date) {
        if (date == null) {
            return null;
        }
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * 获取云快充协议所需时间段
     * 0： 00～0： 30 时段费率号
     * 0： 30～1： 00 时段费率号
     * ……
     * 23： 00～23： 30 时段费率号
     * 23： 30～0： 00 时段费率号
     */
    public static List<String> getPeriodOfTime() {
        int intervalMinutes = 30;
        // 结果集
        List<String> resultList = Lists.newArrayList();
        LocalTime startTime = LocalTime.of(0, 0);

        LocalTime tempStartDateTime = startTime;
        LocalTime tempEndDateTime = null;
        while (true) {
            // 获取加intervalMinutes分钟后的时间
            tempEndDateTime = tempStartDateTime.plusMinutes(intervalMinutes);
            resultList.add(tempStartDateTime.format(DateTimeFormatter.ofPattern("HH:mm:ss")) +
                    "-" + tempEndDateTime.format(DateTimeFormatter.ofPattern("HH:mm:ss")));
            // 下次的开始时间，为上次的结束时间
            tempStartDateTime = tempEndDateTime;
            // 当tempStartDateTime等于startTime时，停止
            if (tempStartDateTime.compareTo(startTime) == 0) {
                break;
            }
        }
        // 特殊处理
        resultList = resultList.subList(0, resultList.size() - 1);
        // 每天的最后半小时
        resultList.add("23:30:00-23:59:59");
        return resultList;
    }

    /**
     * 时分秒转LocalTime
     * 可以是 10:10:23 或者 10:10
     *
     * @param time
     * @return
     */
    public static LocalTime getLocalTime(String time) {
        if (StringUtils.equals("24:00", time)) {
            // System.out.println("time为24:00, 转换为23:59");
            time = "23:59";
        }
        List<String> list = Lists.newArrayList(time.split(":"));
        if (CollectionUtils.isNotEmpty(list)) {
            if (list.size() == 2) {
                return LocalTime.of(Integer.parseInt(list.get(0)), Integer.parseInt(list.get(1)));
            } else if (list.size() == 3) {
                return LocalTime.of(Integer.parseInt(list.get(0)), Integer.parseInt(list.get(1)), Integer.parseInt(list.get(2)));
            }
        }
        return null;
    }

    public enum IntervalType {
        DAY,
        HOUR,
        MINUTE,
        SECOND,
        ;
    }

    /**
     * 时间切割
     *
     * @param startTime    被切割的开始时间
     * @param endTime      被切割的结束时间
     * @param intervalType
     * @param interval     >0
     * @return
     */
    public static List<DateSplit> splitDate(Date startTime, Date endTime, IntervalType intervalType, int interval) {
        if (interval < 0) {
            return null;
        }
        if (endTime.getTime() <= startTime.getTime()) {
            return null;
        }

        if (intervalType == IntervalType.DAY) {
            return splitByDay(startTime, endTime, interval);
        }
        if (intervalType == IntervalType.HOUR) {
            return splitByHour(startTime, endTime, interval);
        }
        if (intervalType == IntervalType.MINUTE) {
            return splitByMinute(startTime, endTime, interval);
        }
        if (intervalType == IntervalType.SECOND) {
            return splitBySecond(startTime, endTime, interval);
        }
        return null;
    }

    /**
     * 按照小时切割时间区间
     */
    public static List<DateSplit> splitByHour(Date startTime, Date endTime, int intervalHours) {
        if (endTime.getTime() <= startTime.getTime()) {
            return null;
        }

        List<DateSplit> dateSplits = new ArrayList<>(256);

        DateSplit param = new DateSplit();
        param.setStartDateTime(startTime);
        param.setEndDateTime(endTime);
        param.setEndDateTime(addHour(startTime, intervalHours));
        while (true) {
            param.setStartDateTime(startTime);
            Date tempEndTime = addHour(startTime, intervalHours);
            if (tempEndTime.getTime() >= endTime.getTime()) {
                tempEndTime = endTime;
            }
            param.setEndDateTime(tempEndTime);

            dateSplits.add(new DateSplit(param.getStartDateTime(), param.getEndDateTime()));

            startTime = addHour(startTime, intervalHours);
            if (startTime.getTime() >= endTime.getTime()) {
                break;
            }
            if (param.getEndDateTime().getTime() >= endTime.getTime()) {
                break;
            }
        }
        return dateSplits;
    }

    /**
     * 按照秒切割时间区间
     * getRealTimeDetectionData
     */
    public static List<DateSplit> splitBySecond(Date startTime, Date endTime, int intervalSeconds) {
        if (endTime.getTime() <= startTime.getTime()) {
            return null;
        }
        List<DateSplit> dateSplits = new ArrayList<>(256);

        DateSplit param = new DateSplit();
        param.setStartDateTime(startTime);
        param.setEndDateTime(endTime);
        param.setEndDateTime(addSecond(startTime, intervalSeconds));
        while (true) {
            param.setStartDateTime(startTime);
            Date tempEndTime = addSecond(startTime, intervalSeconds);
            if (tempEndTime.getTime() >= endTime.getTime()) {
                tempEndTime = endTime;
            }
            param.setEndDateTime(tempEndTime);

            dateSplits.add(new DateSplit(param.getStartDateTime(), param.getEndDateTime()));

            startTime = addSecond(startTime, intervalSeconds);
            if (startTime.getTime() >= endTime.getTime()) {
                break;
            }
            if (param.getEndDateTime().getTime() >= endTime.getTime()) {
                break;
            }
        }
        return dateSplits;
    }

    /**
     * 按照天切割时间区间
     */
    public static List<DateSplit> splitByDay(Date startTime, Date endTime, int intervalDays) {
        if (endTime.getTime() <= startTime.getTime()) {
            return null;
        }
        List<DateSplit> dateSplits = new ArrayList<>(256);

        DateSplit param = new DateSplit();
        param.setStartDateTime(startTime);
        param.setEndDateTime(endTime);
        param.setEndDateTime(addDay(startTime, intervalDays));
        while (true) {
            param.setStartDateTime(startTime);
            Date tempEndTime = addDay(startTime, intervalDays);
            if (tempEndTime.getTime() >= endTime.getTime()) {
                tempEndTime = endTime;
            }
            param.setEndDateTime(tempEndTime);

            dateSplits.add(new DateSplit(param.getStartDateTime(), param.getEndDateTime()));

            startTime = addDay(startTime, intervalDays);
            if (startTime.getTime() >= endTime.getTime()) {
                break;
            }
            if (param.getEndDateTime().getTime() >= endTime.getTime()) {
                break;
            }
        }
        return dateSplits;
    }


    /**
     * 按照分钟切割时间区间
     *
     * @param startTime
     * @param endTime
     * @param intervalMinutes
     * @return
     */
    public static List<DateSplit> splitByMinute(Date startTime, Date endTime, int intervalMinutes) {
        if (endTime.getTime() <= startTime.getTime()) {
            return null;
        }
        List<DateSplit> dateSplits = new ArrayList<>(256);

        DateSplit param = new DateSplit();
        param.setStartDateTime(startTime);
        param.setEndDateTime(endTime);
        param.setEndDateTime(addMinute(startTime, intervalMinutes));
        while (true) {
            param.setStartDateTime(startTime);
            Date tempEndTime = addMinute(startTime, intervalMinutes);
            if (tempEndTime.getTime() >= endTime.getTime()) {
                tempEndTime = endTime;
            }
            param.setEndDateTime(tempEndTime);

            dateSplits.add(new DateSplit(param.getStartDateTime(), param.getEndDateTime()));

            startTime = addMinute(startTime, intervalMinutes);
            if (startTime.getTime() >= endTime.getTime()) {
                break;
            }
            if (param.getEndDateTime().getTime() >= endTime.getTime()) {
                break;
            }
        }
        return dateSplits;
    }

    private static Date addDay(Date date, int days) {
        return add(date, Calendar.DAY_OF_MONTH, days);
    }

    private static Date addHour(Date date, int hours) {
        return add(date, Calendar.HOUR_OF_DAY, hours);
    }

    public static Date addMinute(Date date, int minute) {
        return add(date, Calendar.MINUTE, minute);
    }

    private static Date addSecond(Date date, int second) {
        return add(date, Calendar.SECOND, second);
    }

    private static Date add(final Date date, final int calendarField, final int amount) {
        final Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }

    public static String formatDateTime(Date date) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
        return simpleDateFormat.format(date);
    }

    public static String formatDateTime(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return "";
        }
        Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        return formatDateTime(date);
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class DateSplit {
        private Date startDateTime;
        private Date endDateTime;

        public String getStartDateTimeStr() {
            return formatDateTime(startDateTime);
        }

        public String getEndDateTimeStr() {
            return formatDateTime(endDateTime);
        }
    }

    /**
     * CP56Time2a 转 日期字符串
     * 0x3b交易记录 会使用这个方法，解析开始时间 结束时间 交易时间
     * @param bytes
     * @return
     */
    // public static String CP56Time2aToDateStr(byte[] bytes) {
    //     Date date = CP56Time2aToDate(bytes);
    //     if (date == null) {
    //         return null;
    //     }
    //     return DateUtils.formatDateTime(date);
    // }
    // public static String toDateString(byte[] bytes) {
    //     return Cp56Time2aUtil.toDateString(bytes);
    // }

    /**
     * cp56time2a 格式转date格式
     */
    // public static Date CP56Time2aToDate(byte[] bytes) {
    //     if (bytes == null || bytes.length != 7) {
    //         return null;
    //     }
    //     int ms = BytesUtil.bytesToIntLittle(BytesUtil.copyBytes(bytes, 0, 2));
    //     int min = BytesUtil.bytesToIntLittle(BytesUtil.copyBytes(bytes, 2, 1));
    //     int hour = BytesUtil.bytesToIntLittle(BytesUtil.copyBytes(bytes, 3, 1));
    //     int day = BytesUtil.bytesToIntLittle(BytesUtil.copyBytes(bytes, 4, 1));
    //     int month = BytesUtil.bytesToIntLittle(BytesUtil.copyBytes(bytes, 5, 1));
    //     int year = BytesUtil.bytesToIntLittle(BytesUtil.copyBytes(bytes, 6, 1));
    //     if (month == 0 || day == 0 || year == 0) {
    //         return null;
    //     }
    //     LocalDateTime localDateTime = LocalDateTime.of(year + 2000, month, day, hour, min, ms / 1000);
    //     Date date = DateUtils.localDateTime2Date(localDateTime);
    //     return date;
    // }

    // public static Date CP56Time2aToDate(byte[] bytes) {
    //     return Cp56Time2aUtil.toDate(bytes);
    // }

    /**
     * 时间转16进制字符串
     * Date转成CP56Time2a
     * 发送对时请求，会用到这个方法
     */
    // public static String encodeCP56Time2a(Date date) {
    //     // Calendar calendar = Calendar.getInstance();
    //     // calendar.setTime(date);
    //     // StringBuilder builder = new StringBuilder();
    //     // String milliSecond = String.format("%04X", (calendar.get(Calendar.SECOND) * 1000) + calendar.get(Calendar.MILLISECOND));
    //     // builder.append(milliSecond.substring(2, 4));
    //     // builder.append(milliSecond.substring(0, 2));
    //     // builder.append(String.format("%02X", calendar.get(Calendar.MINUTE) & 0x3F));
    //     // builder.append(String.format("%02X", calendar.get(Calendar.HOUR_OF_DAY) & 0x1F));
    //     // int week = calendar.get(Calendar.DAY_OF_WEEK);
    //     // if (week == Calendar.SUNDAY)
    //     //     week = 7;
    //     // else week--;
    //     // builder.append(String.format("%02X", (week << 5) + (calendar.get(Calendar.DAY_OF_MONTH) & 0x1F)));
    //     // builder.append(String.format("%02X", calendar.get(Calendar.MONTH) + 1));
    //     // builder.append(String.format("%02X", calendar.get(Calendar.YEAR) - 2000));
    //     // return builder.toString();
    //
    //     byte[] result = new byte[7];
    //     final Calendar aTime = Calendar.getInstance();
    //     aTime.setTime(date);
    //     final int milliseconds = aTime.get(Calendar.MILLISECOND);
    //     result[0] = (byte) (milliseconds % 256);
    //     result[1] = (byte) (milliseconds / 256);
    //     result[2] = (byte) aTime.get(Calendar.MINUTE);
    //     result[3] = (byte) aTime.get(Calendar.HOUR_OF_DAY);
    //     result[4] = (byte) aTime.get(Calendar.DAY_OF_MONTH);
    //     result[5] = (byte) (aTime.get(Calendar.MONTH) + 1);
    //     result[6] = (byte) (aTime.get(Calendar.YEAR) % 100);
    //     System.out.println("Year->" + aTime.get(Calendar.YEAR));
    //     return BytesUtil.binary(result, 16);
    // }
    // public static String date2HexStr(Date date) {
    //     return Cp56Time2aUtil.date2HexStr(date);
    // }


    /**
     * 获取两个时间的间隔时间
     *
     * @return 间隔时间 单位：分钟
     */
    public static long intervalTime(String begin, String end) {
        return intervalTime(parseDate(begin), parseDate(end));
    }

    /**
     * 获取两个时间的间隔时间
     *
     * @return 间隔时间 单位：分钟
     */
    public static long intervalTime(Date begin, Date end) {
        return intervalTime(date2LocalDateTime(begin), date2LocalDateTime(end));
    }

    /**
     * 获取两个时间的间隔时间
     *
     * @return 间隔时间 单位：分钟
     */
    public static long intervalTime(LocalDateTime begin, LocalDateTime end) {
        return ChronoUnit.MINUTES.between(begin, end);
    }

    /**
     * 判断2个时间段是否有重叠（交集）
     *
     * @param startDate1 时间段1开始时间戳
     * @param endDate1   时间段1结束时间戳
     * @param startDate2 时间段2开始时间戳
     * @param endDate2   时间段2结束时间戳
     * @param isStrict   是否严格重叠，true 严格，没有任何相交或相等；false 不严格，可以首尾相等，比如2021/5/29-2021/5/31和2021/5/31-2021/6/1，不重叠。
     * @return 返回是否重叠
     */
    public static boolean isOverlap(long startDate1, long endDate1, long startDate2, long endDate2, boolean isStrict) {
        if (isStrict) {
            if (!(endDate1 < startDate2 || startDate1 > endDate2)) {
                return true;
            }
        } else {
            if (!(endDate1 <= startDate2 || startDate1 >= endDate2)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @param time1 17:02:00 - 17:02:00
     * @param time2 00:00-06:30
     * @return
     */
    public static boolean checkTime(String time1, String time2) {
        String[] split = time1.split("-");
        LocalTime startTime1 = DateUtils.getLocalTime(split[0]);
        LocalTime endTime1 = DateUtils.getLocalTime(split[1]);
        String[] split2 = time2.split("-");
        LocalTime startTime2 = DateUtils.getLocalTime(split2[0]);
        LocalTime endTime2 = DateUtils.getLocalTime(split2[1]);
        return DateUtils.isOverlap(startTime1, endTime1, startTime2, endTime2, false);
    }

    /**
     * 判断时间段是否重叠
     *
     * @param startDate1
     * @param endDate1
     * @param startDate2
     * @param endDate2
     * @param isStrict
     * @return
     */
    public static boolean isOverlap(LocalTime startDate1, LocalTime endDate1, LocalTime startDate2, LocalTime endDate2, boolean isStrict) {
        if (startDate1 == null || endDate1 == null || startDate2 == null || endDate2 == null) {
            log.warn("判断时间段是否重叠缺少参数，返回false");
            return false;
        }
        boolean result = false;
        if (isStrict) {
            if (!(endDate1.isBefore(startDate2) || startDate1.isAfter(endDate2))) {
                result = true;
            }
        } else {
            if (!((endDate1.isBefore(startDate2) || endDate1.equals(startDate2)) || (startDate1.isAfter(endDate2) || startDate1.equals(endDate2)))) {
                result = true;
            }
        }
        // log.info("时间段1={}, 时间段2={}, 结果:{}", startDate1 + "-" + endDate1, startDate2 + "-" + endDate2, result);
        return result;
    }

    /**
     * 判断2个时间段是否有重叠（交集）
     *
     * @param startDate1 时间段1开始时间
     * @param endDate1   时间段1结束时间
     * @param startDate2 时间段2开始时间
     * @param endDate2   时间段2结束时间
     * @param isStrict   是否严格重叠，true 严格，没有任何相交或相等；false 不严格，可以首尾相等，比如2021-05-29到2021-05-31和2021-05-31到2021-06-01，不重叠。
     * @return 返回是否重叠
     */
    public static boolean isOverlap(Date startDate1, Date endDate1, Date startDate2, Date endDate2, boolean isStrict) {
        Objects.requireNonNull(startDate1, "startDate1");
        Objects.requireNonNull(endDate1, "endDate1");
        Objects.requireNonNull(startDate2, "startDate2");
        Objects.requireNonNull(endDate2, "endDate2");
        return isOverlap(startDate1.getTime(), endDate1.getTime(), startDate2.getTime(), endDate2.getTime(), isStrict);
    }

    /**
     * 秒 转 天时分秒
     * 时分秒HoursMinutesSeconds
     *
     * @param mss 秒数
     * @return xx天xx小时xx分钟xx秒
     */
    public static String formatHoursMinutesSeconds(long mss) {
        String DateTimes = null;
        long days = mss / (60 * 60 * 24);
        long hours = (mss % (60 * 60 * 24)) / (60 * 60);
        long minutes = (mss % (60 * 60)) / 60;
        long seconds = mss % 60;
        if (days > 0) {
            DateTimes = days + "天" + hours + "小时" + minutes + "分钟"
                    + seconds + "秒";
        } else if (hours > 0) {
            DateTimes = hours + "小时" + minutes + "分钟"
                    + seconds + "秒";
        } else if (minutes > 0) {
            DateTimes = minutes + "分钟"
                    + seconds + "秒";
        } else {
            DateTimes = seconds + "秒";
        }

        return DateTimes;
    }

    /**
     * 当前时间是否在时间指定范围内<br>
     *
     * @param time      被检查的时间
     * @param beginTime 起始时间
     * @param endTime   结束时间
     * @return 是否在范围内
     * @since 3.0.8
     */
    public static boolean isIn(LocalTime time, LocalTime beginTime, LocalTime endTime) {
        // 判断是否在范围内 包含开始结束时间
        if (time.compareTo(beginTime) == 0 || time.compareTo(endTime) == 0) {
            return true;
        }
        if (beginTime.isBefore(time) && endTime.isAfter(time)) {
            return true;
        }
        return false;
    }
}
