package com.wechat.common.utils;

import java.math.BigDecimal;
import java.text.Format;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;


public class DateUtils extends BaseUtils {

    /**
     * 日期格式
     */
    public static String PATTEN_YMD = "yyyy-MM-dd";
    
    /**
     * 日期格式2yyyy/MM/dd
     */
    public static String PATTEN_YMD2 = "yyyy/MM/dd";
    
    /**
     * 日期格式
     */
    public static String PATTEN_YMTOW = "yyyy-MM";

    /**
     * 日期时间 格式
     */
    public static String PATTEN_HMS = "yyyy-MM-dd HH:mm:ss";
    
    /**
     * 日期格式,不带分隔符 yyyyMMddHHmmss
     */
    public static String PATTEN_YMD_HH_MM_SS_SEPRATE = "yyyyMMddHHmmss";

    /**
     * 日期时间 格式
     */
    public static String PATTEN_HM = "yyyy-MM-dd HH:mm";

    /**
     * 带毫秒日期格式
     */
    public static String PATTEN_SSS = "yyyy-MM-dd HH:mm:ss.SSS";

    /**
     * 日期格式,不带分隔符
     */
    public static String PATTEN_YMD_NO_SEPRATE = "yyyyMM";

    /**
     * 文件重命名专用日期格式
     */
    public static String PATTEN_FILE_RENAME = "yyyyMMddHHmmssSSS";
    
    /**
     * HH:mm:ss
     */
    public static String PATTEN_ONLYHMS = "HH:mm:ss";
    
    /**
     * 日期格式
     */
    public static String PATTEN_YMDH = "yyyy-MM-dd HH";

    public static String PATTEN_YM = "yyyyMM";
    public static String PATTEN_Y = "yyyy";
    
    public static String PATTEN_MD = "MM/dd";

    /**
     * 大于
     */
    public static final String COMPARE_TYPE_GT = "GT";

    /**
     * 大于等于
     */
    public static final String COMPARE_TYPE_GTE = "GTE";

    /**
     * 不等于
     */
    public static final String COMPARE_TYPE_NE = "NE";

    /**
     * 日期验证复杂正则
     */
    public static String DATE_REG = "([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))|(02(0[1-9]|[1][0-9]|2[0-9])))";

    /**
     * 日期验证简单正则
     */
    private static String DATE_REG_SIMPLE = "^\\d{4}-\\d{2}-\\d{2}$";

    /**
     * 默认的日期间隔符
     */
    public static String DEFAULT_SEPERATOR = "-";
    
    /**
     * 股票市场开始时的点
     */
    public static int MARKET_START_POINT = 570;

    /**
     * 提供日期格式化工具
     * 
     * @param pattern 日期格式
     * @return 格式化工具类
     */
    private static SimpleDateFormat getDateParser(String pattern) {
        return new SimpleDateFormat(pattern);
    }

    /**
     * 将当前时间转换成指定的格式显示
     * 
     * @param pattern 日期格式
     * @return 转换后的日期字符串
     */
    public static String dateToString(String pattern) {
        return getDateParser(pattern).format(new Date());
    }

    /**
     * 将指定日期转换成指定格式的字符串
     * 
     * @param date 日期
     * @param pattern 日期格式
     * @return 转换后的日期字符串
     */
    public static String dateToString(Date date, String pattern) {
        return getDateParser(pattern).format(date);
    }

    /**
     * 将指定格式的时间转换成Date类型
     * 
     * @param date 指定日期
     * @param pattern 格式
     * @return 转换后日期
     * @throws Exception 转换异常时，返回系统异常
     */
    public static Date stringToDate(String date, String pattern) throws Exception{
        if (StringsUtils.isEmpty(pattern)) {
            pattern = PATTEN_YMD;
        }
        if (StringsUtils.isEmpty(date)) {
            return null;
        }
        Date result = null;
        try {
            result = getDateParser(pattern).parse(date);
        } catch (ParseException e) {
        	log.error("日期格式转换错误",e);
            throw e;
        }
        return result;
    }
    
    
    /**
     * 将指定日期的时间戳格式转换成日期
     * 
     * @param pattern 日期格式
     * @return 转换后的日期字符串
     */
    public static Date stringToDate(String dateTime) {
    	Date date = null;
    	if(!StringsUtils.isEmpty(dateTime))
    	{
    		date = new Date(Long.parseLong(dateTime));
    	}
        return date;
    }


