package com.yifu.cloud.plus.v1.yifu.common.core.util;

import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.sms.MonthObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

/**
 * 日期工具类
 *
 * @author fang
 * @ClassName: DateUtil
 * @date 2017年7月10日 下午4:13:33
 */
@Slf4j
public class DateUtil {

     private DateUtil(){
          throw new IllegalStateException("DateUtil class");
     }
     /**
      * 可用时间格式
      */
     private static String[] parsePatterns = {DateUtil.DATE_PATTERN, DateUtil.ISO_EXPANDED_DATE_FORMAT, DateUtil.DATETIME_PATTERN_SECOND, DateUtil.DATETIME_PATTERN_MINUTE, DateUtil.DATETIME_PATTERN_XIEGANG,
             "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyymmdd"};
     /**
      * Base ISO 8601 Date format yyyyMMdd i.e., 20021225 for the 25th day of
      * December in the year 2002
      */
     public static final String ISO_DATE_FORMAT = "yyyyMMdd";

     /**
      * Expanded ISO 8601 Date format yyyy-MM-dd i.e., 2002-12-25 for the 25th
      * day of December in the year 2002
      */
     public static final String ISO_EXPANDED_DATE_FORMAT = "yyyy-MM-dd";
     /**
      * yyyy/MM/dd
      */
     public static final String DATETIME_PATTERN_XIEGANG = "yyyy/MM/dd";

     /**
      * yyyyMM
      */
     public static final String DATETIME_YYYYMM = "yyyyMM";
	 /**
      * yyyy
      */
     public static final String DATETIME_YYYY = "yyyy";
     /**
      * yyyy-MM
      */
     public static final String DATETIME_YYYY_MM = "yyyy-MM";
     /**
      * yyyy-MM-dd hh:mm:ss
      */
     public static final String DATETIME_PATTERN_SECOND = "yyyy-MM-dd HH:mm:ss";

     /**
      * yyyy-MM-dd hh:mm:ss
      */
     public static final String DATETIME_PATTERN_CONTAINS = "yyyyMMdd HH:mm:ss";
     /**
      * yyyy-MM-dd hh:mm:ss
      */
     public static final String DATETIME_PATTERN_MINUTE = "yyyy-MM-dd HH:mm";
     /**
      * yyyyMMddHHmmss
      */
     public static final String DATE_PATTERN = "yyyyMMddHHmmss";
     public static final String EXPORT_PATTERN = "yyyyMMdd-HHmmss";

     protected static final float normalizedJulian(float jd) {

          return Math.round(jd + 0.5f) - 0.5f;
     }

     /**
      * Returns the Date from a julian. The Julian date will be converted to noon
      * GMT, such that it matches the nearest half-integer (i.e., a julian date
      * of 1.4 gets changed to 1.5, and 0.9 gets changed to 0.5.)
      *
      * @param jd the Julian date
      * @return the Gregorian date
      */
     public static final Date toDate(float jd) {

          /*
           * To convert a Julian Day Number to a Gregorian date, assume that it is
           * for 0 hours, Greenwich time (so that it ends in 0.5). Do the
           * following calculations, again dropping the fractional part of all
           * multiplicatons and divisions. Note: This method will not give dates
           * accurately on the Gregorian Proleptic Calendar, i.e., the calendar
           * you get by extending the Gregorian calendar backwards to years
           * earlier than 1582. using the Gregorian leap year rules. In
           * particular, the method fails if Y<400.
           */
          float z = (normalizedJulian(jd)) + 0.5f;
          float w = (int) ((z - 1867216.25f) / 36524.25f);
          float x = (int) (w / 4f);
          float a = z + 1 + w - x;
          float b = a + 1524;
          float c = (int) ((b - 122.1) / 365.25);
          float d = (int) (365.25f * c);
          float e = (int) ((b - d) / 30.6001);
          float f = (int) (30.6001f * e);
          int day = (int) (b - d - f);
          int month = (int) (e - 1);

          if (month > 12) {
               month = month - 12;
          }

          int year = (int) (c - 4715);

          if (month > 2) {
               year--;
          }

          Calendar calendar = Calendar.getInstance();
          calendar.set(Calendar.YEAR, year);
          calendar.set(Calendar.MONTH, month - 1);
          calendar.set(Calendar.DATE, day);

          return calendar.getTime();
     }

     /**
      * Returns the days between two dates. Positive values indicate that the
      * second date is after the first, and negative values indicate, well, the
      * opposite. Relying on specific times is problematic.
      *
      * @param early the "first date"
      * @param late  the "second date"
      * @return the days between the two dates
      */
     public static final int daysBetween(Date early, Date late) {

          Calendar c1 = Calendar.getInstance();
          Calendar c2 = Calendar.getInstance();
          c1.setTime(early);
          c2.setTime(late);

          return daysBetween(c1, c2);
     }

     /**
      * Returns the days between two dates. Positive values indicate that the
      * second date is after the first, and negative values indicate, well, the
      * opposite.
      *
      * @param early
      * @param late
      * @return the days between two dates.
      */
     public static final int daysBetween(Calendar early, Calendar late) {

          return (int) (toJulian(late) - toJulian(early));
     }

     /**
      * Return a Julian date based on the input parameter. This is based from
      * calculations found at
      * <a href="http://quasar.as.utexas.edu/BillInfo/JulianDatesG.html">Julian
      * Day Calculations (Gregorian Calendar)</a>, provided by Bill Jeffrys.
      *
      * @param calendar a calendar instance
      * @return the julian day number
      */
     public static final float toJulian(Calendar calendar) {

          int y = calendar.get(Calendar.YEAR);
          int m = calendar.get(Calendar.MONTH);
          int d = calendar.get(Calendar.DATE);
          int a = y / 100;
          int b = a / 4;
          int c = 2 - a + b;
          float e = (int) (365.25f * (y + 4716));
          float f = (int) (30.6001f * (m + 1));
          return ((c + d + e + f) - 1524.5f);
     }

