package yem.base.common.utils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;

/**
 * Date工具类
 *
 * @author longh
 * @description:
 * @date 2021年12月2日 下午5:23:06
 */
public class DateUtil {
    public static final String FORMAT_YMD = "yyyy-MM-dd";
    public static final String FORMAT_YMDHMS = "yyyy-MM-dd HH:mm:ss";
    public static final String FORMAT_yyyyMMdd = "yyyyMMdd";
    private static DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    private static DateFormat formatHms = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

    /**
     * 日期格式化
     *
     * @param date
     * @param format //常用："yyyy-MM-dd","yyyy-MM-dd HH:mm:ss","yyyyMMdd"
     * @return
     */
    public static String formatDate(Date date, String format) {
        SimpleDateFormat simpleFormat = new SimpleDateFormat(format);
        return simpleFormat.format(date);
    }

    /**
     * 时间转字符串 格式yyyy-MM-dd
     *
     * @param date
     * @return
     */
    public static String formatDate(Date date) {
        String datestr = "";
        if (date != null) {
            datestr = format.format(date);
        }
        return datestr;
    }

    /**
     * 时间转字符串 格式yyyy-MM-dd hh:mm:ss
     *
     * @param date
     * @return
     */
    public static String formatDateHms(Date date) {
        String datestr = "";
        if (date != null) {
            datestr = formatHms.format(date);
        }
        return datestr;
    }

    /**
     * 字符串转时间  格式yyyy-MM-dd
     *
     * @param datestr
     * @return
     */
    public static Date parseDate(String datestr) {
        Date date = null;
        if (datestr != null && !datestr.isEmpty() && !"null".equals(datestr)) {
            try {
                date = format.parse(datestr);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return date;
    }

    /***
     * 计算用时天数（向下取整）
     * @param begin
     * @param end
     * @return
     */
    public static int countDays(Date begin, Date end) {
        return (int) ((end.getTime() - begin.getTime()) / (1000 * 60 * 60 * 24));
    }

    /***
     * 计算用时小时数（向下取整）
     * @param begin
     * @param end
     * @return
     */
    public static int countHours(Date begin, Date end) {
        return (int) ((end.getTime() - begin.getTime()) / (1000 * 60 * 60));
    }

    /**
     * 计算实际用时天数（注：1月1日 23:59:59 - 1月2日 00:00:01 算两天）
     *
     * @param begin
     * @param end
     * @return
     */
    public static int countActualDays(Date begin, Date end) {
        LocalDate start = begin.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate over = end.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        return (int) (over.toEpochDay() - start.toEpochDay() + 1);
    }

    /**
     * 获取指定日期添加/减去指定天数后的日期
     *
     * @param date
     * @param days 负参为减
     * @return
     */
    public static Date addDays(Date date, int days) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, days);
        return calendar.getTime();
    }

