package com.face.util;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 日期获取工具类
 */

public class DateUtils {

    public final static String DEFAULT_TIMEZONE = "GMT+8";

    public final static String ISO_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS";

    public final static String ISO_SHORT_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";

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

    public final static String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";

    public final static String DEFAULT_ONLY_TIME_FORMAT = "HH:mm:ss";

    public final static String SHORT_TIME_FORMAT = "yyyy-MM-dd HH:mm";

    public final static String FULL_SEQ_FORMAT = "yyyyMMddHHmmssSSS";

    public final static String FULL_FORMAT = "yyyyMMddHHmmssSSS";

    public final static String[] MULTI_FORMAT = {DEFAULT_DATE_FORMAT, DEFAULT_TIME_FORMAT, ISO_DATE_TIME_FORMAT, ISO_SHORT_DATE_TIME_FORMAT,
            SHORT_TIME_FORMAT, "yyyy-MM"};

    public final static String FORMAT_YYYY = "yyyy";

    public final static String FORMAT_YYYYMM = "yyyyMM";

    public final static String FORMAT_YYYYMMDD = "yyyyMMdd";

    public final static String FORMAT_YYYYMMDDHH = "yyyyMMddHH";

    public final static String FORMAT_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public final static String FORMAT_CORN = "ss mm HH dd MM ? yyyy";

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

    public final static String[] MULTI_FORMAT_ALL = {DEFAULT_TIME_FORMAT, ZONE_TIME_FORMAT, FULL_FORMAT, DEFAULT_DATE_FORMAT, ISO_DATE_TIME_FORMAT, ISO_SHORT_DATE_TIME_FORMAT,
            SHORT_TIME_FORMAT};

    /**
     * 日期转字符串
     * 默认格式: {@linkplain DateUtils#DEFAULT_DATE_FORMAT}
     *
     * @param date 日期对象
     * @return 返回格式化字符串
     */
    public static String formatDate(Date date) {
        if (date == null) {
            return "";
        }
        return new SimpleDateFormat(DEFAULT_DATE_FORMAT).format(date);
    }

    /**
     * 将日期时间对象转化为日期数字
     *
     * @param date   日期字符串 {@linkplain DateUtils#SHORT_TIME_FORMAT}
     * @param format 格式字符串
     * @return 返回日期数字
     */
    public static String formatDate(Date date, String format) {
        if (date == null) {
            return null;
        }
        return new SimpleDateFormat(format).format(date);
    }

    /**
     * 将日期时间对象转化为corn表达式
     *
     * @param date 时间点
     * @return convert Date to cron ,eg.  "0 06 10 15 10 ? 2018"
     */
    public static String formatDateToCorn(Date date) {
        if (date == null) {
            return null;
        }
        return new SimpleDateFormat(FORMAT_CORN).format(date);
    }

    /**
     * 将日期时间对象转化为日期数字
     *
     * @param date   日期字符串 {@linkplain DateUtils#SHORT_TIME_FORMAT}
     * @param format 格式字符串
     * @return 返回日期数字
     */
    public static Integer formatDateToInt(Date date, String format) {
        if (date == null) {
            return null;
        }
        return Integer.valueOf(new SimpleDateFormat(format).format(date));
    }

    /**
     * 将日期时间对象转化为日期数字
     *
     * @param date   日期字符串 {@linkplain DateUtils#SHORT_TIME_FORMAT}
     * @param format 格式字符串
     * @return 返回日期数字
     */
    public static Long formatDateToLong(Date date, String format) {
        if (date == null) {
            return null;
        }
        return Long.valueOf(new SimpleDateFormat(format).format(date));
    }

    /**
     * 将日期时间对象转化为日期字符串
     *
     * @param date 日期字符串 {@linkplain DateUtils#DEFAULT_TIME_FORMAT}
     * @return 返回日期字符串
     */
    public static String formatTime(Date date) {
        if (date == null) {
            return null;
        }
        return new SimpleDateFormat(DEFAULT_TIME_FORMAT).format(date);
    }

    /**
     * 将日期时间对象转化为日期字符串
     *
     * @param date 日期字符串 {@linkplain DateUtils#SHORT_TIME_FORMAT}
     * @return 返回日期字符串
     */
    public static String formatShortTime(Date date) {
        if (date == null) {
            return null;
        }
        return new SimpleDateFormat(SHORT_TIME_FORMAT).format(date);
    }