     /**
      * Return a Julian date based on the input parameter. This is based from
      * calculations found at
      * <a href="http://quasar.as.utexas.edu/BillInfo/JulianDatesG.html">Julian
      * Day Calculations (Gregorian Calendar)</a>, provided by Bill Jeffrys.
      *
      * @param date
      * @return the julian day number
      */
     public static final float toJulian(Date date) {

          Calendar c = Calendar.getInstance();
          c.setTime(date);

          return toJulian(c);
     }

     /**
      * @param isoString
      * @param fmt
      * @param field     Calendar.YEAR/Calendar.MONTH/Calendar.DATE
      * @param amount
      * @return
      * @throws ParseException
      */
     public static final String dateIncrease(String isoString, String fmt, int field, int amount) {

          try {
               Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
               cal.setTime(stringToDate2(isoString, fmt));
               cal.add(field, amount);

               return dateToString(cal.getTime(), fmt);

          } catch (Exception ex) {
               return null;
          }
     }

     /**
      * Time Field Rolling function. Rolls (up/down) a single unit of time on the
      * given time field.
      *
      * @param isoString
      * @param field     the time field.
      * @param up        Indicates if rolling up or rolling down the field value.
      *                  use formating char's
      * @throws ParseException if an unknown field value is given.
      */
     public static final String roll(String isoString, String fmt, int field, boolean up)  {

          Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
          cal.setTime(stringToDate(isoString, fmt));
          cal.roll(field, up);

          return dateToString(cal.getTime(), fmt);
     }

     /**
      * Time Field Rolling function. Rolls (up/down) a single unit of time on the
      * given time field.
      *
      * @param isoString
      * @param field     the time field.
      * @param up        Indicates if rolling up or rolling down the field value.
      * @throws ParseException if an unknown field value is given.
      */
     public static final String roll(String isoString, int field, boolean up){

          return roll(isoString, DATETIME_PATTERN_MINUTE, field, up);
     }

     /**
      * java.util.Date
      *
      * @param dateText
      * @param format
      * @return
      */
     public static Date stringToDate2(String dateText, String format) {

          if (dateText == null) {

               return null;
          }

          DateFormat df = null;

          try {

               if (format == null) {
                    df = new SimpleDateFormat();
               } else {
                    df = new SimpleDateFormat(ISO_DATE_FORMAT);
               }

               // setLenient avoids allowing dates like 9/32/2001
               // which would otherwise parse to 10/2/2001
               df.setLenient(false);
			  return df.parse( dateText.replace("/","").replace("-","")
					  .replace(CommonConstants.YEAR,"").replace(CommonConstants.MONTH,"")
					  .replace(CommonConstants.DAY,""));
          } catch (ParseException e) {

               return null;
          }
     }

     /**
      * @return Timestamp
      */
     public static java.sql.Timestamp getCurrentTimestamp() {
          return new java.sql.Timestamp(System.currentTimeMillis());
     }

     /**
      * java.util.Date
      *
      * @param dateString
      * @param format
      * @return
      */
     public static Date stringToDate(String dateString, String format) {

          return stringToDate2(dateString, format);
     }

     /**
      * 校验按指定格式是否可以转换成日期
      *
      * @param @param  dateString
      * @param @param  format
      * @param @return 参数
      * @return boolean    返回类型
      * @throws
      * @Title: checkStringToDate
      */
     public static boolean checkStringToDate(String dateString, String formatStr) {
          SimpleDateFormat format = new SimpleDateFormat(formatStr);
          try {
               format.setLenient(false);
               format.parse(dateString);
          } catch (ParseException e) {
               return false;
          }
          return true;
     }

     /**
      * java.util.Date
      *
      * @param dateString
      */
     public static Date stringToDate(String dateString) {
          return stringToDate2(dateString, ISO_EXPANDED_DATE_FORMAT);
     }
	 
	 /**
	  * @param dateString
	  * @param patten 格式
	  * @Description: 
	  * @Author: hgw
	  * @Date: 2022/7/8 12:02
	  * @return: java.util.Date
	  **/
	 public static Date stringToDateByPatten(String dateString, String patten) {
          return stringToDate2(dateString, patten);
     }

     /**
      * @param pattern
      * @param date
      * @return
      */
     public static String dateToString(Date date, String pattern) {

          if (date == null) {

               return null;
          }

          try {

               SimpleDateFormat sfDate = new SimpleDateFormat(pattern);
               sfDate.setLenient(false);

               return sfDate.format(date);
          } catch (Exception e) {

               return null;
          }
     }

     /**
      * yyyy-MM-dd
      *
      * @param date
      * @return
      */
     public static String dateToString(Date date) {
          return dateToString(date, ISO_EXPANDED_DATE_FORMAT);
     }

     /**
      * @return
      */
     public static Date getCurrentDateTime() {
          Calendar calNow = Calendar.getInstance();
          return calNow.getTime();
     }

     /**
      * @param pattern
      * @return
      */
     public static String getCurrentDateString(String pattern) {
          return dateToString(getCurrentDateTime(), pattern);
     }

     /**
      * yyyy-MM-dd
      *
      * @return
      */
     public static String getCurrentDateString() {
          return dateToString(getCurrentDateTime(), ISO_EXPANDED_DATE_FORMAT);
     }

     /**
      * 返回固定格式的当前时间 yyyy-MM-dd hh:mm:ss
      *
      * @param
      * @return
      */
     public static String dateToStringWithTime() {

          return dateToString(new Date(), DATETIME_PATTERN_MINUTE);
     }

