import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;

import org.apache.commons.lang3.time.DateFormatUtils;

/**
 * 时间工具类
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

    public static String YYYY_MM_DD = "yyyy-MM-dd";

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    /**
     * 获取当前Date型日期
     * @return Date() 当前日期
     */
    public static Date getNowDate() {
        return new Date();
    }

    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     * @return String
     */
    public static String getDate() {
        return dateTimeNow(YYYY_MM_DD);
    }
    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd HH:mm:ss
     * @return String
     */
    public static final String getTime() {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }
    /**
     * 获取当前日期, 默认格式为yyyyMMddHHmmss
     * @return String
     */
    public static final String dateTimeNow() {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }
   /**
    * 根据格式获取当前日期或时间
    * @param  format  数据格式
    * @return String
    * */
    public static final String dateTimeNow(final String format) {
        return parseDateToStr(format, new Date());
    }
    /**
     * 日期转换 Date转String  格式
     * @param date  日期
     * @return String  yyyy-MM-dd
     * */
    public static final String dateTime(final Date date) {
        return parseDateToStr(YYYY_MM_DD, date);
    }
    /**
     * 日期转换 Date转String  格式
     * @param date  日期
     * @param format  数据格式
     * @return String
     * */
    public static final String parseDateToStr(final String format, final Date date) {
        return new SimpleDateFormat(format).format(date);
    }


    /**
     *   获取当前日期路径 即年/月/日
     */
    public static final String datePath() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }


    /**
     * 日期型字符串转化为日期 格式
     * @param str  日期字符串
     * @return  Date
     */
    public static Date parseDate(Object str) {
        if (str == null) {
            return null;
        }
        try {
            return parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 日期型字符串转化为日期 格式
     * @return  Date
     */
    public static Date getServerStartDate() {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 计算相差天数
     * @param  date1  前日期
     * @param date2   后日期
     * @return  int  天数
     */
    public static int differentDaysByMillisecond(Date date1, Date date2) {
        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
    }

    /**
     * 计算相差天数
     * @param  endDate  后日期
     * @param nowDate   当前日期
     * @return  String
     */
    public static String getDatePoor(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        return day + "天" + hour + "小时" + min + "分钟";
    }

    /**
     * LocalDateTime 转 Date
     * @param temporalAccessor  LocalDateTime类型日期
     * @return Date
     */
    public static Date toDate(LocalDateTime temporalAccessor) {
        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
        return Date.from(zdt.toInstant());
    }

    /**
     * LocalDate 转 Date
     * @param temporalAccessor  LocalDate类型日期
     * @return Date
     */
    public static Date toDate(LocalDate temporalAccessor) {
        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
        return Date.from(zdt.toInstant());
    }
    
    /**
     *  获取前几天/当前日期/后几天
     * @param count  天数  正数为后  负数为前  零为当前
     * @return Date
     */
    public static Date getDate(int count) {
        SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM_DD);
        Calendar calendar = Calendar.getInstance();
        Date date = new Date();
        calendar.setTime(date);
        int day = calendar.get(Calendar.DATE);
        calendar.set(Calendar.DATE, day + count);
        return calendar.getTime();
    }


    /**
     *  获取前几小时/当前时间/后几小时
     * @param count   正数为后  负数为前  零为当前
     * @return String
     */
    public static Date getBeforeHour( int count) {
        Calendar calendar = Calendar.getInstance();
        Date date = new Date();
        calendar.setTime(date);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        calendar.set(Calendar.HOUR_OF_DAY, hour + count);
        return calendar.getTime();
    }
    
    /**
     *  获取前几天/当前日期/后几天
     * @param count  天数  正数为后  负数为前  零为当前
     * @return Date
     */
    public static String getDateString(int count) {
        SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM_DD);
        Calendar calendar = Calendar.getInstance();
        Date date = new Date();
        calendar.setTime(date);
        int day = calendar.get(Calendar.DATE);
        // 后一天为 +1   前一天 为-1
        calendar.set(Calendar.DATE, day + count);
        return sdf.format(calendar.getTime());
    }
    
    /**
     * 根据传输值 获取年份 返回String 类型年份
     * @param count 0 为当前年份  负数:为前几年  正数:为后几年
     * @return  String
     */
    /**
     *  获取前几年/当前年份/后几年
     * @param count   正数为后  负数为前  零为当前
     * @return String
     */
    public static String getYear(int count) {
        SimpleDateFormat sdf = new SimpleDateFormat(YYYY);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.YEAR,count);
        Date date = calendar.getTime();
        return sdf.format(date);
    }
    
    /**
     *  获取前几年/当前年份/后几年
     * @param count    正数为后  负数为前  零为当前
     * @return Date
     */
    public static Date getDateYear(int count) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.YEAR,count);
        return calendar.getTime();
    }
    
    /**
     *  获取前几月/当前月/后几月
     * @param count    正数为后  负数为前  零为当前
     * @return int
     */
    public static int getMonth(int count) {
        Calendar calendar = Calendar.getInstance();
        int month = (calendar.get(Calendar.MONTH) + 1 )+count;
        if(month > 12 || month == 0){
            month = 12;
        }
        if(month == -1){
            month = 11;
        }
        if(month == -2){
            month = 10;
        }
        if(month == -3){
            month = 9;
        }
        if(month == -4){
            month = 8;
        }
        if(month == -5){
            month = 7;
        }
        if(month == -6){
            month = 6;
        }
        if(month == -7){
            month = 5;
        }
        if(month == -8){
            month = 4;
        }
        if(month == -9){
            month = 3;
        }
        if(month == -10){
            month = 2;
        }
        if(month <= -11){
            month = 1;
        }
        return month;
    }
    
    /**
     * 根据传输值 获取季度 返回String类型季度
     * @param month  月份
     * @return  date
     */
    public static String getQuarter(int month) {
        if(month < 1 || month > 12){
            return "请输入正确月份";
        }
        int quarter = (month -1)/3 + 1;
        return String.valueOf(quarter);
    }
   
    /**
     * 计算相差分钟数
     * @param  endDate  后日期
     * @param nowDate   当前日期
     * @return  Long
     */
    public static Long getDatePoorMinute(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少分钟
        return diff % nd % nh / nm;
    }

    /**
     *  获取前几天/当前日期/后几天
     * @param beforeDay  天数  正数为后  负数为前  零为当前
     * @return String
     */
    public static String getBeforeDay(Integer beforeDay) {
        Date date = new Date();
        //将时间格式化成yyyy-MM-dd HH:mm:ss的格式
        SimpleDateFormat format = new SimpleDateFormat("MM.dd");
        //创建Calendar实例
        Calendar cal = Calendar.getInstance();
        //设置当前时间
        cal.setTime(date);
        //同理增加一天的方法:
        cal.add(Calendar.DATE, beforeDay);
        String day = format.format(cal.getTime());
        return day;
    }

    /**
     *  日期 或 时间添加
     * @param type 1 分钟 2小时 3天 4月
     * @param time 原始时间
     * @param addTime 添加时间维度 type 1时为分钟 2为日期 计算时需转毫秒
     * @return  Date
     * */
    public static Date timeAdd(Date time, int type,int addTime) {

        Date afterDate;
        if(type == 1){
            afterDate =  new Date(time.getTime() + addTime * 60000);
        }else {
            afterDate =  new Date(time.getTime() + addTime * 3600000*24);
        }
        return afterDate;
    }

    /**
     *   判断日期是否属于当前年份
     * @param time  日期数
     * @return boolean
     */
    public static boolean isCurrentYear(Date time) {
        Calendar calendar = Calendar.getInstance();
        int currentYear = calendar.get(Calendar.YEAR);
        calendar.setTime(time);
        int getYear = calendar.get(Calendar.YEAR);
        if (currentYear == getYear) {
             return true;
        } else {
            return  false;
        }
    }

    /**
     *  增加或减少月份
     * @param count    正数为后  负数为前  零为当前
     * @param time  日期
     * @return String
     */
    public static String changeMonth(Date time, int count) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.add(Calendar.MONTH, count);
        Date newDate = calendar.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat(YYYY_MM);
        return sdf.format(newDate);
    }
}