package org.jeecg.common.util;

import org.springframework.util.StringUtils;

import java.beans.PropertyEditorSupport;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 类描述：时间操作定义类
 *
 * @Author: 张代浩
 * @Date:2012-12-8 12:15:03
 * @Version 1.0
 */
public class DateUtils extends PropertyEditorSupport {
    /**
     * 以毫秒表示的时间
     */
    private static final long DAY_IN_MILLIS = 24 * 3600 * 1000;
    private static final long HOUR_IN_MILLIS = 3600 * 1000;
    private static final long MINUTE_IN_MILLIS = 60 * 1000;
    private static final long SECOND_IN_MILLIS = 1000;

    /**
     * 指定模式的时间格式
     *
     * @param pattern
     * @return
     */
    private static SimpleDateFormat getDateFormat(String pattern) {
        return new SimpleDateFormat(pattern);
    }

    /**
     * 当前日历，这里用中国时间表示
     *
     * @return 以当地时区表示的系统当前日历
     */
    public static Calendar getCalendar() {
        return Calendar.getInstance();
    }

    /**
     * 指定毫秒数表示的日历
     *
     * @param millis 毫秒数
     * @return 指定毫秒数表示的日历
     */
    public static Calendar getCalendar(long millis) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date(millis));
        return cal;
    }

    // ////////////////////////////////////////////////////////////////////////////
    // getDate
    // 各种方式获取的Date
    // ////////////////////////////////////////////////////////////////////////////

    /**
     * 当前日期
     *
     * @return 系统当前时间
     */
    public static Date getDate() {
        return new Date();
    }

    /**
     * 字符串转换成日期
     *
     * @param str
     * @param sdf
     * @return
     */
    public static Date str2Date(String str, SimpleDateFormat sdf) {
        if (null == str || "".equals(str)) {
            return null;
        }
        Date date = null;
        try {
            date = sdf.parse(str);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 日期转换为字符串
     *
     * @return 字符串
     */
    public static String date2Str() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = getDate();
        if (null == date) {
            return null;
        }
        return format.format(date);
    }

    /**
     * 格式化时间
     *
     * @param date
     * @param format
     * @return
     */
    public static String dateformat(String date, String format) {
        SimpleDateFormat sformat = new SimpleDateFormat(format);
        Date getDate = null;
        try {
            getDate = sformat.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return sformat.format(getDate);
    }

    /**
     * 日期转换为字符串
     *
     * @param format 日期格式
     * @return 字符串
     */
    public static String getDate(String format) {
        Date date = new Date();
        if (null == date) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     * 指定毫秒数的时间戳
     *
     * @param millis 毫秒数
     * @return 指定毫秒数的时间戳
     */
    public static Timestamp getTimestamp(long millis) {
        return new Timestamp(millis);
    }

    /**
     * 以字符形式表示的时间戳
     *
     * @param time 毫秒数
     * @return 以字符形式表示的时间戳
     */
    public static Timestamp getTimestamp(String time) {
        return new Timestamp(Long.parseLong(time));
    }

    /**
     * 系统当前的时间戳
     *
     * @return 系统当前的时间戳
     */
    public static Timestamp getTimestamp() {
        return new Timestamp(System.currentTimeMillis());
    }

    /**
     * 当前时间，格式 yyyy-MM-dd HH:mm:ss
     *
     * @return 当前时间的标准形式字符串
     */
    public static String now() {
        SimpleDateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return datetimeFormat.format(getCalendar().getTime());
    }

    /**
     * 指定日期的时间戳
     *
     * @param date 指定日期
     * @return 指定日期的时间戳
     */
    public static Timestamp getTimestamp(Date date) {
        return new Timestamp(date.getTime());
    }

    /**
     * 指定日历的时间戳
     *
     * @param cal 指定日历
     * @return 指定日历的时间戳
     */
    public static Timestamp getCalendarTimestamp(Calendar cal) {
        return new Timestamp(cal.getTime().getTime());
    }

    public static Timestamp gettimestamp() {
        Date dt = new Date();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowTime = df.format(dt);
        java.sql.Timestamp buydate = java.sql.Timestamp.valueOf(nowTime);
        return buydate;
    }

    // ////////////////////////////////////////////////////////////////////////////
    // getMillis
    // 各种方式获取的Millis
    // ////////////////////////////////////////////////////////////////////////////

    /**
     * 系统时间的毫秒数
     *
     * @return 系统时间的毫秒数
     */
    public static long getMillis() {
        return System.currentTimeMillis();
    }

    /**
     * 指定日历的毫秒数
     *
     * @param cal 指定日历
     * @return 指定日历的毫秒数
     */
    public static long getMillis(Calendar cal) {
        return cal.getTime().getTime();
    }

    /**
     * 指定日期的毫秒数
     *
     * @param date 指定日期
     * @return 指定日期的毫秒数
     */
    public static long getMillis(Date date) {
        return date.getTime();
    }

    /**
     * 指定时间戳的毫秒数
     *
     * @param ts 指定时间戳
     * @return 指定时间戳的毫秒数
     */
    public static long getMillis(Timestamp ts) {
        return ts.getTime();
    }

    // ////////////////////////////////////////////////////////////////////////////
    // formatDate
    // 将日期按照一定的格式转化为字符串
    // ////////////////////////////////////////////////////////////////////////////

    /**
     * 默认方式表示的系统当前日期，具体格式：年-月-日
     *
     * @return 默认日期按“年-月-日“格式显示
     */
    public static String formatDate() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(getCalendar().getTime());
    }

    /**
     * 默认方式表示的系统当前日期，具体格式：yyyy-MM-dd HH:mm:ss
     *
     * @return 默认日期按“yyyy-MM-dd HH:mm:ss“格式显示
     */
    public static String formatDateTime() {
        SimpleDateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return datetimeFormat.format(getCalendar().getTime());
    }

    /**
     * 指定日期的默认显示，具体格式：年-月-日
     *
     * @param cal 指定的日期
     * @return 指定日期按“年-月-日“格式显示
     */
    public static String formatDate(Calendar cal) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(cal.getTime());
    }

    /**
     * 指定日期的默认显示，具体格式：年-月-日
     *
     * @param date 指定的日期
     * @return 指定日期按“年-月-日“格式显示
     */
    public static String formatDate(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(date);
    }

    /**
     * 指定毫秒数表示日期的默认显示，具体格式：年-月-日
     *
     * @param millis 指定的毫秒数
     * @return 指定毫秒数表示日期按“年-月-日“格式显示
     */
    public static String formatDate(long millis) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(new Date(millis));
    }

    /**
     * 默认日期按指定格式显示
     *
     * @param pattern 指定的格式
     * @return 默认日期按指定格式显示
     */
    public static String formatDate(String pattern) {
        return getDateFormat(pattern).format(getCalendar().getTime());
    }

    /**
     * 指定日期按指定格式显示
     *
     * @param cal     指定的日期
     * @param pattern 指定的格式
     * @return 指定日期按指定格式显示
     */
    public static String formatDate(Calendar cal, String pattern) {
        return getDateFormat(pattern).format(cal.getTime());
    }

    /**
     * 指定日期按指定格式显示
     *
     * @param date    指定的日期
     * @param pattern 指定的格式
     * @return 指定日期按指定格式显示
     */
    public static String formatDate(Date date, String pattern) {
        return getDateFormat(pattern).format(date);
    }

    // ////////////////////////////////////////////////////////////////////////////
    // formatTime
    // 将日期按照一定的格式转化为字符串
    // ////////////////////////////////////////////////////////////////////////////

    /**
     * 默认方式表示的系统当前日期，具体格式：年-月-日 时：分
     *
     * @return 默认日期按“年-月-日 时：分“格式显示
     */
    public static String formatTime() {
        SimpleDateFormat timeSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        return timeSdf.format(getCalendar().getTime());
    }

    /**
     * 指定毫秒数表示日期的默认显示，具体格式：年-月-日 时：分
     *
     * @param millis 指定的毫秒数
     * @return 指定毫秒数表示日期按“年-月-日 时：分“格式显示
     */
    public static String formatTime(long millis) {
        SimpleDateFormat timeSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        return timeSdf.format(new Date(millis));
    }

    /**
     * 指定日期的默认显示，具体格式：年-月-日 时：分
     *
     * @param cal 指定的日期
     * @return 指定日期按“年-月-日 时：分“格式显示
     */
    public static String formatTime(Calendar cal) {
        SimpleDateFormat timeSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        return timeSdf.format(cal.getTime());
    }

    /**
     * 指定日期的默认显示，具体格式：年-月-日 时：分
     *
     * @param date 指定的日期
     * @return 指定日期按“年-月-日 时：分“格式显示
     */
    public static String formatTime(Date date) {
        SimpleDateFormat timeSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        return timeSdf.format(date);
    }

    // ////////////////////////////////////////////////////////////////////////////
    // formatShortTime
    // 将日期按照一定的格式转化为字符串
    // ////////////////////////////////////////////////////////////////////////////

    /**
     * 默认方式表示的系统当前日期，具体格式：时：分
     *
     * @return 默认日期按“时：分“格式显示
     */
    public static String formatShortTime() {
        SimpleDateFormat shortTimeSdf = new SimpleDateFormat("HH:mm");
        return shortTimeSdf.format(getCalendar().getTime());
    }

    /**
     * 指定毫秒数表示日期的默认显示，具体格式：时：分
     *
     * @param millis 指定的毫秒数
     * @return 指定毫秒数表示日期按“时：分“格式显示
     */
    public static String formatShortTime(long millis) {
        SimpleDateFormat shortTimeSdf = new SimpleDateFormat("HH:mm");
        return shortTimeSdf.format(new Date(millis));
    }

    /**
     * 指定日期的默认显示，具体格式：时：分
     *
     * @param cal 指定的日期
     * @return 指定日期按“时：分“格式显示
     */
    public static String formatShortTime(Calendar cal) {
        SimpleDateFormat shortTimeSdf = new SimpleDateFormat("HH:mm");
        return shortTimeSdf.format(cal.getTime());
    }

    /**
     * 指定日期的默认显示，具体格式：时：分
     *
     * @param date 指定的日期
     * @return 指定日期按“时：分“格式显示
     */
    public static String formatShortTime(Date date) {
        SimpleDateFormat shortTimeSdf = new SimpleDateFormat("HH:mm");
        return shortTimeSdf.format(date);
    }

    // ////////////////////////////////////////////////////////////////////////////
    // parseDate
    // parseCalendar
    // parseTimestamp
    // 将字符串按照一定的格式转化为日期或时间
    // ////////////////////////////////////////////////////////////////////////////

    /**
     * 根据指定的格式将字符串转换成Date 如输入：2003-11-19 11:20:20将按照这个转成时间
     *
     * @param src     将要转换的原始字符窜
     * @param pattern 转换的匹配格式
     * @return 如果转换成功则返回转换后的日期
     * @throws ParseException
     * @throws
     */
    public static Date parseDate(String src, String pattern) throws ParseException {
        return getDateFormat(pattern).parse(src);

    }

    /**
     * 根据指定的格式将字符串转换成Date 如输入：2003-11-19 11:20:20将按照这个转成时间
     *
     * @param src     将要转换的原始字符窜
     * @param pattern 转换的匹配格式
     * @return 如果转换成功则返回转换后的日期
     * @throws ParseException
     * @throws
     */
    public static Calendar parseCalendar(String src, String pattern) throws ParseException {

        Date date = parseDate(src, pattern);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal;
    }

    public static String formatAddDate(String src, String pattern, int amount) throws ParseException {
        Calendar cal;
        cal = parseCalendar(src, pattern);
        cal.add(Calendar.DATE, amount);
        return formatDate(cal);
    }

    /**
     * 根据指定的格式将字符串转换成Date 如输入：2003-11-19 11:20:20将按照这个转成时间
     *
     * @param src     将要转换的原始字符窜
     * @param pattern 转换的匹配格式
     * @return 如果转换成功则返回转换后的时间戳
     * @throws ParseException
     * @throws
     */
    public static Timestamp parseTimestamp(String src, String pattern) throws ParseException {
        Date date = parseDate(src, pattern);
        return new Timestamp(date.getTime());
    }

    // ////////////////////////////////////////////////////////////////////////////
    // dateDiff
    // 计算两个日期之间的差值
    // ////////////////////////////////////////////////////////////////////////////

    /**
     * 计算两个时间之间的差值，根据标志的不同而不同
     *
     * @param flag   计算标志，表示按照年/月/日/时/分/秒等计算
     * @param calSrc 减数
     * @param calDes 被减数
     * @return 两个日期之间的差值
     */
    public static int dateDiff(char flag, Calendar calSrc, Calendar calDes) {

        long millisDiff = getMillis(calSrc) - getMillis(calDes);

        if (flag == 'y') {
            return (calSrc.get(Calendar.YEAR) - calDes.get(Calendar.YEAR));
        }

        if (flag == 'd') {
            return (int) (millisDiff / DAY_IN_MILLIS);
        }

        if (flag == 'h') {
            return (int) (millisDiff / HOUR_IN_MILLIS);
        }

        if (flag == 'm') {
            return (int) (millisDiff / MINUTE_IN_MILLIS);
        }

        if (flag == 's') {
            return (int) (millisDiff / SECOND_IN_MILLIS);
        }

        return 0;
    }

    public static Map<String, Object> getStartEndTime(String createTime) throws ParseException {

        SimpleDateFormat smf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date parse = smf.parse(createTime);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(parse);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date start = calendar.getTime();
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        calendar.add(Calendar.SECOND, -1);
        Date end = calendar.getTime();
        Map<String, Object> map = new HashMap<>();
        map.put("start", smf.format(start));
        map.put("end", smf.format(end));
        return map;
    }

    public static String getQuarterStartDate(Date date) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        Integer month = calendar.get(Calendar.MONTH);
        Integer compare = month % 3;
        calendar.add(Calendar.MONTH, -compare);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        Date getDate = calendar.getTime();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return dateFormat.format(getDate);
    }

    public static String getQuarterEndDate(Date date) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        Integer month = calendar.get(Calendar.MONTH);
        Integer compare = month % 3;
        calendar.add(Calendar.MONTH, (3 - compare));
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        Date getDate = calendar.getTime();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return dateFormat.format(getDate);
    }
    /**
     * String类型 转换为Date, 如果参数长度为10 转换格式”yyyy-MM-dd“ 如果参数长度为19 转换格式”yyyy-MM-dd
     * HH:mm:ss“ * @param text String类型的时间值
     */
    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (StringUtils.hasText(text)) {
            try {
                if (text.indexOf(":") == -1 && text.length() == 10) {
                    setValue(format.parse(text));
                } else if (text.indexOf(":") > 0 && text.length() == 19) {
                    setValue(datetimeFormat.parse(text));
                } else {
                    throw new IllegalArgumentException("Could not parse date, date format is error ");
                }
            } catch (ParseException ex) {
                IllegalArgumentException iae = new IllegalArgumentException("Could not parse date: " + ex.getMessage());
                iae.initCause(ex);
                throw iae;
            }
        } else {
            setValue(null);
        }
    }

    public static int getYear(Date date) {
        GregorianCalendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }


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

    public static List<Map<String, String>> getDateDayRange(String startDate, String endDate) throws ParseException {
        List<Map<String, String>> list = new ArrayList<>();
        String splitDate = DateUtils.addDay(endDate, -1);
        splitDate = DateUtils.addDay(splitDate, 1);
        if (DateUtils.compareDate(startDate, splitDate) >= 0) {
            Map<String, String> map = new HashMap<String, String>();
            map.put("startDate", startDate);
            map.put("endDate", endDate);
            list.add(map);
        } else {
            while (DateUtils.compareDate(startDate, splitDate) < 0 || DateUtils.compareDate(startDate, endDate) <= 0) {
                Map<String, String> map = new HashMap<String, String>();
                map.put("startDate", splitDate);
                map.put("endDate", endDate);
                list.add(map);
                splitDate = DateUtils.addDay(splitDate, -1);
                endDate = DateUtils.addDay(endDate, -1);
                if (DateUtils.compareDate(startDate, splitDate) > 0) {
                    splitDate = startDate;
                }
            }
        }
        return list;
    }

    public static List<Map<String, String>> getDateWeekRange(String startDate, String endDate) throws ParseException {
        List<Map<String, String>> list = new ArrayList<Map<String, String>>();
        String splitDate = DateUtils.addWeek(endDate, -1);
        splitDate = DateUtils.addDay(splitDate, 1);
        if (DateUtils.compareDate(startDate, splitDate) >= 0) {
            Map<String, String> map = new HashMap<String, String>();
            map.put("startDate", startDate);
            map.put("endDate", endDate);
            list.add(map);
        } else {
            while (DateUtils.compareDate(startDate, splitDate) < 0 || DateUtils.compareDate(startDate, endDate) <= 0) {
                Map<String, String> map = new HashMap<String, String>();
                map.put("startDate", splitDate);
                map.put("endDate", endDate);
                list.add(map);
                splitDate = DateUtils.addWeek(splitDate, -1);
                endDate = DateUtils.addWeek(endDate, -1);
                if (DateUtils.compareDate(startDate, splitDate) > 0) {
                    splitDate = startDate;
                }
            }
        }
        return list;
    }

    public static List<Map<String, String>> getDateMonthRange(String startDate, String endDate) throws ParseException {
        List<Map<String, String>> list = new ArrayList<Map<String, String>>();
        String splitDate = DateUtils.addMonth(endDate, -1);
        splitDate = DateUtils.addDay(splitDate, 1);
        if (DateUtils.compareDate(startDate, splitDate) >= 0) {
            Map<String, String> map = new HashMap<String, String>();
            map.put("startDate", startDate);
            map.put("endDate", endDate);
            list.add(map);
        } else {
            while (DateUtils.compareDate(startDate, splitDate) < 0 || DateUtils.compareDate(startDate, endDate) <= 0) {
                Map<String, String> map = new HashMap<String, String>();
                map.put("startDate", splitDate);
                map.put("endDate", endDate);
                list.add(map);
                splitDate = DateUtils.addMonth(splitDate, -1);
                endDate = DateUtils.addMonth(endDate, -1);
                if (DateUtils.compareDate(startDate, splitDate) > 0) {
                    splitDate = startDate;
                }
            }
        }
        return list;
    }

    public static String addMonth(String dateString, int month) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = sdf.parse(dateString);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, month);
        return sdf.format(calendar.getTime());
    }

    public static String addWeek(String dateString, int week) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = sdf.parse(dateString);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.WEEK_OF_YEAR, week);
        return sdf.format(calendar.getTime());
    }

    public static String addDay(String dateString, int day) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = sdf.parse(dateString);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR, day);
        return sdf.format(calendar.getTime());
    }

    public static Date addDay(Date date, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR, day);
        return calendar.getTime();
    }

    public static Date addSecond(Date date, int seconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.SECOND, seconds);
        return calendar.getTime();
    }

    public static int compareDate(String firstDateString, String secondDateString) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date firstDate = sdf.parse(firstDateString);
        Date secondDate = sdf.parse(secondDateString);
        long first = firstDate.getTime();
        long second = secondDate.getTime();
        return first == second ? 0 : (first > second ? 1 : -1);
    }

    public static String timeStamp2Date(Timestamp timeLong) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date;
        try {
            date = sdf.parse(sdf.format(timeLong));
            return sdf.format(date);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String timeStamp2Date(long currentTimeMillis) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date;
        try {
            date = sdf.parse(sdf.format(currentTimeMillis));
            return sdf.format(date);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }


    public static Map<String, Object> getBeforeDate() {
        Date dNow = new Date();
        Date dBefore = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dNow);
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        dBefore = calendar.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String defaultStartDate = sdf.format(dBefore);
        defaultStartDate = defaultStartDate + " 00:00:00";
        String defaultEndDate = defaultStartDate.substring(0, 10) + " 23:59:59";
        Map<String, Object> map = new HashMap<>();
        map.put("startDate", defaultStartDate);
        map.put("endDate", defaultEndDate);
        return map;
    }


    /**
     * @param format 返回日期格式
     * @param date   传入的初始日期
     * @param num    天数
     * @return
     * @throws ParseException
     */
    public static String getAnotherDay(String format, String date, Integer num) throws ParseException {

        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date getDate = sdf.parse(date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(getDate);
        calendar.add(Calendar.DAY_OF_MONTH, num);
        Date resultDate = calendar.getTime();
        return sdf.format(resultDate);
    }


    public static String getNowDate(String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date = new Date();
        return sdf.format(date);
    }


    public static String getMonthBefore(String format, String nowTime, int amount) throws ParseException {
        // 获取当前时间
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        Date date = dateFormat.parse(nowTime);

        //得到日历
        Calendar calendar = Calendar.getInstance();
        //把当前时间赋给日历
        calendar.setTime(date);
        //设置为前2月，可根据需求进行修改
        calendar.add(Calendar.MONTH, amount);
        //获取2个月前的时间
        date = calendar.getTime();

        return dateFormat.format(date);
    }

    public static Map<String, Object> compareDate(String format, String date1, String date2) {


        DateFormat df = new SimpleDateFormat(format);
        Map<String, Object> map = new HashMap<>();
        try {
            Date dt1 = df.parse(date1);
            Date dt2 = df.parse(date2);
            if (dt1.getTime() > dt2.getTime()) {
                map.put("bigDate", date1);
                map.put("smallDate", date2);
                return map;
            } else if (dt1.getTime() < dt2.getTime()) {
                map.put("bigDate", date2);
                map.put("smallDate", date1);
                return map;
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return null;
    }

    /**
     * 日期中获取年份
     *
     * @param format
     * @param date
     * @return
     * @throws ParseException
     */
    public static String getYear(String format, String date) throws ParseException {

        SimpleDateFormat df = new SimpleDateFormat(format);
        Date parse = df.parse(date);
        return String.format("%tY", parse);

    }

    /**
     * 日期中获取月份
     *
     * @param format
     * @param date
     * @return
     * @throws ParseException
     */
    public static String getMonth(String format, String date) throws ParseException {
        SimpleDateFormat df = new SimpleDateFormat(format);
        Date parse = df.parse(date);
        return String.format("%tm", parse);
    }

    /**
     * 日期中获取天
     *
     * @param format
     * @param date
     * @return
     * @throws ParseException
     */
    public static String getDay(String format, String date) throws ParseException {

        SimpleDateFormat df = new SimpleDateFormat(format);
        Date parse = df.parse(date);
        return String.format("%td", parse);
    }

    /**
     * 根据时间获取季度
     * 1即Q1（1，2，3月），以此类推
     * @param date
     * @return
     */
    public static int getQuarter(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        //获取当前月份
        int month = cal.get(Calendar.MONTH) + 1;
        if(month<=3){
            return 1;
        }else if(month <=6){
            return 2;
        }else if(month<=9){
            return 3;
        }else if(month<=12){
            return 4;
        }

        return 0;
    }

    /**
     * 获取【所在周】周五的时间（周五为一周第一天，周四为一周最后一天）
     * @param date
     */
    public static Date getFriday(Date date){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.setFirstDayOfWeek(Calendar.FRIDAY);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        System.out.println(df.format(calendar.getTime()));
        return calendar.getTime();
    }

    /**
     * 获取传入时间的年、月份和季度（周五为每周第一天，周四为每周最后一天）
     * 获取的是所属年、月、季度，因为很多月份的第一周或最后 一周会包括上一个月或者下一个月的部分日期
     */
    public static Map<String,Integer> getYearQuarter(Date date){
        Map<String,Integer> dateMap = new HashMap<>();

        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        int originYear = calendar.get(Calendar.YEAR);
        int originMonth = calendar.get(Calendar.MONTH);
        int originQuarter = DateUtils.getQuarter(date); //本月所在季度（按照日期来的）

        Calendar calendar1 = new GregorianCalendar();
        calendar1.setTime(date);
        calendar1.setFirstDayOfWeek(Calendar.FRIDAY);
        //1.判断当天所在周第一天是否跨月
        calendar1.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
        int fridayYear = calendar1.get(Calendar.YEAR);
        int fridayMonth = calendar1.get(Calendar.MONTH);
        int fridayQuarter = DateUtils.getQuarter(calendar1.getTime());

        //2.判断当天所在周的最后一天是否跨月
        Calendar calendar2 = new GregorianCalendar();
        calendar2.setTime(date);
        calendar2.setFirstDayOfWeek(Calendar.FRIDAY);
        calendar2.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);
        int thursdayYear = calendar2.get(Calendar.YEAR);
        int thursdayMonth = calendar2.get(Calendar.MONTH);
        int thursdayQuarter = DateUtils.getQuarter(calendar2.getTime());

        //如果本周第一天（周五）和当前天不在一个月内，说明周跨月了
        if(fridayMonth == originMonth && thursdayMonth == originMonth){
            dateMap.put("year", originYear);
            dateMap.put("month", originMonth + 1);  //最后一个月是11，应该+1
            dateMap.put("quarter", originQuarter);
            return dateMap;
        }else if(fridayYear < originYear || (fridayYear ==originYear && fridayMonth < originMonth) ){
            //判断本周有几天在本月,如果是（5，6，7）则就是本月本季度
            //int lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
            calendar1.set(Calendar.DATE, calendar1.getActualMaximum(Calendar.DATE));
            int lastDateWeek = calendar1.get(Calendar.DAY_OF_WEEK);
            //判断如果本周所在上个月的最后一天是周五、周六、周日的话，说明本周归属于本月（周五是第一天）；否则本周归属于上个季度
            if(lastDateWeek ==6 || lastDateWeek ==7 || lastDateWeek ==1 ){
                dateMap.put("year", originYear);
                dateMap.put("month", originMonth + 1);
                dateMap.put("quarter",originQuarter);
            }else{
                //判断如果本周属于上个月，判断是否跨年
                if(originYear == fridayYear){
                    dateMap.put("year", originYear);
                    dateMap.put("month", originMonth);
                    //判断是否跨季
                    if(originQuarter == fridayQuarter){
                        dateMap.put("quarter",originQuarter);
                    }else{
                        dateMap.put("quarter",fridayQuarter);
                    }
                }else{
                    //跨年的话说明这周上年的12月（第四季度）
                    dateMap.put("year", originYear-1);
                    dateMap.put("month", 12); //??查看是11，还是12
                    dateMap.put("quarter",4);
                }
            }
            return dateMap;
        }else if(originYear < thursdayYear || (originYear == thursdayYear && originMonth < thursdayMonth) ){
            calendar2.set(Calendar.DATE, 1);
            int firstDateWeek = calendar2.get(Calendar.DAY_OF_WEEK);
            //如果跨月的第一天是周二周三周四的话说明这周不跨月，否在进入下个月（季度、年需要再判断）
            if( firstDateWeek==3 || firstDateWeek==4 || firstDateWeek==5){
                dateMap.put("year", originYear);
                dateMap.put("month", originMonth+1);
                dateMap.put("quarter",originQuarter);
            }else{
                if( originYear == thursdayYear ){
                    dateMap.put("year", originYear);
                    dateMap.put("month", originMonth + 1 + 1);
                    //判断是否跨季
                    if(originQuarter == thursdayQuarter){
                        dateMap.put("quarter",originQuarter);
                    }else{
                        dateMap.put("quarter",thursdayQuarter);
                    }
                }else{
                    //跨年的话说明这周属于明年的1月（第一季度）
                    dateMap.put("year", originYear+1);
                    dateMap.put("month", 1);
                    dateMap.put("quarter",1);
                }
            }
            return dateMap;
        }
        return dateMap;
    }

    /**
     * 计算季度开始、结束时间
     * 原则：周五为本周的第一天，下一周的周四为本周的最后一天
     * @param year
     * @param quarter
     */
    public static Map<String,String> quarterStartEndDate(int year, int quarter){
        Map<String,String> quarterStartEndDateMap = new HashMap<>();

        Date startDate = null;
        Date endDate = null;

        int startMonth = 0;
        int endMonth = 0;

        if(quarter == 1){
            startMonth = 1;
            endMonth = 3;
        }else if(quarter == 2){
            startMonth = 4;
            endMonth = 6;
        }else if(quarter == 3){
            startMonth = 7;
            endMonth = 9;
        }else{
            startMonth = 10;
            endMonth = 12;
        }

        //判断季度第一天的时间（以周为单位，有可能是上个月，也有可能是本月的非1号）
        Calendar calendar1 = new GregorianCalendar();
        calendar1.set(Calendar.YEAR,year);
        calendar1.set(Calendar.MONTH,startMonth-1);
        calendar1.set(Calendar.DATE,1);
        calendar1.setFirstDayOfWeek(Calendar.FRIDAY);

        //如果季度第一个月的第一天是周二周三周四，那么这周应该归属于上个季度，否则这周（包括上个月的时间）归属于这个季度
        int firstDateWeek = calendar1.get(Calendar.DAY_OF_WEEK);
        if(firstDateWeek ==5 || firstDateWeek ==3 || firstDateWeek ==4 ){
            calendar1.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);
            startDate = DateUtils.addDay(calendar1.getTime(),1);
        }else{
            calendar1.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
            startDate = calendar1.getTime();
        }

        //判断季度最后一天的时间（以周为单位，有可能是下个月，也有可能是本月的非最后一天）
        Calendar calendar2 = new GregorianCalendar();
        calendar2.set(Calendar.YEAR,year);
        calendar2.set(Calendar.MONTH,endMonth-1);
        calendar2.set(Calendar.DATE,1);
        calendar2.setFirstDayOfWeek(Calendar.FRIDAY);

        //如果一个季度最后一个月最后一天是周五、周六、周日，则这个月最后一周属于下个季度
        calendar2.set(Calendar.DATE, calendar2.getActualMaximum(Calendar.DATE));
        int lastDateWeek = calendar2.get(Calendar.DAY_OF_WEEK);
        if(lastDateWeek ==1 || lastDateWeek ==7 || lastDateWeek ==6){
            calendar2.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
            endDate = DateUtils.addDay(calendar2.getTime(),-1);
        }else{
            calendar2.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);
            endDate = calendar2.getTime();
        }

        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        quarterStartEndDateMap.put("startDate", sdf.format(startDate));
        quarterStartEndDateMap.put("endDate", sdf.format(endDate));
        return quarterStartEndDateMap;
    }

    public static void main(String[] args) throws ParseException {
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        //Date friDay = DateUtils.getFriday(new Date());
        //Date effiCalcStart = DateUtils.addDay(friDay,  -14);
        //System.out.println(sdf.format(effiCalcStart));
        //Date effiCalcEnd = DateUtils.addDay(friDay,  -1);
        //System.out.println(sdf.format(effiCalcEnd));
        //
        //Date effiEnd = DateUtils.addDay(friDay,  -21);
        //System.out.println(sdf.format(effiEnd));
        //Date effiStart = DateUtils.addDay(friDay,  -15);
        //System.out.println(sdf.format(effiStart));

        Map<String,Integer> map1 = DateUtils.getYearQuarter(DateUtils.parseDate("2020-04-01","yyyy-MM-dd"));

        Map<String,String> map2 = DateUtils.quarterStartEndDate(2019,1);

        for(String key:map2.keySet()){
            System.out.println(key + ":" + map2.get(key));
        }



    }

}