     /**
      * yyyy-MM-dd hh:mm:ss
      *
      * @param date
      * @return
      */
     public static String dateToStringWithTime(Date date) {

          return dateToString(date, DATETIME_PATTERN_MINUTE);
     }

     /**
      * yyyyMMdd
      *
      * @param date
      * @return String
      */
     public static String dateToStringWithTimeIso(Date date) {

          return dateToString(date, ISO_DATE_FORMAT);
     }

     /**
      * @param date
      * @param days
      * @return java.util.Date
      */
     public static Date dateIncreaseByDay(Date date, int days) {

          Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
          cal.setTime(date);
          cal.add(Calendar.DATE, days);

          return cal.getTime();
     }

     /**
      * @param date
      * @param mnt
      * @return java.util.Date
      */
     public static Date dateIncreaseByMonth(Date date, int mnt) {

          Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
          cal.setTime(date);
          cal.add(Calendar.MONTH, mnt);

          return cal.getTime();
     }

     /**
      * @param date
      * @param mnt
      * @return java.util.Date
      */
     public static Date dateIncreaseByYear(Date date, int mnt) {

          Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
          cal.setTime(date);
          cal.add(Calendar.YEAR, mnt);

          return cal.getTime();
     }

     /**
      * @param date yyyy-MM-dd
      * @param days
      * @return yyyy-MM-dd
      */
     public static String dateIncreaseByDay(String date, int days) {
          return dateIncreaseByDay(date, ISO_DATE_FORMAT, days);
     }

     /**
      * @param date
      * @param fmt
      * @param days
      * @return
      */
     public static String dateIncreaseByDay(String date, String fmt, int days) {
          return dateIncrease(date, fmt, Calendar.DATE, days);
     }

     /**
      * @param src
      * @param srcfmt
      * @param desfmt
      * @return
      */
     public static String stringToString(String src, String srcfmt, String desfmt) {
          return dateToString(stringToDate(src, srcfmt), desfmt);
     }

     /**
      * @param date
      * @return string
      */
     public static String getYear(Date date) {
          SimpleDateFormat formater = new SimpleDateFormat("yyyy");
          return formater.format(date);
     }

	/**
	 * @param date
	 * @return string
	 */
	public static int getYearOfInt(Date date) {
		SimpleDateFormat formater = new SimpleDateFormat("yyyy");
		return Integer.parseInt(formater.format(date));
	}

     /**
      * @param date
      * @return string
      */
     public static String getMonth(Date date) {
          SimpleDateFormat formater = new SimpleDateFormat("MM");
          return formater.format(date);
     }

     /**
      * @param date
      * @return string
      */
     public static String getDay(Date date) {
          SimpleDateFormat formater = new SimpleDateFormat("dd");
          return formater.format(date);
     }

     /**
      * @param date
      * @return string
      */
     public static String getHour(Date date) {
          SimpleDateFormat formater = new SimpleDateFormat("HH");
          return formater.format(date);
     }

     public static int getMinsFromDate(Date dt) {
          GregorianCalendar cal = new GregorianCalendar();
          cal.setTime(dt);
          int hour = cal.get(Calendar.HOUR_OF_DAY);
          int min = cal.get(Calendar.MINUTE);
          return ((hour * 60) + min);
     }

     /**
      * Function to convert String to Date Object. If invalid input then current
      * or next day date is returned (Added by Ali Naqvi on 2006-5-16).
      *
      * @param str      String input in YYYY-MM-DD HH:MM[:SS] format.
      * @param isExpiry boolean if set and input string is invalid then next day date
      *                 is returned
      * @return Date
      */
     public static Date convertToDate(String str, boolean isExpiry) {
          SimpleDateFormat fmt = new SimpleDateFormat(DATETIME_PATTERN_MINUTE);
          Date dt = null;
          try {
               dt = fmt.parse(str);
          } catch (ParseException ex) {
               Calendar cal = Calendar.getInstance();
               if (isExpiry) {
                    cal.add(Calendar.DAY_OF_MONTH, 1);
                    cal.set(Calendar.HOUR_OF_DAY, 23);
                    cal.set(Calendar.MINUTE, 59);
               } else {
                    cal.set(Calendar.HOUR_OF_DAY, 0);
                    cal.set(Calendar.MINUTE, 0);
               }
               dt = cal.getTime();
          }
          return dt;
     }

     public static Date convertToDate(String str) {
          SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd hh:mm");
          Date dt = null;
          try {
               dt = fmt.parse(str);
          } catch (ParseException ex) {
               dt = new Date();
          }
          return dt;
     }

     public static String dateFromat(Date date, int minute) {
          String dateFormat = null;
          int year = Integer.parseInt(getYear(date));
          int month = Integer.parseInt(getMonth(date));
          int day = Integer.parseInt(getDay(date));
          int hour = minute / 60;
          int min = minute % 60;
          dateFormat = year + (month > 9 ? String.valueOf(month) : "0" + month + "")
                  + (day > 9 ? String.valueOf(day) : "0" + day) + " "
                  + (hour > 9 ? String.valueOf(hour) : "0" + hour)
                  + (min > 9 ? String.valueOf(min) : "0" + min) + "00";
          return dateFormat;
     }

     public static String sDateFormat() {
          return new SimpleDateFormat(DATE_PATTERN).format(Calendar.getInstance().getTime());
     }

     /**
      * 判断是否为有效时间格式
      *
      * @param str
      * @return
      */
     public static Boolean valid(String str) {
          Boolean result = false;
          if (null != str) {
               for (String Pattern : parsePatterns) {
                    if (Pattern.equals(str)) {
                         result = true;
                         break;
                    }
               }
          }
          return result;
     }

