/**
 * @Author:gongyijun
 * @Title: DateUtil.java
 * @Package com.zhgd.utils
 * @Description: TODO
 * @date 2017年12月22日 下午5:47:05
 * @version V1.0
 */
package com.zhgd.jeecg.common.util;

import lombok.extern.slf4j.Slf4j;

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

/**
 * @Author:gongyijun
 * @ClassName: DateUtil
 * @Description: TODO
 * @date 2017年12月22日 下午5:47:05
 */
@Slf4j
public class DateUtil {
    private static int getDay(String year, String month) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, Integer.parseInt(year));
        c.set(Calendar.MONTH, Integer.parseInt(month) - 1);
        return c.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    private static int getYuTian(int endDay, int toDay) {
        int yuTian = 0;
        if (1 == toDay) {
            toDay += 5;
        } else {
            toDay = toDay - 2;
        }
        yuTian = endDay + toDay;
        if (yuTian > 7) {
            return yuTian % 7;
        }
        if (yuTian == 6) {
            return endDay - 1;
        } else if (yuTian == 7) {
            return endDay - 2;
        } else {
            return endDay;
        }
    }

    public static int workDay(String data) {
        Calendar c = Calendar.getInstance(Locale.CHINA);
        String[] sp = data.split("-");
        c.set(Calendar.YEAR, Integer.parseInt(sp[0]));
        c.set(Calendar.MONTH, Integer.parseInt(sp[1]) - 1);
        c.set(Calendar.DATE, 1);// 计算1号是星期几
        int countDay = getDay(sp[0], sp[1]);
        log.info("总天数" + getDay(sp[0], sp[1]));
        int workDay = 0;
        int countWeek = countDay / 7;
        int wd = c.get(Calendar.DAY_OF_WEEK);
        int yuDay = getYuTian(countDay % 7, wd);
        workDay = countWeek * 5 + yuDay;
        return workDay;
    }

    public static Map<String, Object> getWeekStartAndEnd() throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 设置时间格式
        Calendar cal = Calendar.getInstance();
        Date time = new Date();
        cal.setTime(time);
        log.info("要计算日期为:" + sdf.format(cal.getTime())); // 输出要计算日期
        // 判断要计算的日期是否是周日，如果是则减一天计算周六的，否则会出问题，计算到下一周去了
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }
        cal.setFirstDayOfWeek(Calendar.MONDAY);// 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        int day = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
        // 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        String mondayDate = sdf.format(cal.getTime());
        log.info("所在周星期一的日期：" + mondayDate);
        cal.add(Calendar.DATE, 6);
        String sundayDate = sdf.format(cal.getTime());
        log.info("所在周星期日的日期：" + sundayDate);
        Map<String, Object> map = new HashMap<>();
        map.put("startDate", mondayDate + " 00:00:00");
        map.put("endDate", sundayDate + " " + "23:59:59");
        return map;
    }

    public static Map<String, Object> getLastWeekTimeInterval() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar1 = Calendar.getInstance();
        Calendar calendar2 = Calendar.getInstance();
        int dayOfWeek = calendar1.get(Calendar.DAY_OF_WEEK) - 1;
        int offset1 = 1 - dayOfWeek;
        int offset2 = 7 - dayOfWeek;
        calendar1.add(Calendar.DATE, offset1 - 7);
        calendar2.add(Calendar.DATE, offset2 - 7);
        // log.info(sdf.format(calendar1.getTime()));// last Monday
        String lastBeginDate = sdf.format(calendar1.getTime());
        // log.info(sdf.format(calendar2.getTime()));// last Sunday
        String lastEndDate = sdf.format(calendar2.getTime());
        Map<String, Object> map = new HashMap<>();
        map.put("startDate", lastBeginDate + " 00:00:00");
        map.put("endDate", lastEndDate + " " + "23:59:59");
        return map;
    }

    public static Map<String, Object> getLastMonthTimeInterval() {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, -1);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss");
        String gtimelast = sdf.format(c.getTime()); // 上月
        log.info(gtimelast);
        int lastMonthMaxDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);
        log.info("{}", lastMonthMaxDay);
        c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), lastMonthMaxDay, 23, 59, 59);
        // 按格式输出
        String lastEndDate = sdf.format(c.getTime()); // 上月最后一天
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-01  00:00:00");
        String lastBeginDate = sdf2.format(c.getTime()); // 上月第一天
        Map<String, Object> map = new HashMap<>();
        map.put("startDate", lastBeginDate);
        map.put("endDate", lastEndDate);
        return map;
    }

    public static Map<String, Object> getMonthStartAndEnd(int year, int month) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 设置时间格式
        Calendar cal = Calendar.getInstance();
        cal.set(year, month - 1, 1);
        String mondayDate = sdf.format(cal.getTime());
        log.info("所在月份开始的日期：" + mondayDate);
        int day = cal.getActualMaximum(5);
        cal.set(year, month - 1, day);
        String sundayDate = sdf.format(cal.getTime());
        log.info("所在月份的结束的日期：" + sundayDate);
        Map<String, Object> map = new HashMap<>();
        map.put("startDate", mondayDate + "");
        map.put("endDate", sundayDate + "");
        return map;
    }

