package com.hs.admin.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.util.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 日期操作相关的工具
 */
public class DateUtil {

    private static final Logger log = LoggerFactory.getLogger(DateUtil.class);


    /**
     * @param createTime 传入的日期
     * @param count      时间间隔
     * @return 根据传入的日期与时间间隔，计算过期的时间
     */
    public static Date calExpiredTime(Date createTime, int stepType, int count) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(createTime);
        calendar.add(stepType, count);
        return calendar.getTime();
    }

    /**
     * @param count 提前月的数量
     * @return 月的范围
     * 计算前count个月的范围，如果月为0，代表当月
     */
    public static Date[] getLastetMonthN(int count) {
        Date[] date = new Date[2];
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -count);
        int minMonDay = calendar.getMinimum(Calendar.DAY_OF_MONTH);
        calendar.set(Calendar.DAY_OF_MONTH, minMonDay);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.add(Calendar.SECOND, -1);
        date[0] = calendar.getTime();
        calendar.add(Calendar.MONTH, 1);
        int maxMonDay = calendar.getMaximum(Calendar.DAY_OF_MONTH);
        calendar.set(Calendar.DAY_OF_MONTH, maxMonDay);
        date[1] = calendar.getTime();
        return date;
    }

    /**
     * @return 获取当前时间的“年-月”信息
     */
    public static String getLastYearMonth() {
        Calendar calendar = Calendar.getInstance();
        StringBuilder sb = new StringBuilder();
        calendar.add(Calendar.MONTH, -1);
        sb.append(calendar.get(Calendar.YEAR));
        sb.append("-");
        int month = calendar.get(Calendar.MONTH) + 1;
        if (month < 10) {
            sb.append("0");
        }
        sb.append(month);
        return sb.toString();
    }

    /**
     * @param date
     * @return 获取指定时间的“年-月”信息
     */
    public static String getYearMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        StringBuilder sb = new StringBuilder();
        sb.append(calendar.get(Calendar.YEAR));
        sb.append("-");
        int month = calendar.get(Calendar.MONTH) + 1;
        if (month < 10) {
            sb.append("0");
        }
        sb.append(month);
        return sb.toString();
    }

    /**
     * @param date
     * @return 获取指定时间的“年-月-日”信息
     */
    public static String getYearMonthDay(Date date) {
        DateFormatter dateFormatter = new DateFormatter("yyyy-MM-dd");
        String dateTo = dateFormatter.print(date, Locale.CHINA);
        return dateTo;
    }

    /**
     * @param date
     * @return 获取指定时间的“年-月-日”信息
     */
    public static String getToMinute(Date date) {
        DateFormatter dateFormatter = new DateFormatter("yyyy-MM-dd HH:mm");
        String dateTo = dateFormatter.print(date, Locale.CHINA);
        return dateTo;
    }

    /**
     * 获取指定时间的“年-月-日 HH:mm:ss”信息
     */

    public static String getYearMonthDayHMS(Date date, String resultDateFormat) {
        if (date == null) {
            return "";
        }
        DateFormatter dateFormatter = new DateFormatter(resultDateFormat);
        String dateTo = dateFormatter.print(date, Locale.CHINA);
        return dateTo;
    }

    /**
     * 获取指定时间的“年-月-日 HH:mm:ss”信息
     */
    public static String getYearMonthDayHMS(Date date) {
        return getYearMonthDayHMS(date, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * @return 获取当天日期
     */
    public static Date getToday() {
        Calendar calendar = Calendar.getInstance();
        return calendar.getTime();
    }

    /**
     * @return 获取当天日期字符串
     */
    public static String getTodayString() {
        return getYearMonthDay(getToday());
    }

    /**
     * @return 当前年月
     * 获取当前年月
     */
    public static String getNowYearMonth() {
        Calendar calendar = Calendar.getInstance();
        StringBuilder sb = new StringBuilder();
        sb.append(calendar.get(Calendar.YEAR));
        sb.append("-");
        int month = calendar.get(Calendar.MONTH) + 1;
        if (month < 10) {
            sb.append("0");
        }
        sb.append(month);
        return sb.toString();
    }

    /**
     * @param date
     * @return 昨天的日期
     * 获得昨天的日期
     */
    public static Date yesterday(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -1);
        Date resultDate = calendar.getTime();
        return resultDate;
    }

    /**
     * @param count
     * @return 获得以这
     */
    public static String getYearMonthCount(int count) {
        Calendar calendar = Calendar.getInstance();
        StringBuilder sb = new StringBuilder();
        calendar.add(Calendar.MONTH, count);
        sb.append(calendar.get(Calendar.YEAR));
        sb.append("-");
        int month = calendar.get(Calendar.MONTH) + 1;
        if (month < 10) {
            sb.append("0");
        }
        sb.append(month);
        return sb.toString();
    }

    /**
     * @param dateStr 时间字符串
     * @return 增加一天之后的时间字符串
     */
    public static String addOneDay(String dateStr) {
        try {
            DateFormatter dateFormatter = new DateFormatter("yyyy-MM-dd");
            Date date = dateFormatter.parse(dateStr, Locale.CHINA);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.DATE, 1);
            date = calendar.getTime();
            String dateTo = dateFormatter.print(date, Locale.CHINA);
            return dateTo;
        } catch (ParseException e) {
            log.error("addOneDay dateStr={} cause={}", dateStr, e);
        }
        return null;
    }


    /**
     * @param date 日期
     * @return 将日期设为周一
     * 返回周一的日期
     */
    public static Date toSunday(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        Date dateResult = calendar.getTime();
        return dateResult;
    }


    /**
     * @param date 日期
     * @return 本月第一天的日期
     * 将日期设为本月的第一天
     */
    public static Date toBeginOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        Date dateResult = calendar.getTime();
        return dateResult;
    }

    /**
     * @param date
     * @param resultDateFormat
     * @return 本月第一天的日期
     * 将日期设为本月的第一天
     */
    public static String toBeginOfMonth(Date date, String resultDateFormat) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return new SimpleDateFormat(resultDateFormat).format(calendar.getTime());

    }

    /**
     * @param date
     * @param resultDateFormat 获取当前月最后一天
     * @return
     */
    public static String toEndOfMonth(Date date, String resultDateFormat) {
        //获取当前月最后一天
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        return new SimpleDateFormat(resultDateFormat).format(ca.getTime());
    }

    public static Date toEndOfMonth(Date date) {
        //获取当前月最后一天
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        String format = new SimpleDateFormat("yyyy-MM-dd").format(ca.getTime());
        return toDate(format);
    }


    /**
     * 每周的第一天
     *
     * @param resultDateFormat
     * @return
     */
    public static String getFirstOfWeek(Date date, String resultDateFormat) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int d = 0;
        if (cal.get(Calendar.DAY_OF_WEEK) == 1) {
            d = -6;
        } else {
            d = 2 - cal.get(Calendar.DAY_OF_WEEK);
        }
        cal.add(Calendar.DAY_OF_WEEK, d);
        // 所在周开始日期
        return new SimpleDateFormat(resultDateFormat).format(cal.getTime());
    }

    /**
     * 每周的最后一天
     *
     * @param date
     * @param resultDateFormat
     */
    public static String getLastOfWeek(Date date, String resultDateFormat) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int d = 6;
        cal.add(Calendar.DAY_OF_WEEK, d);
        // 所在周结束日期
        return new SimpleDateFormat(resultDateFormat).format(cal.getTime());
    }

    /**
     * @param date 日期
     * @return 将日期设置为年的第一天
     * 年的第一天
     */
    public static Date toEndOfYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_YEAR, 1);
        calendar.add(Calendar.YEAR, 1);
        calendar.add(Calendar.DATE, -1);
        Date dateResult = calendar.getTime();
        return dateResult;
    }

    /**
     * @param date 日期
     * @return 将日期转化到零点
     */
    public static Date toFirstTimeOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date result = calendar.getTime();
        return result;
    }

    /**
     * @param date 日期
     * @return 将日期转化到一天末尾
     */
    public static Date toLastTimeOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        Date result = calendar.getTime();
        return result;
    }

    /**
     * @param date1
     * @param date2
     * @return 是否为同一天
     * 判断是否为同一天
     */
    public static boolean sameDay(Date date1, Date date2) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date1);
        int day1 = calendar.get(Calendar.DATE);
        int month1 = calendar.get(Calendar.MONTH);
        int year1 = calendar.get(Calendar.YEAR);
        calendar.setTime(date2);
        int day2 = calendar.get(Calendar.DATE);
        int month2 = calendar.get(Calendar.MONTH);
        int year2 = calendar.get(Calendar.YEAR);
        return year2 == year1 && month1 == month2 && day1 == day2;
    }

    /**
     * @param date 日期
     * @return 递增后的日期
     * 日期按天递增
     */
    public static Date dayIncrement(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, 1);
        return calendar.getTime();
    }

    /**
     * String 转换Date格式（yyyy-MM-dd）
     *
     * @param dateStr 时间格式
     * @return
     */
    public static Date toFormatDate(String dateStr) {
        try {
            DateFormatter dateFormatter = new DateFormatter("yyyy/MM/dd");
            return dateFormatter.parse(dateStr, Locale.CHINA);
        } catch (ParseException e) {
            log.error("toFormatDate: dateStr={} cause={}", dateStr, e);
        }
        return null;
    }

    /**
     * String 转换Date格式（yyyy-MM-dd）
     *
     * @param dateStr 时间格式
     * @return
     */
    public static Date toFormatDate(String dateStr, String format) {
        try {
            DateFormatter dateFormatter = new DateFormatter(format);
            return dateFormatter.parse(dateStr, Locale.CHINA);
        } catch (ParseException e) {
            log.error("toFormatDate: dateStr={} cause={}", dateStr, e);
        }
        return null;
    }

    /**
     * @Description: 日期转String
     * @params: [date, format]
     * @Return: java.lang.String
     * @Author: lixin
     * @Date: 2018/8/6 15:31
     * @Modified:
     */
    public static String format(Date date, String format) {
        if (date == null) {
            return null;
        }

        return new SimpleDateFormat(format).format(date);
    }

    /**
     * @Description: 获得格式化
     * @params: [code]
     * @Return: java.lang.String
     * @Author: sulijuan
     * @Date: 2018/8/13 11:31
     * @Modified:
     */
    public static String getFormat(String code) {
        switch (code) {
            case "0":
                return "%Y-%m";
            case "1":
                return "%Y-%m-%d";
            default:
                return "%Y-%m";
        }
    }

    /**
     * @Description: 获得某天的 前后 n 天的日期
     * @params: []
     * @Return: java.lang.String
     * @Author: sulijuan
     * @Date: 2018/8/23 16:47
     * @Modified:
     */
    public static String getDaysBeforeOrAfter(Date today, String resultDateFormat, int n) {
        SimpleDateFormat sdf = new SimpleDateFormat(resultDateFormat);
        //获取三十天前日期
        Calendar theCa = Calendar.getInstance();
        theCa.setTime(today);
        theCa.add(theCa.DATE, n);//最后一个数字30可改，30天的意思
        Date start = theCa.getTime();
        return sdf.format(start);//三十天之前日期
    }

    /**
     * @Description: String 转 Date
     * @params: [dateString]
     * @Return: java.util.Date
     * @Author: sulijuan
     * @Date: 2018/8/23 16:58
     * @Modified:
     */
    public static Date toDate(String dateString) {
        DateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = format1.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }  //完成字符串年月日转年月日时分秒的字符串操作
    public static Date toDateMillisecond(String dateString) {
        DateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        Date date = null;
        try {
            date = format1.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }  //完成字符串年月日转年月日时分秒的字符串操作

    public static String getFirsetFormat(String s) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        try {
            Date parse = sdf.parse(s);
            date = DateUtil.toFirstTimeOfDay(parse);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return sdf2.format(date);
    }

    public static String getLastFormat(String s) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        try {
            Date parse = sdf.parse(s);
            date = DateUtil.toLastTimeOfDay(parse);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return sdf2.format(date);
    }

    public static String getTimeByLong(long time) {
        long hour = time / 3600;
        time = time % 3600;
        long min = time / 60;
        return hour + "小时" + min + "分";
    }

    /**
     * @Description: 获取当前年月日时分秒，20190110175750
     * @params: []
     * @Return: java.lang.String
     * @Author: ckx
     * @Date: 2019/1/10 17:57
     * @Modified:
     */
    public static String getNowDateString() {
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        return formatter.format(currentTime);
    }

    /**
     * @Description: 两个时间之间的月份
     * @params: [minDate, maxDate]
     * @Return: java.util.List<java.lang.String>
     * @Author: sulijuan
     * @Date: 2018/11/7 19:34
     * @Modified:
     */
    public static List<String> getMonthBetween(String minDate, String maxDate) throws ParseException {
        ArrayList<String> result = new ArrayList<String>();
        //格式化为年月
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");

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

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

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

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

    /**
     * @Description: 两个时间的日期
     * @params: [startDate, endDate]
     * @Return: java.util.List<java.util.Date>
     * @Author: sulijuan
     * @Date: 2018/11/7 19:35
     * @Modified:
     */
    public static List<Date> dateSplit(Date startDate, Date endDate)
            throws Exception {
        if (!startDate.before(endDate)) {
            throw new Exception("开始时间应该在结束时间之后");
        }
        Long spi = endDate.getTime() - startDate.getTime();
        // 相隔天数
        Long step = spi / (24 * 60 * 60 * 1000);

        List<Date> dateList = new ArrayList<Date>();
        dateList.add(endDate);
        for (int i = 1; i <= step; i++) {
            // 比上一天减一
            dateList.add(new Date(dateList.get(i - 1).getTime()
                    - (24 * 60 * 60 * 1000)));
        }
        return dateList;
    }

    /**
     * @Description: String时间排序
     * @params: [data]
     * @Return: java.util.List<java.lang.String>
     * @Author: sulijuan
     * @Date: 2018/11/8 13:27
     * @Modified:
     */
    public static List<String> compareDateMonthString(List<String> data) {
        Collections.sort(data, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                String[] arr1 = o1.split("_");
                String[] arr2 = o2.split("_");
                int comparator = toInt(arr1[0], +1) - toInt(arr2[0], +2);
                if (comparator == 0) {
                    comparator = toInt(arr1[1], +1) - toInt(arr2[1], +2);
                    if (comparator == 0) {
                        return toInt(arr1[2], +1) - toInt(arr2[2], +2);
                    }
                }
                return comparator;
            }
        });
        return data;
    }

    private static int toInt(String str, int delVal) {
        try {
            return Integer.parseInt(str);
        } catch (Exception e) {
            return delVal;
        }
    }

    public static int getDaysBetweenTwoDays(String startDay, String endDay) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(toDate(startDay));
        long fromTime = calendar.getTimeInMillis();

        calendar.setTime(toDate(endDay));
        long toTime = calendar.getTimeInMillis();

        long between_days = (toTime - fromTime) / (1000 * 3600 * 24);
        return Integer.parseInt(String.valueOf(between_days));
    }

    public static boolean checkDateFormat(String dateStr) {
        if (!StringUtils.isEmpty(dateStr) && dateStr.length() != 10) return false;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date date = simpleDateFormat.parse(dateStr);
            return dateStr.equals(simpleDateFormat.format(date));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static String getFirstDayOfMonth(Date date) {
        return getYearMonthDay(toBeginOfMonth(date));
    }

    public static String getEndDayOfMonth(Date date) {
        return getYearMonthDay(toEndOfMonth(date));
    }

    public static void main(String[] args) throws ParseException {
        System.out.println(DateUtil.getYearMonthDay(DateUtil.toBeginOfMonth(DateUtil.toDate("2020-02-11"))));
        System.out.println(DateUtil.getYearMonthDay(DateUtil.toEndOfMonth(DateUtil.toDate("2020-02-11"))));
        System.out.println(DateUtil.getDaysBetweenTwoDays("2020-11-11", DateUtil.getYearMonthDay(new Date())));
    }
}
