package com.younike.common.utils.date;

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

import java.sql.Time;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 日期工具类
 */
public class DateUtils {

    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";

    public static String HIK_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";

    /**
     * 文件重命名专用日期格式
     */
    public static String PATTEN_FILE_RENAME = "yyyyMMddHHmmssSSS";

    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"};

    /**
     * 日期转换成指定格式日期字符串
     *
     * @param date 日期
     * @return 返回yyyy-MM-dd格式日期字符串
     */
    public static String formatDate(final Date date) {
        return formatDateByStyle(date, DatePattern.CN_DATE_BASIC_STYLE1.getDatePattern());
    }

    /**
     * 当前日期转换成指定格式日期字符串
     *
     * @return 返回yyyy-MM-dd格式日期字符串
     */
    public static String formatNowDate() {
        return formatNowByStyle(DatePattern.CN_DATE_BASIC_STYLE1.getDatePattern());
    }

    /**
     * 日期转换成指定格式日期字符串
     *
     * @param date 日期
     * @return 返回yyyy-MM-dd HH:mm:ss格式日期字符串
     */
    public static String formatDateTime(final Date date) {
        return formatDateByStyle(date, DatePattern.CN_DATE_BASIC_STYLE.getDatePattern());
    }


    public static long getMinLast(String data){
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 计算时间
        long between = ChronoUnit.MINUTES.between(LocalDateTime.now(),LocalDateTime.parse(data,df));

        return Math.abs(between);
    }

    public static void main(String[] args) {
        System.out.println(" getMinLast(\"2022-04-08 14:50:28\") = " +  getMinLast("2022-04-08 14:50:28"));
    }

    /**
     * 当前日期转换成指定格式日期字符串
     *
     * @return 返回yyyy-MM-dd HH:mm:ss格式日期字符串
     */
    public static String formatNowDateTime() {
        return formatNowByStyle(DatePattern.CN_DATE_BASIC_STYLE.getDatePattern());
    }

    /**
     * 日期转换成指定格式日期字符串
     *
     * @param date        日期
     * @param datePattern 日期格式
     * @return 返回指定格式日期字符串
     */
    public static String formatDateByStyle(final Date date, final String datePattern) {
        if (date != null) {
            SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
            return sdf.format(date);
        }
        return null;
    }