     /**
      * 返回一个有效时间格式串若自身无效则返回"yyyy-MM-dd"
      *
      * @param str
      * @return
      */
     public static String validAndReturn(String str) {
          String result = ISO_EXPANDED_DATE_FORMAT;
          if (valid(str)) {
               result = str;
          }
          return result;
     }

     /**
      * 根据type返回时间差(除不尽加1)
      *
      * @param end   结束时间
      * @param begin 开始时间
      * @param type  返回类型1秒2分3小时4天（type其他值都返回秒）
      * @return
      */
     public static long getSubTime(Date end, Date begin, Integer type) {
          long between = 0;
          if (end != null && begin != null) {
               try {
                    // 得到两者的毫秒数
                    between = (end.getTime() - begin.getTime());
               } catch (Exception ex) {
                    log.error("根据type返回时间差",ex);
               }

               return initSubTime(type, between);
          } else {
               return between;
          }

     }

     private static long initSubTime(Integer type, long between) {
          if (null == type) {
               return between;
          } else if (type == 2) {
               long min = (between / (60 * 1000));
               if (between % (60 * 1000) != 0) {
                    min++;
               }
               return min;
          } else if (type == 3) {
               long hour = (between / (60 * 60 * 1000));
               if (between % (60 * 60 * 1000) != 0) {
                    hour++;
               }
               return hour;
          } else if (type == 4) {
               long day = between / (24 * 60 * 60 * 1000);
               if (between % (24 * 60 * 60 * 1000) != 0) {
                    day++;
               }
               return day;
          } else {
               return between;
          }
     }

