package com.bcxin.signature.util;

import com.bcxin.signature.util.common.StringUtil;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * <b> 日期通用处理工具类 </b>
 * @author ZXF
 * @create 2021/03/22 0022 10:31
 * @version
 * @注意事项 </b>
 */
public class DateUtil extends DateUtils {
	
	private static Logger logger = LoggerFactory.getLogger(DateUtil.class);

	/** 毫秒 */
	public final static long MS = 1;
	/** 每秒钟的毫秒数 */
	public final static long SECOND_MS = MS * 1000;
	/** 每分钟的毫秒数 */
	public final static long MINUTE_MS = SECOND_MS * 60;
	/** 每小时的毫秒数 */
	public final static long HOUR_MS = MINUTE_MS * 60;
	/** 每天的毫秒数 */
	public final static long DAY_MS = HOUR_MS * 24;
	/** 每月的毫秒数 */
	public final static long MONTH_MS = DAY_MS * 30;
	/** 每年的毫秒数 */
	public final static long YEAR_MS = MONTH_MS * 12;

	public static final String FORMAT1 = "yyyy-MM-dd HH:mm:ss";
	public static final String FORMAT2 = "yyyy-MM-dd";

	/**
	 * 当前时间，格式 yyyy-MM-dd HH:mm:ss
	 * @return 当前时间的标准形式字符串
	 */
	public static String now() {
		return formatDateTime(new Date());
	}
	
	/**
	 * 格式 yyyy-MM-dd HH:mm:ss
	 * @param date 被格式化的日期
	 * @return 格式化后的日期
	 */
	public static String formatDateTime(Date date) {
		SimpleDateFormat NORM_DATETIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return NORM_DATETIME_FORMAT.format(date);
	}
	/**
	 * 转换为时间（天,时:分:秒.毫秒）
	 * @param timeMillis
	 * @return
	 */
    public static String formatDateTime(long timeMillis){
		long day = timeMillis/(24*60*60*1000);
		long hour = (timeMillis/(60*60*1000)-day*24);
		long min = ((timeMillis/(60*1000))-day*24*60-hour*60);
		long s = (timeMillis/1000-day*24*60*60-hour*60*60-min*60);
		long sss = (timeMillis-day*24*60*60*1000-hour*60*60*1000-min*60*1000-s*1000);
		return (day>0?day+",":"")+hour+":"+min+":"+s+"."+sss;
    }
	/**
	 * 获取当前日期时间
	 * @return
	 */
	public static String getCurrentDateTime() {
		return getCurrentDateTime(FORMAT1);
	}
	/**
	 * 获取当前日期
	 * @return
	 */
	public static String getCurrentDate() {
		return getCurrentDateTime(FORMAT2);
	}
	/**
	 * 当前日期，格式 yyyy-MM-dd
	 * @return 当前日期的标准形式字符串
	 */
	/**
	 * 根据特定格式获取当前时间
	 * @param format
	 * @return
	 */
	public static String getCurrentDateTime(String format) {
		SimpleDateFormat df = new SimpleDateFormat(format);
		return df.format(new Date());
	}
	public static String today() {
		return formatDate(new Date());
	}

	/**
	 * 得到当前日期字符串 格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
	 */
	public static String getDate(String pattern) {
		return DateFormatUtils.format(new Date(), pattern);
	}
	/**
	 * 获取过去的天数
	 * @param date
	 * @return
	 */
	public static long pastDays(Date date) {
		long t = System.currentTimeMillis()-date.getTime();
		return t/(24*60*60*1000);
	}
	/**
	 * 根据特定格式格式化日期
	 * @param date 被格式化的日期
	 * @param format 格式
	 * @return 格式化后的字符串
	 */
	public static String format(Date date, String format) {
		return new SimpleDateFormat(format).format(date);
	}

	/**
	 * 格式化为Http的标准日期格式
	 * @param date 被格式化的日期
	 * @return HTTP标准形式日期字符串
	 */
	public static String formatHttpDate(Date date) {
		SimpleDateFormat HTTP_DATETIME_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
		return HTTP_DATETIME_FORMAT.format(date);
	}

