package com.ylx.massage.utils;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.*;


@Slf4j
public final class DateTimeUtils {
    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    public static final String TIME = "HHmmss";
    public static final String DATE_TIME_NUMBER_FORMAT = "yyyyMMddHHmmss";
    public static final String DATE_FORMAT = "yyyy-MM-dd";
    public static final String DATE_FORMAT_FOREIGN = "dd/MM/yyyy";
    public static final String DATE_YEAR_MONT_DAY_FORMAT = "yyyy/MM/dd";
    public static final String DATE_NUMBER_FORMAT = "yyyyMMdd";
    public static final String DATE_NUMBER_YEARS_FORMAT = "yyyyMM";
    public static final String DATE_NUMBER_YEAR_MONTH_FORMAT = "yyyy年MM月dd日 HH:mm";

    public static final String DATE_NUMBER_YEAR_MONTH_FORMAT2 = "yyyy-MM";
    public static final String TIME_FORMAT = "yyyy-MM-dd 12:00:00";
    public static final long DAY_SECONDS = 24L * 60 * 60;
    public static final long DAY_MILLISECONDS = 24L * 60 * 60 * 1000;
    public static final String DATE_TIME_ZONE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";

    private DateTimeUtils() {
    }

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

    public static String formatDate(String pattern) {
        return new SimpleDateFormat(pattern).format(new Date());
    }

    public static String formatDate(Date date) {
        return formatDate(date, DATE_FORMAT);
    }

    public static String formatDatetime(Date date) {
        return formatDate(date, DATE_TIME_FORMAT);
    }

    public static String numTime(Date date) {
        return formatDate(date, TIME);
    }


    public static String formatDatetime() {
        return formatDate(DATE_TIME_FORMAT);
    }

    public static Date formatTime(Date date) {
        String formatDate = formatDate(date, TIME_FORMAT);
        return parseDate(formatDate, DATE_TIME_FORMAT);
    }

    /**
     * 解析日期
     *
     * @param date
     * @param pattern
     * @return
     */
    public static Date parseDate(String date, String pattern) {

        try {
            return new SimpleDateFormat(pattern).parse(date);
        } catch (Exception e) {
            log.error("解析日期错误：{}", e.getMessage());
            return null;
        }
    }

    /**
     * 解析日期时间
     *
     * @param date
     * @return
     */
    public static Date parseDatetime(String date) {
        return parseDate(date, DATE_TIME_FORMAT);
    }

    /**
     * 解析年月日期时间
     *
     * @param date
     * @return
     */
    public static Date parseDateday(String date) {
        return parseDate(date, DATE_FORMAT);

    }

    /**
     * 解析年月日期
     *
     * @param date
     * @return
     */
    public static Date parseDateMoth(String date) {
        return parseDate(date, DATE_NUMBER_YEAR_MONTH_FORMAT2);
    }

    /**
     * 解析年月日期时间
     *
     * @param date
     * @return
     */
    public static Date numberDateday(String date) {
        return parseDate(date, DATE_NUMBER_FORMAT);
    }


    /**
     * 获取当前时间戳
     *
     * @return
     */
    public static Timestamp currentTimestamp() {
        return new Timestamp(System.currentTimeMillis());
    }

    /**
     * 获取两个日期相差的天数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int dayDiff(Date date1, Date date2) {
        Long days = (date1.getTime() - date2.getTime()) / DAY_MILLISECONDS;
        return days.intValue();
    }

    /**
     * 计算两个日期相差天数，忽略时分秒
     * @param date1
     * @param date2
     * @return
     */
    public static int dayDiffIgnoreHms(Date date1, Date date2) {
        if(null == date1 || null == date2 ){
            return 0;
        }
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(date1);
        setTime2Start(calendar1);

        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(date2);
        setTime2Start(calendar2);

       return dayDiff(calendar1.getTime(),calendar2.getTime());
    }

