package com.iotechn.unimall.admin.utils;

import org.apache.commons.lang3.StringUtils;
import freemarker.core.ParseException;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

public class DateUtils {


    /**
     * 格式化日期对象
     */
    private static SimpleDateFormat format;

    /**
     * 日期格式【yyyyMMddHHmmssSSS】
     */
    public static final String PATTERN_YYYY_MM_DD_HH_MM_SS_SSS = "yyyyMMddHHmmssSSS";
    /**
     * 日期格式【yyyyMMddHHmmss】
     */
    public static final String PATTERN_YYYY_MM_DD_HH_MM_SS = "yyyyMMddHHmmss";
    /**
     * 日期格式【yyMMdd】
     */
    public static final String PATTERN_YY_MM_DD = "yyMMdd";

    /**
     * 日期格式： yyyy
     */
    public static final String DATE_FMT_YYYY = "yyyy";

    /**
     * 日期格式： MM
     */
    public static final String DATE_FMT_MM = "MM";

    /**
     * 日期格式： yyyyMM
     */
    public static final String DATE_FMT_YYYYMM_NS = "yyyyMM";

    /**
     * 日期格式： yyyy/MM/dd
     */
    public static final String DATE_FMT_YYYYMMDD = "yyyy/MM/dd";
    /**
     * 日期格式： dd/MM/yyyy
     */
    public static final String DATE_FMT_DDMMYYYY = "dd/MM/yyyy";

    /**
     * 日期格式： yyyyMMdd
     */
    public static final String DATE_FMT_YYYYMMDD_NS = "yyyyMMdd";

    /**
     * 日期格式： yyyy/MM/dd HH:mm:ss
     */
    public static final String DATE_FMT_YYYYMMDDHHMMSS = "yyyy/MM/dd HH:mm:ss";

    /**
     * 日期格式：yyyy-MM-dd
     */
    public static final String DATE_FMT_YYYY_MM_DD = "yyyy-MM-dd";
    /**
     * 日期格式：yyyy.MM.dd
     */
    public static final String DATE_FMT_YYYY_MM_DD_DD = "yyyy.MM.dd";

    /**
     * 日期格式：yyyy-MM
     */
    public static final String DATE_FMT_YYYY_MM = "yyyy-MM";

    /**
     * 日期格式：yyyy年MM月dd日
     */
    public static final String DATE_FMT_YYYY_MM_DD2 = "yyyy年MM月dd日";

    /**
     * 日期格式：yyyy年MM月dd日hh时
     */
    public static final String DATE_FMT_YYYY_MM_DD_HH = "yyyy年MM月dd日HH时";

    /**
     * 时间格式：HH:mm
     */
    public static final String TIME_HH_MM = "HH:mm";
    /**
     * 时间格式：HHmm
     */
    public static final String TIME_HHMM = "HHmm";
    /**
     * 日期时间格式：yyyy-MM-dd HH:mm
     */
    public static final String DATE_FMT_YYYYMMDDHH_MM = "yyyy-MM-dd HH:mm";
    /**
     * 日期时间格式：yyyy-MM-dd HH:mm:ss
     */
    public static final String DATE_FMT_YYYYMMDDHH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    /**
     * 日期时间格式：yyyy-MM-dd HH:mm
     */
    public static final String DATE_FMT_YYYYMMDDHHMM = "yyyy/MM/dd HHmm";
    /**
     * 日期时间格式：yyyyMMddHHmm
     */
    public static final String DATE_FMT_DATETIME = "yyyyMMddHHmm";
    /**
     * 日期时间格式： HH:mm:ss
     */
    public static final String DATE_FMT_HH_MM_SS = "HH:mm:ss";
    /**
     * 日期时间格式：dd-MM-yy
     */
    public static final String DATE_FMT_DDMMYY1 = "dd-MM-yy";

    /**
     * 取得日期字符串
     *
     * @param date    日期
     * @param pattern 日期格式
     * @return String 日期字符串
     */
    public static String formatDate(Date date, String pattern) {
        if (date == null) {
            return "";
        }
        format = new SimpleDateFormat();
        format.applyPattern(pattern);
        return format.format(date);
    }