	/**
	 * 格式 yyyy-MM-dd 
	 * @param date 被格式化的日期
	 * @return 格式化后的字符串
	 */
	public static String formatDate(Date date) {
		SimpleDateFormat NORM_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
		return NORM_DATE_FORMAT.format(date);
	}

	/**
	 * 将特定格式的日期转换为Date对象
	 * @param dateString 特定格式的日期
	 * @param format 格式，例如yyyy-MM-dd
	 * @return 日期对象
	 */
	public static Date parse(String dateString, String format) {
		if(StringUtil.isBlank(dateString)){
			SimpleDateFormat NORM_DATETIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			dateString = NORM_DATETIME_FORMAT.format(new Date());
		}
		try {
			return (new SimpleDateFormat(format)).parse(dateString);
		} catch (ParseException e) {
			logger.error("Parse " + dateString + " with format " + format + " error!", e);
		}
		return null;
	}

	/**
	 * 格式yyyy-MM-dd HH:mm:ss
	 * @param dateString 标准形式的时间字符串
	 * @return 日期对象
	 */
	public static Date parseDateTime(String dateString) {
		SimpleDateFormat NORM_DATETIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			return NORM_DATETIME_FORMAT.parse(dateString);
		} catch (ParseException e) {
			logger.error("Parse " + dateString + " with format " + NORM_DATETIME_FORMAT.toPattern() + " error!", e);
		}
		return null;
	}

	public static Date matchFormatByLength(String dateString) {
		SimpleDateFormat NORM_DATETIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			int num = dateString.length();
			if(num == 16){
				SimpleDateFormat NORM_DATETIME_FORMAT1 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
				return NORM_DATETIME_FORMAT1.parse(dateString);
			}else if(num == 19){
				return NORM_DATETIME_FORMAT.parse(dateString);
			}else {
				SimpleDateFormat NORM_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
				return NORM_DATE_FORMAT.parse(dateString);
			}
		} catch (ParseException e) {
			logger.error("Parse " + dateString + " with format " + NORM_DATETIME_FORMAT.toPattern() + " error!", e);
		}
		return null;
	}

	/**
	 * 格式yyyy-MM-dd
	 * @param dateString  标准形式的日期字符串
	 * @return  标准形式的日期字符串
	 */
	public static Date parseDate(String dateString) {
		SimpleDateFormat NORM_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
		try {
			return NORM_DATE_FORMAT.parse(dateString);
		} catch (ParseException e) {
			logger.error("Parse " + dateString + " with format " + NORM_DATE_FORMAT.toPattern() + " error!", e);
		}
		return null;
	}

	/**
	 * 
	 * 获取指定日期偏移指定时间后的时间
	 * 
	 * @param date
	 *            基准日期
	 * 
	 * @param calendarField
	 *            偏移的粒度大小（小时、天、月等）使用Calendar中的常数
	 * 
	 * @param offsite
	 *            偏移量，正数为向后偏移，负数为向前偏移
	 * 
	 * @return 偏移后的日期
	 * 
	 */
	public static Date getOffsiteDate(Date date, int calendarField, int offsite) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(calendarField, offsite);
		return cal.getTime();
	}

	/**
	 * 
	 * 判断两个日期相差的时长<br/>(列：1年前7月25日)
	 * 
	 * 返回 minuend - subtrahend 的差
	 * 
	 * @param subtrahend
	 *            减数日期
	 * 
	 * @param minuend
	 *            被减数日期
	 * 
	 * @return 日期差
	 * 
	 */
	public static String dateDiff(Date subtrahend, Date minuend) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(subtrahend);
		long diff = minuend.getTime() - subtrahend.getTime();
		if(diff <= HOUR_MS)
			return diff / MINUTE_MS + "分钟前";
		else if(diff <= DAY_MS)
			return diff / HOUR_MS + "小时" + (diff % HOUR_MS / MINUTE_MS) + "分钟前";
		else if(diff <= DAY_MS * 2)
			return "昨天" + calendar.get(Calendar.HOUR_OF_DAY) + "点"+ calendar.get(Calendar.MINUTE) + "分";
		else if(diff <= DAY_MS * 3)
			return "前天" + calendar.get(Calendar.HOUR_OF_DAY) + "点"+ calendar.get(Calendar.MINUTE) + "分";
		else if(diff <= MONTH_MS)
			return diff / DAY_MS + "天前" + calendar.get(Calendar.HOUR_OF_DAY) + "点"+ calendar.get(Calendar.MINUTE) + "分";
		else if(diff <= YEAR_MS)
			return diff / MONTH_MS + "个月" + (diff % MONTH_MS) / DAY_MS + "天前" + calendar.get(Calendar.HOUR_OF_DAY) + "点"+ calendar.get(Calendar.MINUTE) + "分";
		else
			return diff / YEAR_MS + "年前" + (calendar.get(Calendar.MONTH) + 1) + "月"+ calendar.get(Calendar.DATE) + "日";
	}
	
	/**
	 * 距离截止日期还有多长时间
	 * 
	 * @param date
	 * @return
	 */
	public static String fromDeadline(Date date) {
		long deadline = date.getTime();
		long now = System.currentTimeMillis();
		long remain = deadline - now;
		if (remain <= HOUR_MS)
			return "只剩下" + remain / MINUTE_MS + "分钟";
		else if (remain <= DAY_MS)
			return "只剩下" + remain / HOUR_MS + "小时"
					+ (remain % HOUR_MS / MINUTE_MS) + "分钟";
		else {
			long day = remain / DAY_MS;
			long hour = remain % DAY_MS / HOUR_MS;
			long minute = remain % DAY_MS % HOUR_MS / MINUTE_MS;
			return "只剩下" + day + "天" + hour + "小时" + minute + "分钟";
		}
	}
	/**
	 * 获取过去的分钟
	 * @param date
	 * @return
	 */
	public static long pastMinutes(Date date) {
		long t = System.currentTimeMillis()-date.getTime();
		return t/(60*1000);
	}
	
	/**获取时间戳格式,返回格式为YYYY-MM-DD HH:MM:SS:SSS*/
	public static Timestamp getTimestamp() {
		Date date = new Date();
		Timestamp nousedate = new Timestamp(date.getTime());
		return nousedate;
	}

	/**
	 * <b> 获取精确到秒的时间戳 </b>
	 * @author ZXF
	 * @create 2021/11/22 0022 17:28
	 * @version
	 * @注意事项 </b>
	 */
	public static int getSecondTimestamp(Date date){
		if (null == date) {
			return 0;
		}
		String timestamp = String.valueOf(date.getTime()/1000);
		return Integer.valueOf(timestamp);
	}

	/**String转Date*/
	public static Date convertString2Date(String time) {
		Date date = new Date();
		// 注意format的格式要与日期String的格式相匹配
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			date = sdf.parse(time);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return date;
	}

	/**计算两个Date数据的大小*/
	public static long calculateTwoDateDvalue(Date date1, Date date2) {
		Calendar cal = Calendar.getInstance();// 定义日历类型的变量
		// 将日期型的日期设置成日历型日期
		cal.setTime(date1);// 应归还日期
		long date1value = cal.getTimeInMillis();// 定义日历类型的变量
		cal.setTime(date2);// 应归还日期
		long date2value = cal.getTimeInMillis();// 定义日历类型的变量
		return date1value - date2value;
	}


	public static Date getDayStart(Date currentDate) {
		Date result = null;

		Calendar current = Calendar.getInstance();
		current.setTime(currentDate);
		current.set(Calendar.HOUR_OF_DAY, 0);
		current.clear(Calendar.MILLISECOND);
		current.clear(Calendar.MINUTE);
		current.clear(Calendar.SECOND);
		result = current.getTime();

		return result;
	}
}