    /**
     * 将指定格式的时间转换成其他日期格式
     * 
     * @param date 指定日期
     * @param pattern 指定格式
     * @param resultPattern 目标格式
     * @return 转换后的日期字符串
     * @throws Exception 转换异常，抛出系统异常
     */
    public static String changeDateFormat(String date, String pattern, String resultPattern) throws Exception {
        String result = "";
        try {
            Date dateTmp = null;
            dateTmp = getDateParser(pattern).parse(date);
            result = getDateParser(resultPattern).format(dateTmp);
        } catch (ParseException e) {
        	log.error("日期格式转换错误",e);
        	throw e;
        }
        return result;
    }

    /**
     * 获取前一天日期
     * 
     * @param fm 日期格式
     * @return 前一天 日期
     * @throws Exception 转换异常，抛出系统异常
     */
    public static String stringToBeforeDate(String fm) {
        String result;
        Calendar date = Calendar.getInstance();
        date.add(Calendar.DAY_OF_MONTH, -1);
        Format format = new SimpleDateFormat(fm);
        result = format.format(date.getTime());
        return result;
    }

    /**
     * 获取当前日期前30天的日期
     * 
     * @param fm 日期格式
     * @return 当前日期前三十天的日期
     * @throws Exception 转换异常，抛出系统异常
     */
    public static String thirtyDaysBeforeNow(String fm) throws Exception {
        String result;
        Calendar date = Calendar.getInstance();
        date.add(Calendar.DAY_OF_MONTH, -30);
        Format format = new SimpleDateFormat(fm);
        result = format.format(date.getTime());
        return result;
    }

    /**
     * 获取指定日期的前30天的日期
     * 
     * @param startDate 指定日期
     * @param fm 格式
     * @return 指定日期前30天的日期
     * @throws Exception 转换异常，抛出系统异常
     */
    public static String thirtyDaysBeforeSpecifiedDate(Date startDate, String fm) throws Exception {
        String result;
        Calendar date = Calendar.getInstance();
        date.setTime(startDate);
        date.add(Calendar.DAY_OF_MONTH, -30);
        Format format = new SimpleDateFormat(fm);
        result = format.format(date.getTime());
        return result;
    }

    /**
     * 获取当天日期
     * 
     * @param fm 日期格式
     * @return 当天日期
     * @throws Exception 转换异常，抛出系统异常
     */
    public static String stringToToday(String fm) throws Exception {
        String result;
        Format format = new SimpleDateFormat(fm);
        result = format.format(new Date());
        return result;
    }

    /**
     * 返回某月的第一天
     * 
     * @param year 年
     * @param month 月
     * @return 某月的第一天
     * @throws Exception 
     */
    public static Date getFirstDayOfMonth(String year, String month) throws Exception {
        //验证空
        if (StringsUtils.isEmpty(year) || StringsUtils.isEmpty(month)) {
            return null;
        }
        //验证年
        if (!StringsUtils.matches(year, "\\d{4}")) {
            return null;
        }
        //验证月
        int monthValue = Integer.parseInt(month);
        if (monthValue > 12 || monthValue < 1) {
            return null;
        }
        //改成  yyyy-MM-dd格式
        StringBuilder sb = new StringBuilder();
        sb.append(year);
        sb.append(DEFAULT_SEPERATOR);
        sb.append(month);
        sb.append(DEFAULT_SEPERATOR);
        sb.append("01");
        return stringToDate(sb.toString(), PATTEN_YMD);
    }
    
    /**
     * 指定日期的每月第一天
     * 
     * @param date 待转化的日期数据
     * @return 每月第一天
     */
    public static LocalDate getFistDayOfMonth(LocalDate date) {
        if (null == date) {
        	date=LocalDate.now();
        }
        LocalDate rest = date.withDayOfMonth(1);
        return rest;
    }
    
    public static LocalDate getFistDayOfMonth(Date date) {
    	LocalDate localDate=LocalDate.now();
        if (null != date) {
        	localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        }
        
        return getFistDayOfMonth(localDate);
    }