    /**
     * 当前日期转换成指定格式日期字符串
     *
     * @param datePattern 日期格式
     * @return 返回指定格式日期字符串
     */
    public static String formatNowByStyle(final String datePattern) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(datePattern);
        return dtf.format(LocalDateTime.now());
    }

    /**
     * 指定格式日期字符串转换成日期
     *
     * @param dateStr     指定格式日期字符串
     * @param datePattern 日期格式
     */
    public static Date formatStringByStyleToDate(final String dateStr, final String datePattern) {
        Date date = null;
        if (StringUtils.isNotBlank(dateStr)) {
            SimpleDateFormat formatter = new SimpleDateFormat(datePattern);
            try {
                date = formatter.parse(dateStr);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return date;
    }

    /**
     * 对日期的【秒】进行加/减
     *
     * @param date    日期
     * @param seconds 秒数，负数为减
     * @return 加/减几秒后的日期
     */
    public static Date addDateSeconds(final Date date, final int seconds) {
        return localDateTimeToDate(dateToLocalDateTime(date).plusSeconds(seconds));
    }

    /**
     * 当前日期的【秒】进行加/减
     *
     * @param seconds 秒数，负数为减
     * @return 加/减几秒后的日期
     */
    public static Date addNowSeconds(final int seconds) {
        return localDateTimeToDate(LocalDateTime.now().plusSeconds(seconds));
    }

    /**
     * 对日期的【分钟】进行加/减
     *
     * @param date    日期
     * @param minutes 分钟数，负数为减
     * @return 加/减几分钟后的日期
     */
    public static Date addDateMinutes(final Date date, final int minutes) {
        return localDateTimeToDate(dateToLocalDateTime(date).plusMinutes(minutes));
    }

    /**
     * 对日期的【分钟】进行加/减
     *
     * @param minutes 分钟数，负数为减
     * @return 加/减几分钟后的日期
     */
    public static Date addDateMinutes(final int minutes) {
        return localDateTimeToDate(LocalDateTime.now().plusMinutes(minutes));
    }

    /**
     * 对日期的【小时】进行加/减
     *
     * @param date  日期
     * @param hours 小时数，负数为减
     * @return 加/减几小时后的日期
     */
    public static Date addDateHours(final Date date, final int hours) {
        return localDateTimeToDate(dateToLocalDateTime(date).plusHours(hours));
    }

    /**
     * 对日期的【小时】进行加/减
     *
     * @param hours 小时数，负数为减
     * @return 加/减几小时后的日期
     */
    public static Date addDateHours(final int hours) {
        return localDateTimeToDate(LocalDateTime.now().plusHours(hours));
    }

    /**
     * 对日期的【天】进行加/减
     *
     * @param date 日期
     * @param days 天数，负数为减
     * @return 加/减几天后的日期
     */
    public static Date addDateDays(final Date date, final int days) {
        return localDateTimeToDate(dateToLocalDateTime(date).plusDays(days));
    }

    /**
     * 对日期的【天】进行加/减
     *
     * @param days 天数，负数为减
     * @return 加/减几天后的日期
     */
    public static Date addDateDays(final int days) {
        return localDateTimeToDate(LocalDateTime.now().plusDays(days));
    }

    /**
     * 对日期的【周】进行加/减
     *
     * @param date  日期
     * @param weeks 周数，负数为减
     * @return 加/减几周后的日期
     */
    public static Date addDateWeeks(final Date date, final int weeks) {
        return localDateTimeToDate(dateToLocalDateTime(date).plusWeeks(weeks));
    }

    /**
     * 对日期的【周】进行加/减
     *
     * @param weeks 周数，负数为减
     * @return 加/减几周后的日期
     */
    public static Date addDateWeeks(final int weeks) {
        return localDateTimeToDate(LocalDateTime.now().plusWeeks(weeks));
    }

    /**
     * 对日期的【月】进行加/减
     *
     * @param date   日期
     * @param months 月数，负数为减
     * @return 加/减几月后的日期
     */
    public static Date addDateMonths(final Date date, final int months) {
        return localDateTimeToDate(dateToLocalDateTime(date).plusMonths(months));
    }

    /**
     * 对日期的【月】进行加/减
     *
     * @param months 月数，负数为减
     * @return 加/减几月后的日期
     */
    public static Date addDateMonths(final int months) {
        return localDateTimeToDate(LocalDateTime.now().plusMonths(months));
    }

    /**
     * 对日期的【年】进行加/减
     *
     * @param date  日期
     * @param years 年数，负数为减
     * @return 加/减几年后的日期
     */
    public static Date addDateYears(final Date date, final int years) {
        return localDateTimeToDate(dateToLocalDateTime(date).plusYears(years));
    }

    /**
     * 对日期的【年】进行加/减
     *
     * @param years 年数，负数为减
     * @return 加/减几年后的日期
     */
    public static Date addNowYears(final int years) {
        return localDateTimeToDate(LocalDateTime.now().plusYears(years));
    }

    /**
     * Date转LocalDateTime
     *
     * @param date 日期
     * @return 日期
     */
    public static LocalDateTime dateToLocalDateTime(final Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    /**
     * LocalDateTime转Date
     *
     * @param localDateTime 日期
     * @return 日期
     */
    public static Date localDateTimeToDate(final LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获得本月的第一天的0点
     *
     * @return
     */
    public static Date firstDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获得本月的最后一天
     *
     * @return
     */
    public static Date lastDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR, 24);
        return calendar.getTime();
    }

    /**
     * 得到日期字符串 默认格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
     */
    public static String formatDate(Date date, Object... pattern) {
        String formatDate = null;
        if (date == null) {
            return formatDate;
        }
        if (pattern != null && pattern.length > 0) {
            formatDate = DateFormatUtils.format(date, pattern[0].toString());
        } else {
            formatDate = DateFormatUtils.format(date, "yyyy-MM-dd");
        }
        return formatDate;
    }

    /**
     * 得到当前年份字符串 格式（yyyy）
     */
    public static String getYear() {
        return formatDate(new Date(), "yyyy");
    }

    public static final String parseDateToStr(final String format, final Date date) {
        return new SimpleDateFormat(format).format(date);
    }

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

    /**
     * 2021-7-9 Another String类型转换成Date类型（时分秒格式）
     * @param dateString
     * @return
     */
    public static Date stringToDate(String dateString) {
        if (dateString == null) {
            return null;
        }
        SimpleDateFormat formatter =  new SimpleDateFormat("HH:mm:ss" );
        Date date = null;
        try {
            date = formatter.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 将指定格式的时间转换成Date类型
     *
     * @param date 指定日期
     * @param pattern 格式
     * @return 转换后日期
     * @throws Exception 转换异常时，返回系统异常
     */
    public static Date stringToDate(String date, String pattern) throws Exception{
        Date result = null;
        try {
            result = new SimpleDateFormat(pattern).parse(date);
        } catch (ParseException e) {
            throw e;
        }
        return result;
    }

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

    /**
     * 日期转换成指定格式日期字符串
     *
     * @param date 日期
     * @return 返回yyyy-MM-dd HH:mm格式日期字符串
     */
    public static String formatDateSTYLE8(final Date date) {
        return formatDateByStyle(date, DatePattern.CN_DATE_BASIC_STYLE8.getDatePattern());
    }

    /**
     * 日期转换成指定格式日期字符串
     *
     * @param date 日期
     * @return 返回HH:mm格式日期字符串
     */
    public static String formatDateHM(final Date date) {
        return formatDateByStyle(date, "HH:mm");
    }

    /**
     * 2021-8-31 Another 根据年月获取开始时间
     * @param year
     * @param month
     * @return
     */
    public static Date getBeginTime(int year, int month) {
        YearMonth yearMonth = YearMonth.of(year, month);
        LocalDate localDate = yearMonth.atDay(1);
        LocalDateTime startOfDay = localDate.atStartOfDay();
        ZonedDateTime zonedDateTime = startOfDay.atZone(ZoneId.of("Asia/Shanghai"));

        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * 2021-8-31 Another 根据年月获取结束时间
     * @param year
     * @param month
     * @return
     */
    public static Date getEndTime(int year, int month) {
        YearMonth yearMonth = YearMonth.of(year, month);
        LocalDate endOfMonth = yearMonth.atEndOfMonth();
        LocalDateTime localDateTime = endOfMonth.atTime(23, 59, 59, 999);
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * 2021-9-8 Another 获取今天是周几（周日-0 周一-1 周二-2 周三-3 周四-4 周五-5 周六-6）
     * @return
     */
    public static int getWeek() {
        String week = "";
        Date today = new Date();
        Calendar c = Calendar.getInstance();
        c.setTime(today);
        return c.get(Calendar.DAY_OF_WEEK) - 1;
    }

    /**
     * 获取当月的最后一天
     * @param year
     * @param month
     * @return
     */
    public static String getLastDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        //设置年份
        cal.set(Calendar.YEAR, year);
        //设置月份
        cal.set(Calendar.MONTH, month-1);
        //获取某月最大天数
        int lastDay = cal.getActualMaximum(Calendar.DATE);
        //设置日历中月份的最大天数
        cal.set(Calendar.DAY_OF_MONTH, lastDay);
        //格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime());
    }

    /**
     * 2021-9-24 Another String 转 Time
     * @param time
     * @return
     */
    public static Time stringToTime(String time) {
        if (StringUtils.isBlank(time)) {
            return null;
        }
        SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss");
        Date d = null;
        try {
            d = format.parse(time);
        } catch (Exception e) {
            e.printStackTrace();
        }
        assert d != null;
        return new Time(d.getTime());
    }

    public static Date toDayEnd(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    // 当天近30天的每一天
    public static List<String> getNearlyThirtyDay() throws ParseException {
        //String str = "2022-01-05";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//日期格式化
        String str = sdf.format(new Date());//当天
        List<String> list = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();

        Date date = sdf.parse(str);
        calendar.setTime(date);
        Date enddate = calendar.getTime();

        calendar.setTime(date);
        calendar.add(calendar.MONTH,-1);
        while (calendar.getTime().before(enddate)){
            //System.out.println(sdf.format(calendar.getTime()));
            list.add(sdf.format(calendar.getTime()));
            calendar.add(Calendar.DAY_OF_MONTH,1);
        }
        return list;
    }
}
