package org.springblade.common.utils;

import lombok.extern.slf4j.Slf4j;

import java.sql.Timestamp;
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.util.Calendar;
import java.util.Date;
import java.util.Objects;

/**
 * @author
 * @date 2020-10-13 20:56:49
 * @description 时间类工具类
 */
@Slf4j
public class DateTimeUtil {

    /**
     * 默认时间格式
     */
    private static ThreadLocal<SimpleDateFormat> dataFormat =
            ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

    private static ThreadLocal<SimpleDateFormat> yyyyMMddFormat =
            ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));

	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 一天的毫秒数
     */
    private static final int DAY_MILLISECOND = 1000 * 3600 * 24;

	public static void main(String[] args) {
		System.out.println(differentDays(getYearFirstDay("2022"), new Date()));
	}

	private static int differentDays(Date date1,Date date2) {
		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(date1);

		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(date2);
		int day1= cal1.get(Calendar.DAY_OF_YEAR);
		int day2 = cal2.get(Calendar.DAY_OF_YEAR);

		int year1 = cal1.get(Calendar.YEAR);
		int year2 = cal2.get(Calendar.YEAR);
		if(year1 != year2) {//同一年
			int timeDistance = 0 ;
			for(int i = year1 ; i < year2 ; i ++)
			{
				if(i%4==0 && i%100!=0 || i%400==0)    //闰年
				{
					timeDistance += 366;
				}
				else    //不是闰年
				{
					timeDistance += 365;
				}
			}

			return timeDistance + (day2-day1) ;
		} else {// 不同年
			System.out.println("判断day2 - day1 : " + (day2-day1));
			return day2-day1;
		}
	}

    /**
     * 指定时分秒
     *
     * @param hour   时间
     * @param minute 分钟
     * @param second 秒
     * @return 指定的时间
     */
    public static Date time(int hour, int minute, int second) {
        return time(new Date(), hour, minute, second);
    }

    public static SimpleDateFormat format() {
        return dataFormat.get();
    }

    public static SimpleDateFormat yyyyMMdd() {
        return yyyyMMddFormat.get();
    }

    /**
     * 指定时分秒
     *
     * @param date   操作对象
     * @param hour   时间
     * @param minute 分钟
     * @param second 秒
     * @return 指定的时间
     */
    public static Date time(Date date, int hour, int minute, int second) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, minute);
        calendar.set(Calendar.SECOND, second);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static String getYear() {
        Calendar can = Calendar.getInstance();
        can.setTime(new Date());//设置当前日期
        String yearStr = can.get(Calendar.YEAR) + "";//获取年份
        return yearStr;
    }

    public static String getDate() {
        String format = format().format(new Date());
        return format;
    }

    public static String getFormat() {
        return yyyyMMdd().format(new Date());
    }

	/**
	 * 获取当前小时的时间
	 * @param date
	 * @return java.util.Date
	 */
	public static Date nowTimeHour(Date date, int minute, int second) {
		Calendar calendar = Calendar.getInstance();
		/* HOUR_OF_DAY 指示一天中的小时 */
		calendar.setTime(date);
		calendar.set(Calendar.MINUTE, minute);
		calendar.set(Calendar.SECOND, second);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}


    public static String getDateFormat(Date date) {
        return dataFormat.get().format(date);
    }

    /**
     * @param date    日期
     * @param format1 传入的日期的格式
     * @param format1 需要转成指定的日期格式
     * @return 返回指定格式的时间字符串
     */
    public static String getFormatStrDate(String date, String format1, String format2) {
        SimpleDateFormat sdf = new SimpleDateFormat(format1);
        String strDate = null;
        try {
            Date parse = sdf.parse(date);
            SimpleDateFormat sdf1 = new SimpleDateFormat(format2);
            strDate = sdf1.format(parse);
        } catch (ParseException e) {
            log.error("getFormatStrDate fail: " + e.toString());
        }
        return strDate;
    }


    /**
     * @param date   日期
     * @param format 日期格式
     * @return 返回指定格式的时间字符串
     */
    public static String getFormatStrDate(Date date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     * 计算日期偏移
     *
     * @param field  偏移类型
     * @param amount 偏移量
     * @return 便宜后的时间
     */
    public static Date add(int field, int amount) {
        Calendar can = Calendar.getInstance();
        can.add(field, amount);
        return can.getTime();
    }

    public static Date add(Date flag, int field, int amount) {
        Objects.requireNonNull(flag);
        Calendar can = Calendar.getInstance();
        can.setTime(flag);
        can.add(field, amount);
        return can.getTime();
    }

    /**
     * 指定日期的最后一刻
     *
     * @param time 不传表示当天
     * @return
     */
    public static Date lastestTime(Date time) {
        Calendar can = Calendar.getInstance();
        can.setTime((time == null) ? new Date() : time);
        can.set(Calendar.HOUR_OF_DAY, 23);
        can.set(Calendar.MINUTE, 59);
        can.set(Calendar.SECOND, 59);
        can.set(Calendar.MILLISECOND, 999);
        return can.getTime();
    }

    /**
     * 一天的最早时间
     *
     * @param time 不传表示当前
     * @return
     */
    public static Date earliestTime(Date time) {
        Calendar can = Calendar.getInstance();
        can.setTime((time == null) ? new Date() : time);
        can.set(Calendar.HOUR_OF_DAY, 0);
        can.set(Calendar.MINUTE, 0);
        can.set(Calendar.SECOND, 0);
        can.set(Calendar.MILLISECOND, 0);
        return can.getTime();
    }

    /**
     * 获取指定的时间所属月份的第一天的零点
     *
     * @param date 指定的时间
     * @return 月份的第一天不传表示当月第一天
     */
    public static Date firstDay(Date date) {
        Calendar can = Calendar.getInstance();
        can.setTime((date == null) ? new Date() : date);
        can.set(Calendar.DAY_OF_MONTH, 1);
        can.set(Calendar.SECOND, 0);
        can.set(Calendar.MINUTE, 0);
        can.set(Calendar.HOUR_OF_DAY, 0);
        can.set(Calendar.MILLISECOND, 0);
        return can.getTime();
    }

    /**
     * 获取指定年份第一天
     *
     * @param year
     * @return
     */
    public static Date getYearFirstDay(String year) {
        Calendar can = Calendar.getInstance();
        can.set(Calendar.YEAR, Integer.parseInt(year));
        can.set(Calendar.MONTH, 0);
        can.set(Calendar.DAY_OF_MONTH, 1);
        can.set(Calendar.SECOND, 0);
        can.set(Calendar.MINUTE, 0);
        can.set(Calendar.HOUR_OF_DAY, 0);
        can.set(Calendar.MILLISECOND, 0);
        Date time = can.getTime();
        return time;
    }

    /**
     * 获取指定年份第一天
     *
     * @param year
     * @return
     */
    public static Date getYearLastDay(String year) {
        Calendar can = Calendar.getInstance();
        can.set(Calendar.YEAR, Integer.parseInt(year));
        can.set(Calendar.MONTH, 11);
        can.set(Calendar.DAY_OF_MONTH, 31);
        can.set(Calendar.HOUR_OF_DAY, 23);
        can.set(Calendar.MINUTE, 59);
        can.set(Calendar.SECOND, 59);
        Date time = can.getTime();
        return time;
    }

    /**
     * 获取所传月份的最后一天的最后一秒
     *
     * @param date 指定的时间
     * @return 月份的最后一天的最后一秒
     */
    public static Date lastDay(Date date) {
        Calendar can = Calendar.getInstance();
        can.setTime((date == null) ? new Date() : date);
        can.set(Calendar.DAY_OF_MONTH, can.getActualMaximum(Calendar.DAY_OF_MONTH));
        can.set(Calendar.HOUR_OF_DAY, 23);
        can.set(Calendar.SECOND, 59);
        can.set(Calendar.MINUTE, 59);
        can.set(Calendar.MILLISECOND, 999);
        return can.getTime();
    }

	/**
	 * 获取所传月份的第一天
	 *
	 * @param month 指定的月份
	 * @return 月份的第一天
	 */
	public static Date getMonthFirstDay(Integer month) {
		Calendar can = Calendar.getInstance();
		can.set(Calendar.MONTH, month);
		can.set(Calendar.DAY_OF_MONTH, 1);
		can.set(Calendar.HOUR_OF_DAY, 00);
		can.set(Calendar.SECOND, 00);
		can.set(Calendar.MINUTE, 00);
		can.set(Calendar.MILLISECOND, 000);
		return can.getTime();
	}

    public static Date date(String date) {
        try {
            return dataFormat.get().parse(date);
        } catch (ParseException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * 获取指定日期的时间
     *
     * @param date 指定的日期，不指定表示当前
     * @return 时间
     */
    public static LocalTime getTime(Date date) {
        return toLocalTime(date);
    }

    public static LocalTime getTime(String date) {
        return toLocalTime(date(date));
    }

    /**
     * 获取指定日期的年月日
     *
     * @param date 指定的日期，不指定表示当前
     * @return localDate
     */
    public static LocalDate getDate(Date date) {
        if (date == null) {
            return LocalDate.now();
        } else {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            return LocalDate.of(c.get(Calendar.YEAR), c.get(Calendar.MONTH) + 1, c.get(Calendar.DAY_OF_MONTH));
        }
    }

    public static LocalDate getDate(String date) {
        return getDate(date(date));
    }

    /**
     * 获取两个时间之间的差值
     *
     * @param end   结束时间
     * @param start 开始时间
     * @return 返回值
     */
    public static int diffDay(Date end, Date start) {
        Objects.requireNonNull(end);
        Objects.requireNonNull(start);
        end = earliestTime(end);
        start = earliestTime(start);
        return Long.valueOf((end.getTime() - start.getTime()) / DAY_MILLISECOND).intValue();
    }

    /**
     * 判断两个时间相差多少个月
     *
     * @param end   结束时间
     * @param start 开始时间
     * @return 相差的月份
     */
    public static int diffMonth(Date end, Date start) {
        Objects.requireNonNull(end);
        Objects.requireNonNull(start);
        Calendar can = Calendar.getInstance();
        can.setTime(end);
        int ey = can.get(Calendar.YEAR);
        int em = can.get(Calendar.MONTH);

        can.setTime(start);
        return (ey - can.get(Calendar.YEAR)) * 12 + (em - can.get(Calendar.MONTH));
    }

    public static LocalDate toLocalDate(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static LocalDateTime toLocalDateTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static LocalTime toLocalTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
    }

    public static Date toDate(LocalDate date) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, date.getYear());
        c.set(Calendar.MONTH, date.getMonthValue() - 1);
        c.set(Calendar.DAY_OF_MONTH, date.getDayOfMonth());
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    }

    public static Date toDate(LocalDateTime date) {
        return Date.from(date.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static String getMidMonth(int currentMonth, String format, Boolean flog) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());// 设置当前日期
        if (flog) {
            calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + 1);
        }
        calendar.set(Calendar.MONTH, currentMonth - 1);
        calendar.set(Calendar.DAY_OF_MONTH, 15);//设置该月的第一天
        Date date = calendar.getTime();
        String monthFirst = sdf.format(date);
        return monthFirst;
    }

    public static String getPreviousMonth(String date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date parse = null;
        String monthFirst = "";
        try {
            parse = sdf.parse(date);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(parse);// 设置当前日期
            calendar.set(Calendar.MONTH, -1);
            calendar.set(Calendar.DAY_OF_MONTH, 16);
            Date newDate = calendar.getTime();
            monthFirst = sdf.format(newDate);
        } catch (ParseException e) {
            log.error("getPreviousMonth fail :", e.toString());
        }
        return monthFirst;

    }

    public static String getYearMonth(String date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date parse = null;
        try {
            parse = sdf.parse(date);
            return sdf.format(parse);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Date getAddDate(Date startDate, int num) {
        Date endTime = new Date(startDate.getTime() + num * 24 * 60 * 60 * 1000);
        return endTime;
    }

    //获取Timestamp时间
    public static Timestamp getTimestamp() {
        Timestamp time = new Timestamp(Calendar.getInstance().getTimeInMillis());
        return time;
    }

    /**
     * 计算时差
     *
     * @param date1 需要计算的时间
     * @param date2 现在的时间
     * @return
     */
    public static Long timeDifference(Timestamp date1, Timestamp date2) {
        Long day = null;
        if (date1 != null) {
            //day = (date1.getTime()-date2.getTime())/(24*60*60*1000)>0 ? (date1.getTime()-date2.getTime())/(24*60*60*1000):(date2.getTime()-date1.getTime())/(24*60*60*1000);
            day = (date2.getTime() - date1.getTime()) / (24 * 60 * 60 * 1000);
        }
        return day;
    }

    /**
     * 判断时间前后
     *
     * @param date1 基准时间
     * @param date2 需要比较的时间
     * @return
     */
    public static boolean compareDate(Date date1, Date date2) {
        if (date1.getTime() > date2.getTime()) {
            //System.out.println("dt1 在dt2前");
            //return true;
        } else if (date1.getTime() < date2.getTime()) {
            //System.out.println("dt1在dt2后");
            return false;
        }
        return true;

    }

	/**
	 * 获取今天剩余秒数
	 * @return
	 */
	public static Long getTodayRemainSeconds() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DAY_OF_YEAR, 1);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000;
	}

    /**
     * 生成操作对象
     *
     * @param date 指定的时间
     * @return 返回一个操作对象
     */
    public static TimeOperation init(Date date) {
        date = date == null ? new Date() : date;
        return TimeOperation.init(date);
    }

    public static String day2Date(int month, String monthCompleteTime) {
        String[] split = monthCompleteTime.split(",");
        SimpleDateFormat yyyy = new SimpleDateFormat("yyyy");
        String format = yyyy.format(new Date());
        String mo = "";
        String endDate = "";
        if (month < 10) {
            mo = "0" + month;
        } else {
            mo = month + "";
        }
        endDate = format + "-" + mo + "-" + split[0];
        endDate = endDate + "," + format + "-" + mo + "-" + split[1];
        return endDate;
    }

    public static class TimeOperation {
        private Calendar calendar;

        private TimeOperation() {
        }

        public Calendar getCalendar() {
            return this.calendar;
        }

        public Date getDate() {
            Objects.requireNonNull(calendar);
            return this.getCalendar().getTime();
        }

        private static TimeOperation init(Date date) {
            Objects.requireNonNull(date);
            TimeOperation op = new TimeOperation();
            op.calendar = Calendar.getInstance();
            op.calendar.setTime(date);
            return op;
        }

        private static TimeOperation init() {
            return init(new Date());
        }

        public TimeOperation firstDay() {
            return add(Calendar.DAY_OF_MONTH, 1);
        }

        public TimeOperation lastDay() {
            return add(Calendar.DAY_OF_MONTH, this.calendar.getActualMaximum(Calendar.DATE));
        }

        public TimeOperation add(int field, int amount) {
            Objects.requireNonNull(calendar);
            this.calendar.add(field, amount);
            return this;
        }

        public TimeOperation earliest() {
            return time(0, 0, 0, 0);
        }

        public TimeOperation lastest() {
            return time(23, 59, 59, 999);
        }

        public TimeOperation time(int hour, int minute, int second) {
            return time(hour, minute, second, 0);
        }

        public TimeOperation time(LocalTime time) {
            Objects.requireNonNull(time);
            return this.time(time.getHour(), time.getMinute(), time.getSecond(), 0);
        }

        public TimeOperation time(int hour, int minute, int second, int millisecond) {
            Objects.requireNonNull(calendar);
            this.calendar.set(Calendar.SECOND, second);
            this.calendar.set(Calendar.MINUTE, minute);
            this.calendar.set(Calendar.HOUR_OF_DAY, hour);
            this.calendar.set(Calendar.MILLISECOND, millisecond);
            return this;
        }
    }
}