//	public static void main(String[] args) {
//		log.info(getMonthStartAndEnd(2019,05)) ;
//	}

    public static Map<String, Object> getYearStartAndEnd() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 设置时间格式
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, getNowYear());
        cal.set(Calendar.MONTH, Calendar.JANUARY);
        cal.set(Calendar.DATE, 1);
        String mondayDate = sdf.format(cal.getTime());
        log.info("所在年份开始的日期：" + mondayDate);
        cal.set(Calendar.YEAR, getNowYear());
        cal.set(Calendar.MONTH, Calendar.DECEMBER);
        cal.set(Calendar.DATE, 31);
        String sundayDate = sdf.format(cal.getTime());
        log.info("所在年份的结束的日期：" + sundayDate);
        Map<String, Object> map = new HashMap<>();
        map.put("startDate", mondayDate);
        map.put("endDate", sundayDate + " " + "23:59:59");
        return map;
    }

    // public static void main(String[] args) throws ParseException {
    //
    // log.info(getLastWeekTimeInterval());
    // }

    // 获取今年是哪一年
    public static Integer getNowYear() {
        Date date = new Date();
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        return Integer.valueOf(gc.get(1));
    }

    // 获取本月是哪一月
    public static int getNowMonth() {
        Date date = new Date();
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        return gc.get(2) + 1;
    }

    public static Map<String, Object> getYesterDayStr() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 设置时间格式
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -1);// 把日期往后增加一天.整数往后推,负数往前移动
        String dateString = sdf.format(cal.getTime());
        Map<String, Object> map = new HashMap<>();
        map.put("startDate", dateString);
        map.put("endDate", dateString);
        return map;
    }

    public static Map<String, Object> getTodDayStr() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 设置时间格式
        Calendar cal = Calendar.getInstance();
        String dateString = sdf.format(cal.getTime());
        Map<String, Object> map = new HashMap<>();
        map.put("startDate", dateString);
        map.put("endDate", dateString);
        return map;
    }

    /**
     * 判断某一时间是否在一个区间内
     *
     * @param sourceTime 时间区间,半闭合,如[10:00-20:00)
     * @param curTime    需要判断的时间 如10:00
     * @throws IllegalArgumentException
     * @author Songzhipeng
     */
    public static boolean isInTime(String sourceTime, String curTime) {
        if (sourceTime == null || !sourceTime.contains("-") || !sourceTime.contains(":")) {
            throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);
        }
        if (curTime == null || !curTime.contains(":")) {
            throw new IllegalArgumentException("Illegal Argument arg:" + curTime);
        }
        String[] args = sourceTime.split("-");
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        try {
            long now = sdf.parse(curTime).getTime();
            long start = sdf.parse(args[0]).getTime();
            long end = sdf.parse(args[1]).getTime();
            if (args[1].equals("00:00")) {
                args[1] = "24:00";
            }
            if (end < start) {
                if (now >= end && now < start) {
                    return false;
                } else {
                    return true;
                }
            } else {
                if (now >= start && now < end) {
                    return true;
                } else {
                    return false;
                }
            }
        } catch (ParseException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);
        }

    }

    public static Date String2Date(String pattern, String dateStr) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        Date date = null;
        try {
            date = simpleDateFormat.parse(dateStr);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return date;
    }

    public static String Date2String(Date date, String pattern) {
        // log.info(date.toString());
        SimpleDateFormat dateFormater = new SimpleDateFormat(pattern);
        return dateFormater.format(date);
    }

    /**
     * 字符串转换成日期
     *
     * @param str
     * @return date
     */
    public static Date StrToDate(String str) {

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = format.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    public static Date getYesterDay(Date date) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, -1);// 把日期往后增加一天.整数往后推,负数往前移动
        date = calendar.getTime(); // 这个时间就是日期往后推一天的结果
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        String dateString = formatter.format(date);

        return date;
    }

    /**
     * 获取当月天数
     *
     * @return
     */
    public static int getNowMonthDay() {
        Calendar d = Calendar.getInstance();
        return d.getActualMaximum(Calendar.DATE);
    }

    /**
     * date2比date1多的天数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int differentDays(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        int day1 = cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if (year1 != year2) // 同一年
        {
            int timeDistance = 0;
            for (int i = year1; i < year2; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) // 闰年
                {
                    timeDistance += 366;
                } else // 不是闰年
                {
                    timeDistance += 365;
                }
            }

            return timeDistance + (day2 - day1);
        } else // 不同年
        {
            log.info("判断day2 - day1 : " + (day2 - day1));
            return day2 - day1;
        }
    }

    public static String dateStringArithmetic(int type, int num, String format, String date) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date1 = null;
        try {
            date1 = sdf.parse(date);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(date1);
        rightNow.add(type, num);
        return sdf.format(rightNow.getTime());
    }

    // 将18：00等时间类型拼接当天时间变为2018-05-09 18：00：00 并转为long类型
    public static long hourOrMinuterToDate(String time) {
        long datetime = 0L;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 小写的mm表示的是分钟
            Date date = new Date();
            String[] split = sdf.format(date).toString().split(" ");
            String data = split[0];
            String[] times = time.split(":");
            String dateTime = null;
            if (times.length > 1) {
                dateTime = data + " " + time + ":00";
            } else {
                dateTime = data + " " + times[0] + ":00:00";
            }
            datetime = sdf.parse(dateTime).getTime();

        } catch (Exception e) {
            // TODO: handle exception
        }
        return datetime;
    }

    // 使用当前月份,得到上一个月的月份:月份的格式是:yyyy-MM
    public static String getLastDate(String currentDate) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(currentDate + "-" + "01");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MONTH, -1);
        String lastDate = c.get(Calendar.YEAR) + "-" + (c.get(Calendar.MONTH) + 1);
        return lastDate;
    }

    //	public static int differentDaysByMillisecond(Date date1, Date date2) {
//		long between = date2.getTime() - date1.getTime();
//		int day = (int) between / (24 * 60 * 60 * 1000);
//		int hour = (int) (between / (60 * 60 * 1000) - day * 24);
//		int min = (int) ((between / (60 * 1000)) - day * 24 * 60 - hour * 60);
//		return day * 24 * 60 + hour * 60 + min;
//	}
    //获取几分钟之前或之后
    public static String getTimeByMinute(String time, int minute) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = sdf.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minute);
        return sdf.format(calendar.getTime());

    }


    public static int differentDaysByMillisecond(Date begin, Date end) {
        int days = (int) ((end.getTime() - begin.getTime()) / (1000 * 3600 * 24));
        return days;
    }

    public static Date parseStringToDate(String date) {
        Date result = null;
        try {
            String parse = date;
            parse = parse.replaceFirst("^[0-9]{4}([^0-9]?)", "yyyy$1");
            parse = parse.replaceFirst("^[0-9]{2}([^0-9]?)", "yy$1");
            parse = parse.replaceFirst("([^0-9]?)[0-9]{1,2}([^0-9]?)", "$1MM$2");
            parse = parse.replaceFirst("([^0-9]?)[0-9]{1,2}( ?)", "$1dd$2");
            parse = parse.replaceFirst("( )[0-9]{1,2}([^0-9]?)", "$1HH$2");
            parse = parse.replaceFirst("([^0-9]?)[0-9]{1,2}([^0-9]?)", "$1mm$2");
            parse = parse.replaceFirst("([^0-9]?)[0-9]{1,2}([^0-9]?)", "$1ss$2");
            //log.info(parse);
            DateFormat format = new SimpleDateFormat(parse);
            result = format.parse(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 和当前时间比较大小，比当前日期小返回-1，相等返回 0  比当前日期大 返回1
     *
     * @param t1
     * @return
     */
    public static int timeCompare(String t1) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        String t2 = formatter.format(new Date());
        try {
            c1.setTime(formatter.parse(t1));
            c2.setTime(formatter.parse(t2));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        int result = c1.compareTo(c2);
        return result;
    }

    public static void main(String[] args) {
        log.info("{}", timeCompare("2020-06-05"));
        log.info("{}", timeCompare("2020-06-03"));
        log.info("{}", timeCompare("2020-06-08"));
    }

    public static List<String> getDayBetweenDates(String begin, String end) {
        List<String> lDate = new ArrayList<String>();
        try {
            SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
            Date dBegin = sd.parse(begin);
            Date dEnd = sd.parse(end);
            if (dEnd.getTime() > dBegin.getTime()) {
                lDate.add(sd.format(dBegin));
                Calendar calBegin = Calendar.getInstance();
                // 使用给定的 Date 设置此 Calendar 的时间
                calBegin.setTime(dBegin);
                Calendar calEnd = Calendar.getInstance();
                // 使用给定的 Date 设置此 Calendar 的时间
                calEnd.setTime(dEnd);
                // 测试此日期是否在指定日期之后
                while (dEnd.after(calBegin.getTime())) {
                    // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
                    calBegin.add(Calendar.DAY_OF_MONTH, 1);
                    lDate.add(sd.format(calBegin.getTime()));
                }
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return lDate;
    }

    public static int getdayForWeek(String pTime) {
        int dayForWeek = 0;
        try {
            SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
            Calendar c = Calendar.getInstance();
            c.setTime(sd.parse(pTime));
            if (c.get(Calendar.DAY_OF_WEEK) == 1) {
                dayForWeek = 7;
            } else {
                dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return dayForWeek;
    }

}