    /**
     * 将日期时间字符串转化为日期对象
     *
     * @param date   日期字符串
     * @param format 格式串
     * @return 返回日期对象
     */
    public static Date parseDate(String date, String format) {
        if (date == null) {
            return null;
        }
        try {
            return new SimpleDateFormat(format).parse(date);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将日期时间字符串转化为日期对象
     *
     * @param date   日期字符串
     * @param format 格式串
     * @return 返回日期对象
     */
    public static Date parseTime(String date, String format) {
        if (date == null) {
            return null;
        }
        try {
            return new SimpleDateFormat(format).parse(date);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将日期时间字符串转化为日期对象
     *
     * @param date 日期字符串 {@linkplain DateUtils#DEFAULT_TIME_FORMAT}
     * @return 返回日期对象
     */
    public static Date parseDate(String date) {
        return parseDate(date, DEFAULT_DATE_FORMAT);
    }

    /**
     * 将日期时间字符串转化为日期对象
     *
     * @param date 日期字符串 {@linkplain DateUtils#DEFAULT_TIME_FORMAT}
     * @return 返回日期对象
     */
    public static Date parseTime(String date) {
        return parseTime(date, DEFAULT_TIME_FORMAT);
    }

    /**
     * 对差异时间的格式化显示，方便人工查看
     *
     * @param diffMillis 差异时间(毫秒)
     * @return 人能看懂的字符串
     */
    public static String getHumanDisplayForTimediff(Long diffMillis) {
        if (diffMillis == null) {
            return "";
        }
        long day = diffMillis / (24 * 60 * 60 * 1000);
        long hour = (diffMillis / (60 * 60 * 1000) - day * 24);
        long min = ((diffMillis / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long se = (diffMillis / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        StringBuilder sb = new StringBuilder();
        if (day > 0) {
            sb.append(day).append("D");
        }
        DecimalFormat df = new DecimalFormat("00");
        sb.append(df.format(hour)).append(":");
        sb.append(df.format(min)).append(":");
        sb.append(df.format(se));
        return sb.toString();
    }

    /**
     * 获取日期相差天数
     *
     * @param beginDate 字符串类型开始日期
     * @param endDate   字符串类型结束日期
     * @return Long 日期相差天数
     */
    public static Long getDiffDay(String beginDate, String endDate) {
        SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
        Long checkday = 0L;
        //开始结束相差天数
        try {
            checkday = (formatter.parse(endDate).getTime() - formatter.parse(beginDate).getTime()) / (1000 * 24 * 60 * 60);
        } catch (ParseException e) {

            e.printStackTrace();
            checkday = null;
        }
        return checkday;
    }

    /**
     * 获取日期相差天数
     *
     * @param beginDate Date类型开始日期
     * @param endDate   Date类型结束日期
     * @return Long 相差天数
     */
    public static Long getDiffDay(Date beginDate, Date endDate) {
        SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
        String strBeginDate = format.format(beginDate);

        String strEndDate = format.format(endDate);
        return getDiffDay(strBeginDate, strEndDate);
    }

    /**
     * N天之后
     *
     * @param n    天数
     * @param date 日期
     * @return n天之后
     */
    public static Date nDaysAfter(Integer n, Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH) + n);
        return cal.getTime();
    }

    /**
     * N年之后
     *
     * @param n    年数
     * @param date 日期
     * @return n年之后
     */
    public static Date nYearsAfter(Integer n, Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + n);
        return cal.getTime();
    }

    /**
     * N天之前
     *
     * @param n    天数
     * @param date 日期
     * @return N天之后
     */
    public static Date nDaysAgo(Integer n, Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH) - n);
        return cal.getTime();
    }

    /**
     * N年之前
     *
     * @param n    年数
     * @param date 日期
     * @return n年之前
     */
    public static Date nYearsAgo(Integer n, Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) - n);
        return cal.getTime();
    }

    /**
     * 指定日期在全年中的第几周
     *
     * @param date 日期
     * @return 返回日期在这一年中的周数
     */
    public static Integer getWeekOfYear(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return Integer.valueOf(formatDate(date, FORMAT_YYYY) + c.get(Calendar.WEEK_OF_YEAR));
    }

    /**
     * 获取当前日期时间
     *
     * @return 返回当前日期时间
     */
    public static Date getCurrentDateTime() {
        return new Date();
    }

    /**
     * 获取当前日期
     *
     * @return 返回当前日期
     */
    public static Date getCurrentDate() {
        Calendar calendar = Calendar.getInstance();
        //获取年份
        int year = calendar.get(Calendar.YEAR);
        //获取月份
        int month = calendar.get(Calendar.MONTH);
        //获取日
        int day = calendar.get(Calendar.DATE);
        calendar.set(year, month, day, 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 日期格式化为年月日的日期
     *
     * @param date 日期
     * @return 年月日的日期
     */
    public static Date formatDate2Date(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(date.getTime());
        //获取年份
        int year = calendar.get(Calendar.YEAR);
        //获取月份
        int month = calendar.get(Calendar.MONTH);
        //获取日
        int day = calendar.get(Calendar.DATE);
        calendar.set(year, month, day, 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    //根据传入日期查询该日期前五天内全部日期，不考虑跨月情况
    public static List<String> getDatesList(String pdate) {
        List<String> datesList = new ArrayList<>();
        List<LocalDate> previousFiveDays = new ArrayList<>();
        LocalDate date2 = LocalDate.parse(pdate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        // 逐一计算前五天的日期
        for (int i = 0; i < 5; i++) {
            //判断是不是在一个月份，如果不是，则不添加，反正则添加
//			if (date2.minusDays(i).getMonthValue() == date2.getMonthValue()) {
//				previousFiveDays.add(date2.minusDays(i));
//			}
            previousFiveDays.add(date2.minusDays(i));
        }
        // 格式化日期为字符串
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (LocalDate date : previousFiveDays) {
            String day = date.format(formatter);
            datesList.add(day);
        }
        return datesList;
    }

    //根据传入的开始时间、结束时间查询该范围内的全部时间
    public static List<String> getRangeDateList(String sdate, String edate) {
        LocalDate startDate = LocalDate.parse(sdate);
        LocalDate endDate = LocalDate.parse(edate);

        List<LocalDate> dateList = new ArrayList<>();
        List<String> rangeList = new ArrayList<>();
        LocalDate currentDate = startDate;

        while (!currentDate.isAfter(endDate)) {
            dateList.add(currentDate);
            currentDate = currentDate.plus(Period.ofDays(1));
        }
        //格式转换
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (LocalDate date : dateList) {
            String day = date.format(formatter);
            rangeList.add(day);
        }

        return rangeList;
    }

    //根据月份获取该月的全部日期信息
    public static List<String> getMonthDates(String pdate) {
        List<String> dateList = new ArrayList<>();
        List<Date> dates = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(pdate);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            int month = calendar.get(Calendar.MONTH);
            while (calendar.get(Calendar.MONTH) == month) {
                dates.add(calendar.getTime());
                calendar.add(Calendar.DAY_OF_MONTH, 1);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        for (Date date1 : dates) {
            dateList.add(sdf.format(date1));
        }
        return dateList;
    }

    //获取传入月份的开始时间和结束时间
    public static List<String> getBEDateOfMonth(String month) {
        List<String> dateList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(month);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            // 获取给定日期所在月份的开始时间
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            Date monthStartDate = calendar.getTime();
            // 获取给定日期所在月份的结束时间
            calendar.add(Calendar.MONTH, 1);
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            calendar.add(Calendar.DAY_OF_MONTH, -1);
            Date monthEndDate = calendar.getTime();
            String startDate = sdf.format(monthStartDate);
            String endDate = sdf.format(monthEndDate);
            dateList.add(startDate);
            dateList.add(endDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return dateList;
    }

    //获取上一个月
    public static String getLastMonth(String month) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = format.parse(month);
            Calendar calendar = Calendar.getInstance();
            // 设置为当前时间
            calendar.setTime(date);
            calendar.add(Calendar.MONTH, -1);
            // 设置为上一个月
            //calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
            date = calendar.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return format.format(date);
    }

    //获取起止时间
    public static List<String> getStartStopTime(String startMonth, String endMonth) {
        List<String> list = new ArrayList<>();
        //开始时间
        startMonth = startMonth.substring(0, 7) + "-01";
        //结束时间
        // 将字符串转换为 LocalDate 对象
        LocalDate date = LocalDate.parse(endMonth, DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        // 获取该月的最后一天
        endMonth = date.withDayOfMonth(date.lengthOfMonth()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        list.add(startMonth);
        list.add(endMonth);

        return list;
    }

    //获取传入月份范围的全部月份的起止时间
    public static Map<String, List<String>> getMonthStartEnd(String start, String end) {
        Map<String, List<String>> map = new HashMap<>();
        List<String> startMonthList = new ArrayList<>();
        List<String> endMonthList = new ArrayList<>();

        // 将字符串转换为 LocalDate 对象
        LocalDate startMonth = LocalDate.parse(start, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        LocalDate endMonth = LocalDate.parse(end, DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        // 遍历月份范围并输出每个月的开始和结束时间
        LocalDate currentMonth = startMonth;
        while (!currentMonth.isAfter(endMonth)) {
            String firstDayOfMonth = currentMonth.withDayOfMonth(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String lastDayOfMonth = currentMonth.withDayOfMonth(currentMonth.lengthOfMonth()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            startMonthList.add(firstDayOfMonth);
            endMonthList.add(lastDayOfMonth);
            // 下一个月
            currentMonth = currentMonth.plusMonths(1);
        }
        map.put("start", startMonthList);
        map.put("end", endMonthList);
        return map;
    }

    //获取月份的天数
    public static int getDaysNumByYearMonth(String date) {
        int year = Integer.parseInt(date.substring(0, 4));
        int month = Integer.parseInt(date.substring(5, 7));
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.DATE, 1);
        calendar.roll(Calendar.DATE, -1);
        return calendar.get(Calendar.DATE);
    }


    public static String getWeekByDate(String date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        try {
            Date givenDate = sdf.parse(date); // 替换为你要检查的日期
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(givenDate);
            int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);

            String weekday;
            switch (dayOfWeek) {
                case Calendar.SUNDAY:
                    weekday = "0";
                    break;
                case Calendar.MONDAY:
                    weekday = "1";
                    break;
                case Calendar.TUESDAY:
                    weekday = "2";
                    break;
                case Calendar.WEDNESDAY:
                    weekday = "3";
                    break;
                case Calendar.THURSDAY:
                    weekday = "4";
                    break;
                case Calendar.FRIDAY:
                    weekday = "5";
                    break;
                case Calendar.SATURDAY:
                    weekday = "6";
                    break;
                default:
                    throw new IllegalStateException("Unexpected value: " + dayOfWeek);
            }
            System.out.println("给定日期是：" + weekday);
            return weekday;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Date stringToDate(String dateString, String format) {
        SimpleDateFormat formatter = new SimpleDateFormat(format);
        try {
            return formatter.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }


    public static String getWeekByDateName(String date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        try {
            Date givenDate = sdf.parse(date); // 替换为你要检查的日期
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(givenDate);
            int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);

            String weekday;
            switch (dayOfWeek) {
                case Calendar.SUNDAY:
                    weekday = "星期天";
                    break;
                case Calendar.MONDAY:
                    weekday = "星期一";
                    break;
                case Calendar.TUESDAY:
                    weekday = "星期二";
                    break;
                case Calendar.WEDNESDAY:
                    weekday = "星期三";
                    break;
                case Calendar.THURSDAY:
                    weekday = "星期四";
                    break;
                case Calendar.FRIDAY:
                    weekday = "星期五";
                    break;
                case Calendar.SATURDAY:
                    weekday = "星期六";
                    break;
                default:
                    throw new IllegalStateException("Unexpected value: " + dayOfWeek);
            }
            System.out.println("给定日期是：" + weekday);
            return weekday;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }



    /**
     * 根据年月获取月初第一天日期
     * @param year
     * @param month
     * @return
     */
    public static String getFirstDay(int year,int month,String format) {
        Calendar cale = Calendar.getInstance();



        cale.set(Calendar.YEAR,year);    //赋值年份
        cale.set(Calendar.MONTH, month-1);//赋值月份
        int lastDay = cale.getActualMinimum(Calendar.DAY_OF_MONTH);//获取月最大天数
        cale.set(Calendar.DAY_OF_MONTH, lastDay);//设置日历中月份的最大天数
        SimpleDateFormat sdf = new SimpleDateFormat(format);//格式化日期yyyy-MM-dd
        String lastDayOfMonth = sdf.format(cale.getTime());
        return lastDayOfMonth;
    }


    /**
     * 根据年月获取月末最后一天日期
     * @param year
     * @param month
     * @return
     */
    public static String getLastDay(int year,int month,String format) {
        Calendar cale = Calendar.getInstance();

        cale.set(Calendar.YEAR,year);//赋值年份
        cale.set(Calendar.MONTH, month-1);//赋值月份
        int lastDay = cale.getActualMaximum(Calendar.DAY_OF_MONTH);//获取月最大天数
        cale.set(Calendar.DAY_OF_MONTH, lastDay);//设置日历中月份的最大天数
        SimpleDateFormat sdf = new SimpleDateFormat(format);    //格式化日期yyyy-MM-dd
        String lastDayOfMonth = sdf.format(cale.getTime());
        return lastDayOfMonth;
    }

    public static void main(String[] args) {
        List<String> cdf=DateUtils.getBEDateOfMonth("02");
    }
}