    /**
     * 向前或是向后滚动年
     *
     * @return Date 日期
     */
    public static Date rollYear(Date date, int rollCount) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.roll(Calendar.YEAR, rollCount);
        return ca.getTime();
    }


    /**
     * 向前或者向后滚动月份 正数像前滚 负数向后滚
     *
     * @param date      准备滚动的日期
     * @param rollCount 滚动参数
     * @return Date 滚动之后的日期
     * @author gdc
     */
    public static Date rollMonth(Date date, int rollCount) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.add(Calendar.MONTH, rollCount);
        return ca.getTime();
    }

    /**
     * 向前或者向后滚动天 正数像前滚 负数向后滚
     *
     * @param date      准备滚动的日期
     * @param rollCount 滚动参数
     * @return Date 滚动之后的日期
     * @author gdc
     */
    public static Date rollDay(Date date, int rollCount) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.add(Calendar.DATE, rollCount);
        return ca.getTime();
    }

    /**
     * 时间滚动 正数像前滚 负数向后滚
     *
     * @param date      准备滚动的日期
     * @param calendar  滚动系数 年 Calendar.YEAR; 月 Calendar.MONTH; 日 Calendar.DATE; 时
     *                  Calendar.HOUR; 钟Calendar.MINUTE;
     * @param rollCount 滚动参数
     * @return Date 滚动之后的日期
     * @author gdc
     */
    public static Date rollDate(Date date, int calendar, int rollCount) {

        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.add(calendar, rollCount);
        return ca.getTime();
    }

    /**
     * 取得去年的今天
     *
     * @return String 去年的今天
     */
    public static Date getLastYearOfToday() {
        return rollYear(new Date(), -1);
    }


    /**
     * 取得当前年
     *
     * @return String 年的字符型值
     */
    public static String getYear() {
        return formatDate(new Date(), DATE_FMT_YYYY);
    }

    /**
     * 取得去年
     *
     * @return String 去年的字符型值
     */
    public static String getLastYear() {
        return formatDate(getLastYearOfToday(), DATE_FMT_YYYY);
    }

    /**
     * 取得当前年月日
     *
     * @return String 年月日的字符型值
     */
    public static String getYearMonthDay() {
        return formatDate(new Date(), DATE_FMT_YYYY_MM_DD);
    }

    /**
     * 取得去年月日
     *
     * @return String 去年月日的字符型值
     */
    public static String getLastYearMonthDay() {
        return formatDate(getLastYearOfToday(), DATE_FMT_YYYY_MM_DD);
    }

    /**
     * 判断是否是指定日期格式字符串
     *
     * @param strDate
     * @param dateFormat
     * @return
     * @author gdc
     */
    public static boolean isDate(String strDate, String dateFormat) {
        SimpleDateFormat df = new SimpleDateFormat(dateFormat);
        try {
            Date tmpDate = df.parse(strDate);
            String strTempDate = df.format(tmpDate);
            if (!strTempDate.equals(strDate)) {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 判断两日期年份月份..是否相同
     *
     * @param d1
     * @param d2
     * @param dateFmt
     * @return
     */
    public static boolean sameDate(Date d1, Date d2, String dateFmt) {
        SimpleDateFormat fmt = new SimpleDateFormat(dateFmt);
        //fmt.setTimeZone(new TimeZone()); // 如果需要设置时间区域，可以在这里设置
        return fmt.format(d1).equals(fmt.format(d2));
    }

    /**
     * 取得月份的第一天
     *
     * @param yearMonth 年月yyyy-MM
     * @return Date
     */
    public static Date getMonthFirstDay(String yearMonth) {
        String[] arr = yearMonth.split("-");

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, Integer.parseInt(arr[0]));
        cal.set(Calendar.MONTH, Integer.parseInt(arr[1]));
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.add(Calendar.DAY_OF_MONTH, -1);

        cal.set(Calendar.DAY_OF_MONTH, 1);

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

    /**
     * 取得月份的最后一天
     *
     * @param yearMonth 年月yyyy-MM
     * @return Date
     */
    public static Date getMonthLastDay(String yearMonth) {
        String[] arr = yearMonth.split("-");

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, Integer.parseInt(arr[0]));
        cal.set(Calendar.MONTH, Integer.parseInt(arr[1]));
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.add(Calendar.DAY_OF_MONTH, -1);

        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        return cal.getTime();
    }

    /**
     * 取得昨天
     *
     * @param nowDate
     * @return
     * @author gdc
     */
    public static String getYesToday(Date nowDate) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(nowDate);
        calendar.add(Calendar.DATE, -1);
        return new SimpleDateFormat(DATE_FMT_YYYY_MM_DD).format(calendar.getTime());

    }

    /**
     * 通过出生时间计算年龄
     *
     * @param birthday
     * @return
     */
    public static int getAgeByBirth(Date birthday) {
        int age = 0;
        try {
            Calendar now = Calendar.getInstance();
            now.setTime(new Date());// 当前时间

            Calendar birth = Calendar.getInstance();
            birth.setTime(birthday);

            if (birth.after(now)) {//如果传入的时间，在当前时间的后面，返回0岁
                age = 0;
            } else {
                age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
                if (now.get(Calendar.DAY_OF_YEAR) > birth.get(Calendar.DAY_OF_YEAR)) {
                    age += 1;
                }
            }
            return age;
        } catch (Exception e) {//兼容性更强,异常后返回数据
            return 0;
        }
    }

    /**
     * 日期时间格式：dd-MMM-yyyy
     */
    public static final String DATE_FMT_DDMMMYYYY = "dd-MMM-yyyy";
    /**
     * 日期时间格式：dd-MMM-yyyy
     */
    public static final String DATE_FMT_MMMYYYY = "MMM-yyyy";

    /**
     * 日期时间格式：dd-MM-yyyy
     */
    public static final String DATE_FMT_DDMMYYYY2 = "dd-MM-yyyy";
    /**
     * 日期时间格式：dd-MMM-yy
     */
    public static final String DATE_FMT_DDMMMYY2 = "dd-MMM-yy";

    // 一天的毫秒数 60*60*1000*24
    private final static long DAY_MILLIS = 86400000;

    // 一小时的毫秒数 60*60*1000
    private final static long HOUR_MILLIS = 3600000;

    // 一分钟的毫秒数 60*1000
    private final static long MINUTE_MILLIS = 60000;

    /**
     * 取得日期字符串(英文格式)
     *
     * @param date    日期
     * @param pattern 日期格式
     * @return String 日期字符串
     */
    public static String formatDateEn(Date date, String pattern) {
        if (date == null) {
            return "";
        }
        // 日期字符串格式化
        SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.ENGLISH);
        return sdf.format(date);
    }

    /**
     * 取得日期字符串
     *
     * @param date    日期
     * @param pattern 日期格式
     * @return String 日期字符串
     */
    public static String formatStringDate(String date, String pattern) {

        if (date == null) {
            return "";
        }
        DateFormat format1 = new SimpleDateFormat(pattern);
        Date dateFormat = null;
        try {
            dateFormat = format1.parse(date);
            format = new SimpleDateFormat();
            format.applyPattern(pattern);
        } catch (Exception e) {
            return "";
        }
        return format.format(dateFormat);
    }

    /**
     * 取得当前日期上个月下个月
     * 上一个月 -1
     * 下一个月 1
     *
     * @param nowDate
     * @return
     */
    public static Date getOtherMonth(Date nowDate, int number) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(nowDate); // 设置为当前时间
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + number);
        return calendar.getTime();
    }

    /**
     * 计算两个日期之间相差的天数
     *
     * @param smdate 较小的时间
     * @param bdate  较大的时间
     * @return 相差小时数
     * @throws ParseException
     */
    public static long timesBetween(Date smdate, Date bdate, String timeType) {

        long startL = smdate.getTime();
        long endL = bdate.getTime();

        if (timeType.equals("DAY")) {
            return (endL - startL) / DAY_MILLIS;
        } else if (timeType.equals("HOUR")) {
            return (endL - startL) / HOUR_MILLIS;
        } else if (timeType.equals("MINUTE")) {
            return (endL - startL) / MINUTE_MILLIS;
        } else {
            return (endL - startL);
        }

    }


    /**
     * 判断时间是上午还是下午
     * true 下午
     * false 上午
     *
     * @param date
     * @return
     */
    public static boolean greGorian(Date date) {
        boolean greGorianFlag = true;
        SimpleDateFormat df = new SimpleDateFormat("HH");
        String str = df.format(date);
        int a = Integer.parseInt(str);

        if (a < 12) {
            greGorianFlag = true;
        }
        if (a >= 12) {
            greGorianFlag = false;
        }
        return greGorianFlag;
    }

    /**
     * 获取当前月第一天
     *
     * @return
     */
    public static Date getMonthFirstDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.add(Calendar.MONTH, 0);
        return calendar.getTime();
    }

    /**
     * 获取当前月最后一天
     *
     * @return
     */
    public static Date getMonthLastDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.DAY_OF_MONTH, 0);
        calendar.add(Calendar.MONTH, 1);
        return calendar.getTime();
    }

    /**
     * 判断字符串是否为日期格式
     *
     * @return
     */
    public static boolean isValidDate(String date, String pattern) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        dateFormat.setLenient(false);
        try {
            dateFormat.parse(date);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

}