    /**
     * 返回某月的最后一天
     * 
     * @param year 年
     * @param month 月
     * @return 某月的最后一天
     */
    public static Date getLastDayOfMonth(String year, String month) {
        //验证空
        if (StringsUtils.isEmpty(year) || StringsUtils.isEmpty(month)) {
            return null;
        }
        //验证年
        if (!StringsUtils.matches(year, "\\d{4}")) {
            return null;
        }
        //验证月
        int monthValue = Integer.parseInt(month);
        if (monthValue > 12 || monthValue < 1) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, Integer.parseInt(year));
        cal.set(Calendar.MONTH, monthValue - 1);
        cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        return cal.getTime();
    }
    
    /**
     * 指定日期的每月最后一天
     * 
     * @param date 待转化的日期数据
     * @return 每月最后一天
     */
    public static LocalDate getLastDayOfMonth(LocalDate date) {
        if (null == date) {
        	date=LocalDate.now();
        }
        LocalDate rest = date.withDayOfMonth(date.lengthOfMonth());
        return rest;
    }
    
    public static LocalDate getLastDayOfMonth(Date date) {
    	LocalDate localDate=LocalDate.now();
        if (null != date) {
        	localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        }
        
        return getLastDayOfMonth(localDate);
    }
    
    /**
     * 指定日期的当年第一天
     * 
     * @param date 待转化的日期数据
     * @return 当年第一天
     */
    public static LocalDate getFistDayOfYear(LocalDate date) {
        if (null == date) {
        	date=LocalDate.now();
        }
        LocalDate rest = date.withDayOfYear(1);
        return rest;
    }
    
    public static LocalDate getFistDayOfYear(Date date) {
    	LocalDate localDate=LocalDate.now();
        if (null != date) {
        	localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        }
        
        return getFistDayOfYear(localDate);
    }
    
    /**
     * 指定日期的当年最后一天
     * 
     * @param date 待转化的日期数据
     * @return 当年最后一天
     */
    public static LocalDate getLastDayOfYear(LocalDate date) {
        if (null == date) {
        	date=LocalDate.now();
        }
        LocalDate rest = date.withMonth(12).withDayOfMonth(31);
        return rest;
    }
    
    public static LocalDate getLastDayOfYear(Date date) {
    	LocalDate localDate=LocalDate.now();
        if (null != date) {
        	localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        }
        
        return getLastDayOfYear(localDate);
    }

    /**
     * 返回yyyy-mm-dd格式日期
     * 
     * @param date 传入的日期
     * @return yyyy-mm-dd格式日期
     */
    public static String formatString(String date) {

        if (StringsUtils.isEmpty(date) || !checkIsActiveDate(date)) {
            return "";
        }
        if (date.length() < 10) {
            return date;
        } else {
            return date.substring(0, 10);
        }
    }

    /**
     * 返回指定格式的日期字符串
     * 
     * @param date 待转化的日期数据
     * @param dateFm 日期格式
     * @return 指定格式的日期字符串
     */
    public static String formatString(Date date, String dateFm) {
        if (StringsUtils.isEmpty(dateFm)) {
            dateFm = PATTEN_YMD;
        }
        if (null == date) {
            return "";
        }
        Format fm = new SimpleDateFormat(dateFm);
        return fm.format(date);
    }
    
    /**
     * 返回指定格式的日期字符串
     * 
     * @param date 待转化的日期数据
     * @param dateFm 日期格式
     * @return 指定格式的日期字符串
     */
    public static String localDateformatString(LocalDate date, String dateFm) {
        if (StringsUtils.isEmpty(dateFm)) {
            dateFm = PATTEN_YMD;
        }
        if (null == date) {
        	date=LocalDate.now();
        }
        
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFm);
        String dateStr = dateTimeFormatter.format(date);
        return dateStr;
    }
    

    /**
     * 获取当前日期字符串
     * 
     * @param formart 日期格式
     * @return 当前日期字符串
     */
    public static String getDateFormatStr(String formart) {
        return new SimpleDateFormat(formart).format(new java.util.Date());
    }
    
    public static String getLocalDateNowStr(String formart) {
        return localDateformatString(LocalDate.now(),formart);
    }

    /**
     * 日期加年
     * 
     * @param date 日期
     * @param spans 增加数量
     * @return 增加X年后的日期
     */
    public static Date addYear(Date date, int spans) {
        return addDate(date, Calendar.YEAR, spans);
    }

    /**
     * 日期加月
     * 
     * @param date 日期
     * @param spans 增加数量
     * @return 加月后的日期
     */
    public static Date addMonth(Date date, int spans) {
        return addDate(date, Calendar.MONTH, spans);
    }

    /**
     * 日期加天
     * 
     * @param date 日期
     * @param spans 增加数量
     * @return 加天后的日期
     */
    public static Date addDay(Date date, int spans) {
        return addDate(date, Calendar.DAY_OF_MONTH, spans);
    }

    /**
     * 日期加小时
     * 
     * @param date 日期
     * @param spans 增加数量
     * @return 加小时后的日期
     */
    public static Date addHour(Date date, int spans) {
        return addDate(date, Calendar.HOUR_OF_DAY, spans);
    }

    /**
     * 日期加分钟
     * 
     * @param date 日期
     * @param spans 增加数量
     * @return 加分钟后的日期
     */
    public static Date addMinute(Date date, int spans) {
        return addDate(date, Calendar.MINUTE, spans);
    }

    /**
     * 日期加秒
     * 
     * @param date 日期
     * @param spans 增加数量
     * @return 加秒后的日期
     */
    public static Date addSecond(Date date, int spans) {
        return addDate(date, Calendar.SECOND, spans);
    }

    /**
     * 日期加法计算
     * 
     * @param date 日期
     * @param type 增加类型
     * @param spans 增加数量
     * @return 加法计算后的日期
     */
    public static Date addDate(Date date, int type, int spans) {
        Calendar inputCalendar = Calendar.getInstance();
        inputCalendar.setTime(date);
        inputCalendar.add(type, spans);
        return inputCalendar.getTime();
    }

    /**
     * 获取当前day of month
     * 
     * @return String
     */
    public static String getCurrentDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        return String.valueOf(calendar.get(Calendar.DAY_OF_MONTH));
    }

    /**
     * 获取当前月份数字
     * 
     * @return String
     */
    public static String getCurrentMonth() {
        Calendar calendar = Calendar.getInstance();
        return String.valueOf(calendar.get(Calendar.MONTH) + 1);
    }

    /**
     * 获取当前小时
     * 
     * @return String
     */
    public static String getCurrentHour() {
        Calendar calendar = Calendar.getInstance();
        return String.valueOf(calendar.get(Calendar.HOUR_OF_DAY));
    }
    
    /**
     * 获取当前年
     * 
     * @return String
     */
    public static String getCurrentYear() {
        Calendar calendar = Calendar.getInstance();
        return String.valueOf(calendar.get(Calendar.YEAR));
    }

    /**
     * 获取当前时间，字符串类型，格式（yyyy-mm-dd）
     * 
     * @return String
     */
    public static String getCurrentDateString() {
        return getDateFormatStr(PATTEN_YMD);
    }

    /**
     * 获取当前时间， 日期类型
     * 
     * @return java.util.Date
     */
    public static Date getCurrentDate() {
        return new Date();
    }

    /**
     * 判断是否是有效日期
     * 
     * @param date 判断日期
     * @return 是否有效日期
     */
    public static boolean checkIsActiveDate(String date) {
        //先验证基本格式是否正确
        if (!StringsUtils.matches(date, DATE_REG_SIMPLE)) {
            return false;
        }
        //验证复杂格式是否正确
        if (StringsUtils.isNotEmpty(date) && date.contains(DEFAULT_SEPERATOR)) {
            String dateNoSeprator = date.replaceAll(DEFAULT_SEPERATOR, "");
            return StringsUtils.matches(dateNoSeprator, DATE_REG);
        }
        return false;
    }

    /**
     * 比较两个日期大小
     * 
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 开始日期早于结束日期，返回true。否则返回false。相等，返回false
     */
    public static boolean dateCompare(Date startDate, Date endDate) {
        if (endDate.compareTo(startDate)==1) {
            return true;
        }
        return false;
    }

    /**
     * 比较两个日期是否相等
     * 
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 开始日期等于结束日期，返回true。否则返回false
     */
    public static boolean dateEqual(Date startDate, Date endDate) {
        if (startDate.compareTo(endDate) == 0) {
            return true;
        }
        return false;
    }
    
    /**
     * 返回指定日期的年
     * 
     * @param date 指定的日期
     * @return 指定日期的年
     */
    public static String getYearFromDate(String date) {
        if (!checkIsActiveDate(date)) {
            return "";
        }
        //日期格式化
        try {
            Date dateTmp = getDateParser(PATTEN_YMD).parse(date);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(dateTmp);
            return String.valueOf(calendar.get(Calendar.YEAR));
        } catch (ParseException e) {
        	log.error("日期格式转换错误",e);
            return "";
        }
    }

    /**
     * 返回指定日期的月
     * 
     * @param date 指定的日期
     * @return 指定日期的月
     */
    public static String getMonthFromDate(String date) {
        if (!checkIsActiveDate(date)) {
            return "";
        }
        //日期格式化
        try {
            Date dateTmp = getDateParser(PATTEN_YMD).parse(date);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(dateTmp);
            return String.valueOf(calendar.get(Calendar.MONTH) + 1);
        } catch (ParseException e) {
        	log.error("日期格式转换错误",e);
            return "";
        }
    }

    /**
     * 返回指定日期的日
     * 
     * @param date 指定日期
     * @return 指定日期的日
     */
    public static String getDayFromDate(String date) {
        if (!checkIsActiveDate(date)) {
            return "";
        }
        //日期格式化
        try {
            Date dateTmp = getDateParser(PATTEN_YMD).parse(date);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(dateTmp);
            return String.valueOf(calendar.get(Calendar.DAY_OF_MONTH));
        } catch (ParseException e) {
        	log.error("日期格式转换错误",e);
            return "";
        }
    }
    
    /**
	 * 根据日期取得星期几
	 * @param dt
	 * @return
	 */
    public static String getWeekOfDate(Date dt) {
        String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(dt);

        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0)
            w = 0;

        return weekDays[w];
    }
    
    /**
     * 获取某月的第一天的0点0分1秒
     * 
     * @param pattern 日期格式
     * @return 转换后的日期字符串
     */
    public static Date getFirstdayOfMonth(Date theDate) {
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(theDate);
    	//将月至1
    	calendar.set(Calendar.DAY_OF_MONTH, 1);
    	//将小时至0
    	calendar.set(Calendar.HOUR_OF_DAY, 0);
    	//将分钟至0
    	calendar.set(Calendar.MINUTE, 0);
    	//将秒至1
    	calendar.set(Calendar.SECOND,1);
    	//将毫秒至0
    	calendar.set(Calendar.MILLISECOND, 0);

    	return calendar.getTime();
    }
    
    
    /**
     * 获取某日的0点0分1秒
     * 
     * @param pattern 日期格式
     * @return 转换后的日期字符串
     */
    public static Date getFirstTimeOfDay(Date theDate) {
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(theDate);
    	//将小时至0
    	calendar.set(Calendar.HOUR_OF_DAY, 0);
    	//将分钟至0
    	calendar.set(Calendar.MINUTE, 0);
    	//将秒至1
    	calendar.set(Calendar.SECOND,1);
    	//将毫秒至0
    	calendar.set(Calendar.MILLISECOND, 0);

    	return calendar.getTime();
    }
    
    
    /**
    * <li>功能描述：时间相减得到天数
    * @param beginDateStr
    * @param endDateStr
    * @return
    * long 
    * @author Administrator
    */
    public static long getDaySub(Date beginDate,Date endDate)
    {
        return  (endDate.getTime()-beginDate.getTime())/(24*60*60*1000);
    }
    
    
    /**
     * <li>功能描述：时间相减得到分钟数（向上取整）
     * @param beginDateStr
     * @param endDateStr
     * @return
     * long 
     * @author Administrator
     */
     public static int getMinuteSubUp(Date beginDate,Date endDate)
     {
    	 if(beginDate == null || endDate == null)
    	 {
    		 return 0;
    	 }
    	 BigDecimal second = new BigDecimal((endDate.getTime()-beginDate.getTime())/1000);
    	 
    	 return second.divide(new BigDecimal(60),0,BigDecimal.ROUND_UP).intValue();
     }
    
    /**
     * <li>功能描述：时间相减得到年数（四舍五入）
     * @param beginDateStr
     * @param endDateStr
     * @return
     * long 
     * @author Administrator
     */
     public static int getYearSub(Date beginDate,Date endDate)
     {
    	 if(beginDate == null || endDate == null)
    	 {
    		 return 0;
    	 }
    	 BigDecimal second = new BigDecimal((endDate.getTime()-beginDate.getTime())/1000);
    	 
    	 return second.divide(new BigDecimal((24*60*60*365)),0,BigDecimal.ROUND_HALF_UP).intValue();
     }

     /**
      * 返回指定格式的日期字符串
      * 
      * @param date 待转化的日期数据
      * @param dateFm 日期格式
      * @return 指定格式的日期字符串
      */
     public static String localDateYMDString(LocalDate date) {
         if (null == date) {
         	date=LocalDate.now();
         }
         String dateStr = localDateformatString(date,PATTEN_YMD);
         return dateStr;
     }
     
     


}