    /**
     * 将日期的 时、分、秒、毫秒域 清零
     *
     * @param date
     * @return
     */
    public static Date cleanDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(10, 0);
        cal.set(11, 0);
        cal.set(12, 0);
        cal.set(13, 0);
        cal.set(14, 0);
        return cal.getTime();
    }

    /**
     * 获取本年第一天
     *
     * @return
     */
    public static Date getCurrYearFirst() {
        Calendar currCal = Calendar.getInstance();
        int currentYear = currCal.get(1);
        return getYearFirst(currentYear);
    }

    /**
     * 获取本年最后一天
     *
     * @return
     */
    public static Date getCurrYearLast() {
        Calendar currCal = Calendar.getInstance();
        int currentYear = currCal.get(1);
        currCal.set(currentYear, 11, 31, 23, 59, 59);
        return currCal.getTime();
    }

    /**
     * 获取当年第一天
     *
     * @param year
     * @return
     */
    public static Date getYearFirst(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(1, year);
        Date currYearFirst = calendar.getTime();
        return currYearFirst;
    }

    /**
     * 获取当年第一天
     *
     * @param date
     * @return
     */
    public static Date getYearFirst(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = calendar.get(1);
        calendar.clear();
        calendar.set(1, year);
        Date currYearFirst = calendar.getTime();
        return currYearFirst;
    }

    /**
     * 获取当周第一天
     *
     * @return
     */
    public static Date getWeekStart(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.WEEK_OF_MONTH, 0);
        calendar.set(Calendar.DAY_OF_WEEK, 2);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取当周最后一天
     *
     * @return
     */
    public static Date getWeekEnd(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_WEEK, calendar.getActualMaximum(Calendar.DAY_OF_WEEK));
        calendar.add(Calendar.DAY_OF_WEEK, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 99);
        return calendar.getTime();
    }

    /**
     * add by zhangh   20220311
     * 获取本周第一天
     *
     * @return
     */
    public static Date getWeekStart() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.WEEK_OF_MONTH, 0);
        calendar.set(Calendar.DAY_OF_WEEK, 2);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * add by zhangh   20220311
     * 获取本周最后一天
     *
     * @return
     */
    public static Date getWeekEnd() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_WEEK, calendar.getActualMaximum(Calendar.DAY_OF_WEEK));
        calendar.add(Calendar.DAY_OF_WEEK, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 99);
        return calendar.getTime();
    }

    /**
     * add by zhangh  20220314
     * 获取上周第一天
     *
     * @return
     */
    public static Date getLastWeekStart() {
        Calendar calendar = Calendar.getInstance();
        // 将每周第一天设为星期一，默认是星期天
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.add(Calendar.DATE, -1 * 7);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);

        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * add by zhangh 20220314
     * 获取上周最后一天
     *
     * @return
     */
    public static Date getLastWeekEnd() {
        Calendar calendar = Calendar.getInstance();
        //将每周第一天设为星期一，默认是星期天
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.add(Calendar.DATE, -1 * 7);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);

        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 99);
        return calendar.getTime();
    }

    /**
     * 获取当年最后一天
     *
     * @param date
     * @return
     */
    public static Date getYearLast(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = calendar.get(1);
        calendar.set(year, 11, 31, 23, 59, 59);
        return calendar.getTime();
    }

    /**
     * 获取去年第一天
     *
     * @param date
     * @return
     */
    public static Date getLastYearFirst(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = calendar.get(1);
        calendar.clear();
        calendar.set(1, year - 1);
        Date currYearFirst = calendar.getTime();
        return currYearFirst;
    }

    /**
     * 获取去年最后一天
     *
     * @param date
     * @return
     */
    public static Date getLastYearEnd(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = calendar.get(1);
        calendar.set(year - 1, 11, 31, 23, 59, 59);
        return calendar.getTime();
    }

    /**
     * 获取本月第一天
     *
     * @return
     */
    public static Date getThisMonthFirstDay() {
        Calendar c = Calendar.getInstance();
        c.set(5, 1);
        c.set(11, 0);
        c.set(12, 0);
        c.set(13, 0);
        c.set(14, 0);
        return c.getTime();
    }

    /**
     * 获取本月最后一天
     *
     * @return
     */
    public static Date getThisMonthEndDay() {
        Calendar ca = Calendar.getInstance();
        ca.set(5, ca.getActualMaximum(5));
        ca.set(11, 23);
        ca.set(12, 59);
        ca.set(13, 59);
        ca.set(14, 99);
        return ca.getTime();
    }

    /**
     * 获取当月第一天
     *
     * @param date
     * @return
     */
    public static Date getMonthFirstDay(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(5, 1);
        c.set(11, 0);
        c.set(12, 0);
        c.set(13, 0);
        c.set(14, 0);
        return c.getTime();
    }

    /**
     * 获取当月最后一天
     *
     * @param date
     * @return
     */
    public static Date getMonthEndDay(Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.set(5, ca.getActualMaximum(5));
        ca.set(11, 23);
        ca.set(12, 59);
        ca.set(13, 59);
        ca.set(14, 99);
        return ca.getTime();
    }

    /**
     * 获取上个月第一天
     *
     * @param date
     * @return
     */
    public static Date getLastMonthFirstDay(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(2, c.get(2) - 1);
        c.set(5, 1);
        c.set(11, 0);
        c.set(12, 0);
        c.set(13, 0);
        c.set(14, 0);
        return c.getTime();
    }

    /**
     * 获取上个月最后一天
     *
     * @param date
     * @return
     */
    public static Date getLastMonthEndDay(Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.set(2, ca.get(2) - 1);
        ca.set(5, ca.getActualMaximum(5));
        ca.set(11, 23);
        ca.set(12, 59);
        ca.set(13, 59);
        ca.set(14, 99);
        return ca.getTime();
    }

    /**
     * 获取上个月同一天
     *
     * @param date
     * @return
     */
    public static Date getLastMonthDay(Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.set(2, ca.get(2) - 1);
        return ca.getTime();
    }

    /**
     * 获取去年当月第一天
     *
     * @param date
     * @return
     */
    public static Date getMonthFirstDayLastYear(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(1, c.get(1) - 1);
        c.set(5, 1);
        c.set(11, 0);
        c.set(12, 0);
        c.set(13, 0);
        c.set(14, 0);
        return c.getTime();
    }

    /**
     * 获取去年当月最后一天
     *
     * @param date
     * @return
     */
    public static Date getMonthEndDayLastYear(Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.set(1, ca.get(1) - 1);
        ca.set(5, ca.getActualMaximum(5));
        ca.set(11, 23);
        ca.set(12, 59);
        ca.set(13, 59);
        ca.set(14, 99);
        return ca.getTime();
    }

    public static Date getQuarterFirst(int quarter) {
        Calendar cal = Calendar.getInstance();
        int year = cal.get(1);
        cal.clear();
        if (quarter == 1) {
            cal.set(year, 0, 1, 0, 0, 0);
        } else if (quarter == 2) {
            cal.set(year, 3, 1, 0, 0, 0);
        } else if (quarter == 3) {
            cal.set(year, 6, 1, 0, 0, 0);
        } else {
            cal.set(year, 9, 1, 0, 0, 0);
        }

        return cal.getTime();
    }

    public static Date getQuarterLast(int quarter) {
        Calendar cal = Calendar.getInstance();
        int year = cal.get(1);
        cal.clear();
        if (quarter == 1) {
            cal.set(year, 2, 31, 23, 59, 59);
        } else if (quarter == 2) {
            cal.set(year, 5, 30, 23, 59, 59);
        } else if (quarter == 3) {
            cal.set(year, 8, 30, 23, 59, 59);
        } else {
            cal.set(year, 11, 31, 23, 59, 59);
        }

        return cal.getTime();
    }

    /**
     * 获取当天的开始或结束时间
     *
     * @param date
     * @param isEnd
     * @return
     */
    public static Date getStartOrEndDate(Date date, boolean isEnd) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        if (isEnd) {
            cal.set(11, 23);
            cal.set(12, 59);
            cal.set(13, 59);
        } else {
            cal.set(11, 0);
            cal.set(12, 0);
            cal.set(13, 0);
        }

        return cal.getTime();
    }

    public static Date getStartOfDay(Date date) {
        return localDateTimeToDate(LocalDateTime.of(dateToLocalDate(date), LocalTime.MIN));
    }

    public static Date getEndOfDay(Date date) {
        return localDateTimeToDate(LocalDateTime.of(dateToLocalDate(date), LocalTime.MAX));
    }

    public static LocalDate dateToLocalDate(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static Date localDateTimeToDate(LocalDateTime date) {
        return Date.from(date.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date localDateToDate(LocalDate date) {
        return Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    public static LocalDate getStartOfYear(int year) {
        return LocalDate.of(year, 1, 1);
    }

    public static int getDay(final Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(5);
    }

    public static int getMonth(final Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(2);
    }

    public static int getYear(final Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(1);
    }

    /**
     * 判断是否同一天
     *
     * @param date1
     * @param date2
     * @return
     */
    public static boolean isSameDay(final Date date1, final Date date2) {
        if (date1 == null || date2 == null) {
            return false;
        }
        final Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        final Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        return isSameDay(cal1, cal2);
    }

    /**
     * 判断是否同一天
     *
     * @param cal1
     * @param cal2
     * @return
     */
    public static boolean isSameDay(final Calendar cal1, final Calendar cal2) {
        return cal1 != null && cal2 != null && cal1.get(0) == cal2.get(0) && cal1.get(1) == cal2.get(1) && cal1.get(6) == cal2.get(6);
    }

    /**
     * 判断是否同月
     *
     * @param d1
     * @param d2
     * @return
     */
    public static boolean isSameMonth(final Date d1, final Date d2) {
        return isSameDay(getMonthFirstDay(d1), getMonthFirstDay(d2));
    }
}