    /**
     * 获取一个日期与当前时间相差的天数
     *
     * @param date
     * @return
     */
    public static int dayDiff(Date date) {
        Calendar calendar = Calendar.getInstance();
        setTime2Start(calendar);
        return dayDiff(date, calendar.getTime());
    }

    /**
     * 设置时间部分到开始时刻
     *
     * @param calendar
     * @return
     */
    public static void setTime2Start(Calendar calendar) {
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
    }

    /**
     * 设置时间部分到结束时刻
     *
     * @param calendar
     * @return
     */
    public static void setTime2End(Calendar calendar) {
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
    }

    /**
     * 当前年的开始时间
     *
     * @return
     */
    public static Date getFirstDayOfYear() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_YEAR, calendar.getActualMinimum(Calendar.DAY_OF_YEAR));
        setTime2Start(calendar);
        return calendar.getTime();
    }

    /**
     * 当前年的结束时间
     *
     * @return
     */
    public static Date getLastDayOfYear() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_YEAR, calendar.getActualMaximum(Calendar.DAY_OF_YEAR));
        setTime2End(calendar);
        return calendar.getTime();
    }

    /**
     * 当前月的开始时间
     *
     * @return
     */
    public static Date getFirstDayOfMonth() {
        return getFirstDayOfMonth(new Date());
    }

    public static Date getFirstDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
        setTime2Start(calendar);
        return calendar.getTime();
    }

    /***
     * 当前月的结束时间
     * @return
     */
    public static Date getLastDayOfMonth() {
        return getLastDayOfMonth(new Date());
    }

    public static Date getLastDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        setTime2End(calendar);
        return calendar.getTime();
    }

    /**
     * 获取某个日期所在月的天数
     *
     * @param date
     * @return
     */
    public static int getDaysOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int days = calendar.getActualMaximum(Calendar.DATE);
        return days;
    }

    /**
     * 两个时间相差的月份
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int monthDiff(Date date1, Date date2) {
        Long month = (date1.getTime() - date2.getTime()) / (DAY_MILLISECONDS * 365 / 12);
        return month.intValue();
    }

    /**
     * 获取某个日期的天数
     *
     * @param date
     * @return
     */
    public static int getDayOfDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取某个日期的月份
     *
     * @param date
     * @return
     */
    public static int getMonthOfDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH);
    }

    /**
     * 获取某个日期的月份，补充到两位
     *
     * @param date
     * @return
     */
    public static String getMonthOfDateToString(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        String Month = String.valueOf(calendar.get(Calendar.MONTH) + 1);
        return Month.length() > 1 ? Month : BigDecimal.ZERO.toString().concat(Month);
    }

    /**
     * 获取某个日期的年份
     *
     * @param date
     * @return
     */
    public static int getYearOfDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 日期加减
     *
     * @param date
     * @param field
     * @param amount
     * @return
     */
    public static Date add(Date date, int field, int amount) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(field, amount);
        return calendar.getTime();
    }

    /**
     * 获取某个日期当天的开始时间(00:00:00)
     *
     * @param date
     * @return
     */
    public static Date getStartDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        setTime2Start(calendar);
        return calendar.getTime();
    }

    /**
     * 获取某个日期当天的结束时间(23:59:59)
     *
     * @param date
     * @return
     */
    public static Date getEndDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        setTime2End(calendar);
        return calendar.getTime();
    }

    /**
     * 获取某个日期昨天的结束时间(23:59:59)
     *
     * @param date
     * @return
     */
    public static Date yesterdayEnddate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -1);
        setTime2End(calendar);
        return calendar.getTime();
    }

    /**
     * 日期天数加减
     *
     * @param date
     * @param amount
     * @return
     */
    public static Date addDays(Date date, int amount) {
        return add(date, Calendar.DAY_OF_MONTH, amount);
    }

    /**
     * 根据type获取开始时间
     *
     * @param endDate
     * @param type
     * @return
     */

    /**
     * 日期月份加减
     *
     * @param date
     * @param amount
     * @return
     */
    public static Date addMonths(Date date, int amount) {
        return add(date, Calendar.MONTH, amount);
    }

    public static Date addYears(Date date, int amount) {
        return add(date, Calendar.YEAR, amount);
    }
    /**
     * 加减小时
     *
     * @param date
     * @param amount
     * @return
     */
    public static Date addHours(Date date, int amount) {
        return add(date, Calendar.HOUR_OF_DAY, amount);
    }

    /**
     * 加减分钟
     *
     * @param date   指定日期
     * @param amount
     * @return Date 加减后的日期
     */
    public static Date addMinute(Date date, int amount) {
        return add(date, Calendar.MINUTE, amount);
    }


    /**
     * 获取昨天开始时间
     *
     * @return
     */
    public static Date yesterdayStart() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        setTime2Start(calendar);
        return calendar.getTime();
    }

    /**
     * 获取昨天结束时间
     *
     * @return
     */
    public static Date yesterdayEnd() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        setTime2End(calendar);
        return calendar.getTime();
    }

    /**
     * 获取今天开始时间
     *
     * @return
     */
    public static Date todayStart() {
        Calendar calendar = Calendar.getInstance();
        setTime2Start(calendar);
        return calendar.getTime();
    }

    /**
     * 获取今天结束时间
     *
     * @return
     */
    public static Date todayEnd() {
        Calendar calendar = Calendar.getInstance();
        setTime2End(calendar);
        return calendar.getTime();
    }

    /**
     * 时间戳转换为date类型
     *
     * @param timestamp
     * @return
     */
    public static Date getTimeOfDate(Long timestamp) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timestamp);
        return calendar.getTime();
    }



    /**
     * 获取某个日期当天的开始时间(00:00:00)
     *
     * @param timestamp
     * @return
     */
    public static Date getStartTimeOfDate(Long timestamp) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timestamp);
        setTime2Start(calendar);
        return calendar.getTime();
    }

    /**
     * 获取某个日期当天的结束时间(23:59:59)
     *
     * @param timestamp
     * @return
     */
    public static Date getEndTimeOfDate(Long timestamp) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timestamp);
        setTime2End(calendar);
        return calendar.getTime();
    }

    /**
     * 获取某个日期当天的开始时间(00:00:00)
     *
     * @param startDate
     * @return
     */
    public static Date getStartTimeOfDate(String startDate) {
        Date date = parseDate(startDate, DATE_FORMAT);
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(date.getTime());
        setTime2Start(calendar);
        return calendar.getTime();
    }

    /**
     * 获取某个日期当天的结束时间(23:59:59)
     *
     * @param endDate
     * @return
     */
    public static Date getEndTimeOfDate(String endDate) {
        Date date = parseDate(endDate, DATE_FORMAT);
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(date.getTime());
        setTime2End(calendar);
        return calendar.getTime();
    }

    /**
     * 获取某个日期的本周的开始时间
     *
     * @param date 某个日期
     * @return 开始时间
     */
    public static Date getBeginDayOfWeek(Date date) {
        Calendar cal = Calendar.getInstance();
        if (null != date) {
            cal.setTime(date);
        }
        int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayofweek == 1) {
            dayofweek += 7;
        }
        cal.add(Calendar.DATE, 2 - dayofweek);
        return getStartTimeOfDate(cal.getTime().getTime());
    }

    /**
     * 获取某个日期的本周的结束时间
     *
     * @param date 某个日期
     * @return 结束时间
     */
    public static Date getEndDayOfWeek(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginDayOfWeek(date));
        cal.add(Calendar.DAY_OF_WEEK, 6);
        return getEndTimeOfDate(cal.getTime().getTime());
    }

    /**
     * 获取某个日期的本月的开始时间
     *
     * @param date 某个日期
     * @return 开始时间
     */
    public static Date getBeginDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getYearOfDate(date), getMonthOfDate(date), 1);
        return getStartTimeOfDate(calendar.getTime().getTime());
    }

    /**
     * 获取某个日期的本月的结束时间
     *
     * @param date 某个日期
     * @return 结束时间
     */
    public static Date getEndDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getYearOfDate(date), getMonthOfDate(date), 1);
        int day = calendar.getActualMaximum(Calendar.DATE);
        calendar.set(getYearOfDate(date), getMonthOfDate(date), day);
        return getEndTimeOfDate(calendar.getTime().getTime());
    }

    /**
     * 获取某个日期的本年的开始时间
     *
     * @param date 某个日期
     * @return 开始时间
     */
    public static Date getBeginDayOfYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, getYearOfDate(date));
        cal.set(Calendar.MONTH, Calendar.JANUARY);
        cal.set(Calendar.DATE, 1);
        return getStartTimeOfDate(cal.getTime().getTime());
    }

    /**
     * 获取某个日期的本年的结束时间
     *
     * @param date 某个日期
     * @return 结束时间
     */
    public static Date getEndDayOfYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, getYearOfDate(date));
        cal.set(Calendar.MONTH, Calendar.DECEMBER);
        cal.set(Calendar.DATE, 31);
        return getEndTimeOfDate(cal.getTime().getTime());
    }

    /**
     * 时间Date类型转Long时间戳
     *
     * @param date
     * @return
     */
    public static Long dateToStamp(Date date) {
        long time = 0L;
        try {
            String sDate = formatDatetime(date);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_TIME_FORMAT);
            Date parse = simpleDateFormat.parse(sDate);
            time = parse.getTime();
        } catch (Exception e) {
            log.error("时间Date转时间戳错误:{}", e);
        }
        return time;
    }

    /**
     * 时间DateString类型转Long时间戳
     *
     * @param date
     * @return
     */
    public static Long dateStringToStamp(String date) {
        long time = 0L;
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_TIME_FORMAT);
            Date parse = simpleDateFormat.parse(date);
            time = parse.getTime();
        } catch (Exception e) {
            log.error("时间DateString转时间戳错误:{}", e);
        }
        return time;
    }

    /**
     * 秒级时间戳转Date
     *
     * @param stamp
     * @param pattern
     * @return
     */
    public static String stampToDate(Long stamp, String pattern) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        return simpleDateFormat.format(new Date(stamp));
    }

    /**
     * 获取年份加减时间
     *
     * @param years
     * @return
     */
    public static Date getYearAdd(Integer years) {
        Date date = new Date();//获取当前时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, years);//当前时间减去一年，即一年前的时间
        return calendar.getTime();//获取一年前的时间，或者一个月前的时间
    }

    public static Date getBeginDate(int year, int month) {
        YearMonth yearMonth = YearMonth.of(year, month);
        LocalDate localDate = yearMonth.atDay(1);
        LocalDateTime startOfDay = localDate.atStartOfDay();
        ZonedDateTime zonedDateTime = startOfDay.atZone(ZoneId.of("Asia/Shanghai"));
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * 根据传入时间、时间单位获取该单位起始时间
     *
     * @param dateTime 时间
     * @param dateUnitType 时间单位：0-日-默认昨天  1-周-本周  2-月-本月 3-年-本年
     */



    /**
     * 判断某个时间是否在[startTime, endTime]区间，注意时间格式要一致
     *
     * @param dateTime 比较时间
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return
     * @author jqlin
     */
    public static boolean isEffectiveDate(Date dateTime, Date startTime, Date endTime) {
        if ((dateTime.getTime() == startTime.getTime())
                || (dateTime.getTime() == endTime.getTime())) {
            return true;
        }

        Calendar date = Calendar.getInstance();
        date.setTime(dateTime);

        Calendar begin = Calendar.getInstance();
        begin.setTime(startTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        if (date.after(begin) && date.before(end)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 日期类型转字符串类型
     * @param date
     * @param pattern
     * @return
     */

    /**
     * 数字转换成日期的开始时间
     *
     * @param year，month，day
     * @return
     */
    public static Date getStartTimeOfDate(int year,int month, int day) {
        String date = year+"-"+month+"-"+day;
        return getStartTimeOfDate(date);
    }

    /**
     * 设置查询区间，最大查询3个月数据，超过3个月区间抛异常
     * @param startDate,
     * @param endDate
     * @param months ,需要查询的区间月份,传正数，超过最大区间抛异常信息
     * @return
     */

    /**
     * 设置查询区间，最大查询一周数据，超过一周区间抛异常
     *
     * @param startDate,
     * @param endDate
     * @param weeks      需要查询的区间:周,传正数，超过最大区间抛异常信息
     * @return
     */

    /**
     * 获取两个日期之间所有日期
     *
     * @param startDayDate
     * @param endDayDate
     * @return
     */

    /**
     * 获取两个日期之间所有日期
     *
     * @param startDayLong
     * @param endDayLong
     * @return
     */

    /**
     * 计算两个日期之间包含的所有月份
     *
     * @param beginTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    public static List<String> findMonthsStr(String beginTime, String endTime) throws ParseException {
        List<String> monthsStrList = new ArrayList<>();
        //格式化为年月
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");

        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();

        min.setTime(sdf.parse(beginTime));
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

        max.setTime(sdf.parse(endTime));
        max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

        while (min.before(max)) {
            monthsStrList.add(sdf.format(min.getTime()));
            min.add(Calendar.MONTH, 1);
        }
        return monthsStrList;
    }

    /**
     * 计算两个日期之间包含的所有年份
     *
     * @param beginTime
     * @param endTime
     * @return
     */
    public static List<String> findYearsStr(String beginTime, String endTime) {
        List<String> yearsStrList = new ArrayList<>();
        beginTime = beginTime.substring(0, 4);
        endTime = endTime.substring(0, 4);
        if (beginTime.equals(endTime)) {
            yearsStrList.add(beginTime);
        } else {
            yearsStrList.add(beginTime);
            for (int i = 1; i <= Integer.parseInt(endTime) - Integer.parseInt(beginTime); i++) {
                yearsStrList.add(String.valueOf(Integer.parseInt(beginTime) + i));
            }
        }
        return yearsStrList;
    }

    /**
     * 格式化Excel时间
     * @param day
     * @return yyyy-MM-dd
     */
    public static String formatExcelDate(int day) {
        Calendar calendar = new GregorianCalendar(1899,11,30);
        Date gregorianDate = calendar.getTime();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return simpleDateFormat.format(addDays(gregorianDate, day));
    }

    /**
     * 转换Excel时间
     * @param day
     * @retur date
     */
    public static Date ExcelDate(int day) {
        Calendar calendar = new GregorianCalendar(1899,11,30);
        Date gregorianDate = calendar.getTime();
        Date date = addDays(gregorianDate, day);

        return date;
    }

    /**
     * 获取时间戳
     * @param date
     * @return
     */
    public static Long getTimeStamp(Date date){
        return date != null ? date.getTime() : 0L;
    }


    public static void main(String[] args) throws InterruptedException {
        while (true){
            Thread.sleep(100);
            stampToDate1();
        }
    }

    public static void  stampToDate1() {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());

        // 设置未来日期的时间，例如2023年12月31日 23:59:59
        LocalDateTime futureDate = LocalDateTime.of(2025, 3, 26, 19, 0, 00);

        // 计算两个时间点之间的差值（以毫秒为单位）
        long durationInMillis = Duration.between(now, futureDate).toMillis();

        // 将毫秒差值转换为秒
        long durationInSeconds = durationInMillis / 1000;

        System.err.println(new Date() + "There is still a future date " + durationInMillis + " second");
    }



}