     /**
      * 已当月为基准往前退 i+1 个生成月份格式：YYYYMMDD  未完善
      *
      * @param @param  i
      * @param @return 参数
      * @return String    返回类型
      * @throws
      * @Title: getMonthByNum
      * @Description:
      */
     public static List<MonthObject> getMonthByNum(int i, int endDate) {
          List<MonthObject> socailStartList = new ArrayList<>();
          MonthObject temp = null;
          MonthObject temp2 = null;
          SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_YYYYMM);
          // 取时间
          Date date = new Date();
          Calendar calendar = new GregorianCalendar();
          calendar.setTime(date);
          if (endDate <= Integer.parseInt(DateUtil.getDay(date))) {
               // 把日期往后增加一个月.整数往后推,负数往前移动
               calendar.add(Calendar.MONTH, 2);
          } else {
               // 把日期往后增加一个月.整数往后推,负数往前移动
               calendar.add(Calendar.MONTH, 1);
          }
          temp2 = new MonthObject();
          temp2.setMonth(sdf.format(calendar.getTime()));
          date = calendar.getTime();
          socailStartList.add(temp2);
          for (int x = 1; x <= i; x++) {
               calendar.setTime(date);
               calendar.add(Calendar.MONTH, -x);
               temp = new MonthObject();
               temp.setMonth(sdf.format(calendar.getTime()));
               socailStartList.add(temp);
          }
          return socailStartList;
     }

     /**
      * 获得指定月份的日期
      *
      * @param i
      * @return
      * @Author fxj
      * @Date 2019-09-18
      **/
     public static Date getDateByMonthNum(int i) {
          // 取时间
          Date date = new Date();
          Calendar calendar = new GregorianCalendar();
          calendar.setTime(date);
          // 把日期往后增加一个月.整数往后推,负数往前移动
          calendar.add(Calendar.MONTH, i);
          return calendar.getTime();
     }

     /**
      * @param @param  i
      * @param @return 参数
      * @return List<MonthObject>    返回类型
      * @throws
      * @Title: getFutureMonthByNum
      * @Description: (已当前月份未基准往后退 i + 1个月份)
      */
     public static List<MonthObject> getFutureMonthByNum(int k, int endDate) {
          List<MonthObject> socailStartList = new ArrayList<>();
          MonthObject temp = null;
          SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_YYYYMM);
          Date date = new Date();//取时间
          Calendar calendar = new GregorianCalendar();
          int j = 0;
          if (endDate <= Integer.parseInt(DateUtil.getDay(date))) {
               j = 2;
          } else {
               j = 1;
          }
          for (int x = j; x < k; x++) {
               calendar.setTime(date);
               calendar.add(Calendar.MONTH, x);
               temp = new MonthObject();
               temp.setMonth(sdf.format(calendar.getTime()));
               socailStartList.add(temp);
          }
          return socailStartList;
     }

     public static List<Date> getDateListByStartEndDate(Date startDate, Date endDate) {
          List<Date> lstDate = new ArrayList<>();
          lstDate.add(startDate);
          if (startDate.equals(endDate)) {
               return lstDate;
          }
          SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_YYYYMM);
          Calendar calendar = new GregorianCalendar();
          calendar.setTime(startDate);
          for (int i = 1; i > 0; i = 1) {
               calendar.add(Calendar.MONTH, i);
               try {
                    if (sdf.format(calendar.getTime()).equals(sdf.format(endDate))) {
                         lstDate.add(sdf.parse(sdf.format(calendar.getTime())));
                         break;
                    }
                    lstDate.add(sdf.parse(sdf.format(calendar.getTime())));
               } catch (ParseException e) {
                    log.error("getDateListByStartEndDate",e);
               }
          }
          return lstDate;
     }

     /**
      * @param @param  startDate  起缴日期
      * @param @param  backNum  补缴月份
      * @param @param  type  补缴类型  1.当月缴纳当月 2.当月缴纳次月
      * @param @return 参数
      * @return boolean    返回类型
      * @throws
      * @Title: checkStartDate
      * @Description: (判断日期是否在指定的日期范围内)
      */
     public static boolean checkStartDate(Date startDate, int backNum, int type) {
          Calendar calendar = new GregorianCalendar();
          calendar.setTime(new Date());
          Date temp = null;
          if (type == 1) {
               calendar.add(Calendar.MONTH, backNum);
          } else if (type == 2) {
               calendar.add(Calendar.MONTH, backNum - 1);
          }
          temp = calendar.getTime();
          SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_YYYYMM);
          try {
               // 当startDate 在temp 前 返回false
               if (!startDate.before(sdf.parse(sdf.format(temp)))) {
                    return true;
               }
          } catch (ParseException e) {
               return true;
          }
          return false;
     }

	 /**
	  * @param startDate
	  * @param endDate
	  * @Description: 计算年月的月份差值（202205-202205=0,202205-202105=12）想要1自己+1 年月差值
	  * @Author: hgw
	  * @Date: 2022/7/15 12:16
	  * @return: int
	  **/
	 public static int getMonthDiff(Date startDate, Date endDate) {
		try {
			Calendar c1 = Calendar.getInstance();
			Calendar c2 = Calendar.getInstance();
			c1.setTime(startDate);
			c2.setTime(endDate);
			return 12 * (c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR)) + c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);
		} catch (IllegalFormatException e) {
			log.error("计算日期月份差，方法名：getMonthDiff，出错：",e);
			return 0;
		}
	}

     public static int getMonthCountByDate(Date startDate, Date endDate) {
          // type:1.当月缴当月的 2.当月缴次月的
          int monthC = 0;
          SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_YYYYMM);
          if (endDate == null) {
               endDate = new Date();
          }
          try {
               monthC = getMonthSpace(sdf.format(startDate), sdf.format(endDate));
               monthC = monthC + 1;
          } catch (ParseException e) {
               log.error("getMonthCountByDate",e);
               return 0;
          }

          return monthC;
     }

     /**
      * @param date1 <String>
      * @param date2 <String>
      * @return int
      * @throws ParseException
      */
     public static int getMonthSpace(String date1, String date2)
             throws ParseException {

          int result = 0;

          SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_YYYYMM);

          Calendar c1 = Calendar.getInstance();
          Calendar c2 = Calendar.getInstance();

          c1.setTime(sdf.parse(date1));
          c2.setTime(sdf.parse(date2));

          result = 12 * (c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR)) + c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);

          return result / 1;

     }
     /**
      * @param date1 <String>
      * @param date2 <String>
      * @return int
      * @throws ParseException
      */
     public static int getYearSpace(String date1, String date2)
             throws ParseException {

          int result = 0;

          SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_YYYYMM);

          Calendar c1 = Calendar.getInstance();
          Calendar c2 = Calendar.getInstance();

          c1.setTime(sdf.parse(date1));
          c2.setTime(sdf.parse(date2));

          result = 1 * (c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR)) + (c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH))/12;

          return result / 1;

     }
     /**
      * 获取任意时间的月的最后一天
      * 描述:<描述函数实现的功能>.
      *
      * @param repeatDate
      * @return
      */
     public static String getMaxMonthDate(String repeatDate) {
          SimpleDateFormat dft = new SimpleDateFormat(ISO_DATE_FORMAT);
          Calendar calendar = Calendar.getInstance();
          try {
               if (StringUtils.isNotBlank(repeatDate) && !"null".equals(repeatDate)) {
                    calendar.setTime(dft.parse(repeatDate));
               }
          } catch (ParseException e) {
               log.error("getMaxMonthDate",e);
          }
          calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
          return dft.format(calendar.getTime());
     }

     public static Date getMaxDayOfMonth(Date temp) {
          SimpleDateFormat sdf = new SimpleDateFormat(ISO_DATE_FORMAT);
          String dateStr = sdf.format(temp);
          dateStr = getMaxMonthDate(dateStr);
          Date res = null;
          try {
               res = sdf.parse(dateStr);
          } catch (ParseException e) {
               log.error("getMaxDayOfMonth",e);
          }
          return res;
     }

     public static Integer getDateOfNow() {
          Calendar now = Calendar.getInstance();
          return now.get(Calendar.DAY_OF_MONTH);
     }

     /**
      * 获取i年后的时间自动 -1天
      * @param @param  date
      * @param @param  i
      * @param @return
      * @param @throws ParseException    参数
      * @return String    返回类型
      * @throws
      * @Title: getMonthSpace
      * @Description: (获取指定日期后指定 (i 个年的时间)
      */
     public static String getDateStr(Date date, int i) {
          String str = "";
          Calendar c1 = Calendar.getInstance();
          c1.setTime(date);
          c1.set(Calendar.YEAR,c1.get(Calendar.YEAR)+i);
          c1.set(Calendar.DAY_OF_MONTH,c1.get(Calendar.DAY_OF_MONTH) -1);
          int year = c1.get(Calendar.YEAR);
          int month = c1.get(Calendar.MONTH)+1;
          int day = c1.get(Calendar.DAY_OF_MONTH);
          str = year +""+ (month < 10 ? "0" + month : month) + (day < 10 ? "0" + day : day);
          return str;

     }

     /**
      * 获取指定月份
      * @Author fxj
      * @Date 2019-10-16
      * @param yearMonth  格式 ：YYYYMM
      * @param i
      * @return
      * @Description (获取指定日期后指定 ( i)个月的时间YYYYMM)
      **/
     public static String getYearAndMonth(String yearMonth,int i){
          if (!Common.isNotNull(yearMonth) || yearMonth.length() != 6 || !Common.isNumber(yearMonth)){
               return null;
          }
          Calendar c1 = Calendar.getInstance();
          c1.set(Integer.valueOf(yearMonth.substring(0,4)),Integer.valueOf(yearMonth.substring(4,6)),1);
          c1.set(Calendar.MONTH,c1.get(Calendar.MONTH) + i);
          String str ="";
          int year = c1.get(Calendar.YEAR);
          int month = c1.get(Calendar.MONTH);
          if (month == 0){
               year = year -1;
               month = month + 12;
               str = year + (month < 10 ? "0" + month: month + "");
          }else{
               str = year + (month < 10 ? "0" + month : month + "");
          }
          return str;
     }


     /**
      * 获取指定月份
      * @Author fxj
      * @Date 2019-10-16
      * @param yearMonth  格式 ：LocalDateTime
      * @param i
      * @return
      * @Description (获取指定日期后指定 ( i)个月的时间YYYYMM)
      **/
     public static String getYearAndMonth(LocalDateTime yearMonth, int i){
          String str ="";
          if(yearMonth != null) {
               Calendar c1 = Calendar.getInstance();
               c1.set(yearMonth.getYear(),yearMonth.getMonthValue(),1);
               c1.set(Calendar.MONTH,c1.get(Calendar.MONTH) + i );
               int year = c1.get(Calendar.YEAR);
               int month = c1.get(Calendar.MONTH);
               if (month == 0){
                    year = year -1;
                    month = month + 12;
                    str = year + (month < 10 ? "0" + month : Integer.toString(month));
               }else{
                    str = year + (month < 10 ? "0" + month : Integer.toString(month));
               }
          }
          return str;
     }

     /**
      * @param i 加减年份
      * @Description: 获取当前年月，对年月加减（yyyyMM）
      * @Author: hgw
      * @Date: 2019/10/29 17:13
      * @return: java.lang.String
      **/
     public static String getYearMonthByAddYear(int i){
          Calendar c1 = Calendar.getInstance();
          c1.set(Calendar.YEAR,c1.get(Calendar.YEAR) + i);
          SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_YYYYMM);
          return sdf.format(c1.getTime());
     }

     /**
      * 获取第一天
      * @Author fxj
      * @Date 2019-10-16
      * @param yearMonth YYYYMM
      * @return
      **/
     public static Date getFirstDay(String yearMonth){
          if (!Common.isNotNull(yearMonth) || yearMonth.length() != 6 || !Common.isNumber(yearMonth)){
               return null;
          }
          Calendar c1 = Calendar.getInstance();
          c1.set(Integer.valueOf(yearMonth.substring(0,4)),Integer.valueOf(yearMonth.substring(4,6))-1,1);
          return c1.getTime();
     }

     /**
      * 获取第一天
      * @Author fxj
      * @Date 2019-10-16
      * @param yearMonth YYYYMM
      * @return
      **/
     public static String getFirstDayString(String yearMonth){
          return yearMonth.substring(0,4)+"-"+yearMonth.substring(4,6)+"-01";
     }
     /**
      * 当月第一天
      * @Author fxj
      * @Date 2021-01-05
      * @param
      * @return
      * @see com.yifu.cloud.v1.common.core.util
      **/
     public  static LocalDateTime getFirstDay(){
          return LocalDateTime.now().with(TemporalAdjusters.firstDayOfMonth());
     }
     /**
      * 获取最后一天
      * @Author fxj
      * @Date 2019-10-16
      * @param yearMonth YYYYMM
      * @return
      **/
     public static Date getLastDay(String yearMonth){
          if (!Common.isNotNull(yearMonth) || yearMonth.length() != 6 || !Common.isNumber(yearMonth)){
               return null;
          }
          Calendar c1 = Calendar.getInstance();
          c1.set(Integer.valueOf(yearMonth.substring(0,4)),Integer.valueOf(yearMonth.substring(4,6))-1,c1.getActualMaximum(Calendar.DAY_OF_MONTH));
          return c1.getTime();
     }
     /**
      * 根据指定的格式将字符串转换成Date 如输入：2003-11-19 11:20:20将按照这个转成时间
      *
      * @param src     将要转换的原始字符窜
      * @param pattern 转换的匹配格式
      * @return 如果转换成功则返回转换后的日期
      * @throws ParseException
      */
     public static Date parseDate(String src, String pattern) throws ParseException {
          return getSDFormat(pattern).parse(src);

     }

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

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

	 /**
	  * @param date
	  * @param patten
	  * @Description: 按指定格式返回
	  * @Author: hgw
	  * @Date: 2022/7/19 17:10
	  * @return: java.lang.String
	  **/
	public static String formatDatePatten(Date date, String patten) {
		if (Common.isEmpty(patten)) {
			patten = DATETIME_YYYYMM;
		}
		SimpleDateFormat sdf = new SimpleDateFormat(patten);
		return sdf.format(date);
	}

	/**
	 * @param date
	 * @Description: 按指定格式返回int
	 * @Author: hgw
	 * @Date: 2022/7/19 17:13
	 * @return: java.lang.Integer
	 **/
	public static Integer formatDateInt(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_YYYYMM);
		return Integer.parseInt(sdf.format(date));
	}

     /**
      * @param mnt 增减月份的 值
      * @param yearMonth 202101
      * @Description: 增减月份
      * @Author: hgw
      * @Date: 2019/9/17 10:15
      * @return: java.lang.String
      **/
     public static String addMonthByYearMonth(int mnt, String yearMonth) {
          Calendar cal = Calendar.getInstance();
          cal.set(Integer.valueOf(yearMonth.substring(0,4)),Integer.valueOf(yearMonth.substring(4,6))-1,1);
          cal.add(Calendar.MONTH, mnt);
          SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_YYYYMM);
          return sdf.format(cal.getTime());
     }

     /**
      * @param mnt 增减月份的 值
      * @param yearToMonth 2021-01
      * @Description: 增减月份
      * @Author: hgw
      * @Date: 2019/9/17 10:15
      * @return: java.lang.String
      **/
     public static String addMonthByYearToMonth(int mnt, String yearToMonth) {
          Calendar cal = Calendar.getInstance();
          cal.set(Integer.parseInt(yearToMonth.substring(0,4)),Integer.parseInt(yearToMonth.substring(5,7))-1,1);
          cal.add(Calendar.MONTH, mnt);
          SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_YYYY_MM);
          return sdf.format(cal.getTime());
     }

     /**
      * @param yearToMonth 2021-01
      * @Description: 比较年月大小
      * @Author: hgw
      * @Date: 2021/4/27 14:55
      * @return: boolean
      **/
     public static int paseYearToMonth(String yearToMonth) {
          return Integer.parseInt(yearToMonth.substring(0,4) + yearToMonth.substring(5,7));
     }

     /**
      * @param mnt 增减月份的 值
      * @Description: 增减月份
      * @Author: hgw
      * @Date: 2019/9/17 10:15
      * @return: java.lang.String
      **/
     public static String addMonth(int mnt) {
          Calendar cal = Calendar.getInstance();
          cal.add(Calendar.MONTH, mnt);
          SimpleDateFormat sdf = new SimpleDateFormat(DATETIME_YYYYMM);
          return sdf.format(cal.getTime());
     }

	 /**
	  * @Description: 增减（月）
	  * @Author: hgw
	  * @Date: 2022/8/3 9:17
	  * @return: java.util.Date
	  **/
	 public static Date addMonthByDate(Date date, int mnt) {
          Calendar cal = Calendar.getInstance();
		  if (date != null) {
			  cal.setTime(date);
		  }
          cal.add(Calendar.MONTH, mnt);
          return cal.getTime();
     }

	 /**
	  * @Description: 增减（日）
	  * @Author: hgw
	  * @Date: 2022/8/3 9:17
	  * @return: java.util.Date
	  **/
	 public static Date addDayByDate(Date date, int mnt) {
          Calendar cal = Calendar.getInstance();
		  if (date != null) {
			  cal.setTime(date);
		  }
          cal.add(Calendar.DATE, mnt);
          return cal.getTime();
     }

     /**
      * @param mnt 增减日的 值
      * @Description: 增减日
      * @Author: hgw
      * @Date: 2021-7-15 11:36:23
      * @return: java.lang.String
      **/
     public static String addDay(int mnt) {
          Calendar cal = Calendar.getInstance();
          cal.add(Calendar.DATE, mnt);
          SimpleDateFormat sdf = new SimpleDateFormat(ISO_EXPANDED_DATE_FORMAT);
          return sdf.format(cal.getTime());
     }

     /**
      * @param taxYearMonth 计税月
      * @Description: 根据计税年月返回个税扣除额
      * @Author: hgw
      * @Date: 2019/9/19 16:02
      * @return: double
      **/
     public static BigDecimal getTaxMonthMoney(String taxYearMonth) {
          try {
               int taxYear = Integer.parseInt(taxYearMonth.substring(0, 4));
               int taxMonth = Integer.parseInt(taxYearMonth.substring(4, 6));
               int nowYear = Integer.parseInt(DateFormatUtils.format(new Date(), "yyyy"));
               int nowMonth = Integer.parseInt(DateFormatUtils.format(new Date(), "MM"));
               // 同一个计税年
               if (nowYear - taxYear == 0) {
                    return new BigDecimal((nowMonth - taxMonth + 1) * 5000);
                    // 前一个计税年
               } else if (nowYear - taxYear > 0) {
                    // 禅道461：王成说的。
                    return new BigDecimal((nowMonth) * 5000);
               } else {
                    // 比当前年还大
                    return new BigDecimal(0);
               }
          } catch (Exception e) {
               log.error("getTaxMonthMoney",e);
          }
          return new BigDecimal(0);
     }

     /**
      * <p>Description: 返回最大值月份</p>
      * @author hgw
      * @Date 2019年4月29日下午6:52:41
      * @param taxMonth
      * @return
      */

     /**
      * @param taxMonth
      * @Description: 返回起始计税月（例如：计税月是今年之前的，则取值今年1月，否则=计税月）
      * @Author: hgw
      * @Date: 2019/9/30 18:16
      * @return: java.lang.String
      **/
     public static String getMaxYearMonth(String taxMonth) {
          if (Common.isNotNull(taxMonth) && taxMonth.length() >= 6) {
               taxMonth = taxMonth.substring(0, 6);
               String nowYearMonth = getCurrentDateString("yyyy") + "01";
               int nowYearMonthInt = Integer.parseInt(nowYearMonth);
               if (Integer.parseInt(taxMonth) > nowYearMonthInt) {
                    return taxMonth;
               } else {
                    return nowYearMonth;
               }
          }
          return null;
     }

     /**
      * <p>Description: 返回年月</p>
      * @author hgw
      * @Date 2019年5月16日下午6:39:02
      * @param currentMonth
      * @return
      */
     public static String getYearMonth(String currentMonth) {
          if (Common.isNotNull(currentMonth) && currentMonth.length() > 5) {
               if (currentMonth.indexOf('-') >= 0) {
                    currentMonth = currentMonth.replace("-", "");
               }
               return currentMonth.substring(0,4) + currentMonth.substring(4,6);

          }
          return null;
     }


     /**
      *
      * @Author fxj
      * @Date 2019-11-20
      * @param backMonths 补缴月份数
      * @param haveThisMonth 0是1否 补缴是否含当月  含当月 补缴月份数 -1   不含当月补缴月数不变
      * @param isBack 0是1否 是否补缴  不补缴默认从当前月开始 至次月
      * @return
      **/
     public static List<String> getMonthsForSocialAndFund(int isBack,int backMonths,int haveThisMonth){
          List<String> months = new ArrayList<>();
          int count = 0;
          //补缴
          if (isBack==0){
              //含当月
              if (haveThisMonth == 0){
                count = backMonths-1;
              //不含当月
              }else if (haveThisMonth == 1){
                count = backMonths;
              }
          }
         LocalDateTime now = LocalDateTime.now();
          while (count >= 0){
              months.add(getYearAndMonth(now,-count));
              count--;
          }
         months.add(getYearAndMonth(now,1));
          return months;
     }

     /**
      * @param cur
      * @param to
      * @Description: 比较月份大小
      * @Author: hgw
      * @Date: 2019/11/25 18:18
      * @return: int
      **/
     public static int compareMonth(LocalDateTime cur, LocalDateTime to) {
          return (cur.getYear() - to.getYear()) * 12 + (cur.getMonthValue() - to.getMonthValue());
     }

     /**
      * @param a 第一个年月
      * @param b 第二个年月
      * @Description:  比较a和b的大小，a大，则返回true;
      * @Author: hgw
      * @Date: 2020/10/16 15:44
      * @return: boolean
      **/
     public static boolean compareYearMonth(String a, String b) {
          try {
               if (a != null && b != null && !"".equals(a) && !"".equals(b) && a.length() == 6 && b.length() == 6) {
                    int aInt = Integer.parseInt(a.substring(0, 4));
                    int bInt = Integer.parseInt(b.substring(0, 4));
                    if (aInt > bInt) {
                         return true;
                    } else if (aInt < bInt) {
                         return false;
                    } else {
                         aInt = Integer.parseInt(a.substring(4, 6));
                         bInt = Integer.parseInt(b.substring(4, 6));
                         return aInt > bInt;
                    }
               }
               return true;
          } catch (NumberFormatException e) {
               return true;
          }
     }

     /**
      * @param
      * @Author: wangan
      * @Date: 2020/12/21
      * @Description: 获取这个月
      * @return: java.lang.String
      **/
     public static String getThisMonth(){
          SimpleDateFormat sf = new SimpleDateFormat(DateUtil.DATETIME_YYYYMM);
          Date nowDate = new Date();
          String thisMonth = sf.format(nowDate);
          return thisMonth;
     }

	 /**
	  * @param years 出生年
	  * @Description:  获取年龄
	  * @Author: hgw
	  * @Date: 2022/6/24 16:49
	  * @return: int
	  **/
	 public static int getAge(int years){
		SimpleDateFormat sf = new SimpleDateFormat(DateUtil.DATETIME_YYYY);
		Date nowDate = new Date();
		int thisYear = Integer.parseInt(sf.format(nowDate));
		return thisYear - years + 1;
	}

	 /**
	  * @Description: 返回当前年月日字符串
	  * @Author: hgw
	  * @Date: 2022/6/21 17:19
	  * @return: java.lang.String
	  **/
	 public static String getThisDay(){
          SimpleDateFormat sf = new SimpleDateFormat(DateUtil.ISO_DATE_FORMAT);
          return sf.format(new Date());
     }

	 /**
	  * @Description: 返回当前年月日时分秒字符串（一般用在导出文件名）
	  * @Author: hgw
	  * @Date: 2022-6-24 10:00:41
	  * @return: java.lang.String
	  **/
	 public static String getThisTime(){
          SimpleDateFormat sf = new SimpleDateFormat(DateUtil.EXPORT_PATTERN);
          return sf.format(new Date());
     }


     /**
      * @param
      * @Author: wangan
      * @Date: 2020/12/21
      * @Description: 获取上个月
      * @return: java.lang.String
      **/
     public static String getLastMonth(){
          SimpleDateFormat sf = new SimpleDateFormat(DateUtil.DATETIME_YYYYMM);
          Date nowDate = new Date();
          Calendar instance = Calendar.getInstance();
          instance.setTime(nowDate);
          instance.add(Calendar.MONTH, -1);
          String lastMonth = sf.format(instance.getTime());
          return lastMonth;
     }


     /**
      * @param
      * @Author: wangan
      * @Date: 2020/12/21
      * @Description: 获取上n个月
      * @return: java.lang.String
      **/
     public static String getLastXMonth(int month){
          SimpleDateFormat sf = new SimpleDateFormat(DateUtil.DATETIME_YYYYMM);
          Date nowDate = new Date();
          Calendar instance = Calendar.getInstance();
          instance.setTime(nowDate);
          instance.add(Calendar.MONTH, month);
          return sf.format(instance.getTime());
     }

     /**
      * @param yearMonth 年月（例：202201）
      * @param month 增减数值（例：1，或 -1）
      * @Description: String年月，根据month增减，大多数为了获取下月或上月使用
      * @Author: hgw
      * @Date: 2022/3/31 20:43
      * @return: java.lang.String
      **/
     public static String addMonthByString(String yearMonth, int month) {
          if (Common.isNotNull(yearMonth)) {
               try {
                    SimpleDateFormat sf = new SimpleDateFormat(DateUtil.DATETIME_YYYYMM);
                    Date d1 = sf.parse(yearMonth);
                    Calendar instance = Calendar.getInstance();
                    instance.setTime(d1);
                    instance.add(Calendar.MONTH, month);
                    return sf.format(instance.getTime());
               } catch (ParseException e) {
                    return null;
               }
          } else {
               return null;
          }
     }
}
