/**
 * Copyright (c) 2016-2019 人人开源 All rights reserved.
 * <p>
 * https://www.renren.io
 * <p>
 * 版权所有，侵权必究！
 */

package tech.glinfo.enbao.common.utils;

import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 日期处理
 *
 * @author Mark sunlightcs@gmail.com
 */
public class DateUtils {
    /**
     * 时间格式(yyyy-MM-dd)
     */
    public final static String DATE_PATTERN = "yyyy-MM-dd";
    /**
     * 时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date 日期
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date    日期
     * @param pattern 格式，如：DateUtils.DATE_TIME_PATTERN
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date, String pattern) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }

    /**
     * 字符串转换成日期
     *
     * @param strDate 日期字符串
     * @param pattern 日期的格式，如：DateUtils.DATE_TIME_PATTERN
     */
    public static Date stringToDate(String strDate, String pattern) {
        if (StringUtils.isBlank(strDate)) {
            return null;
        }

        DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
        return fmt.parseLocalDateTime(strDate).toDate();
    }

    /**
     * 根据周数，获取开始日期、结束日期
     *
     * @param week 周期  0本周，-1上周，-2上上周，1下周，2下下周
     * @return 返回date[0]开始日期、date[1]结束日期
     */
    public static Date[] getWeekStartAndEnd(int week) {
        DateTime dateTime = new DateTime();
        LocalDate date = new LocalDate(dateTime.plusWeeks(week));

        date = date.dayOfWeek().withMinimumValue();
        Date beginDate = date.toDate();
        Date endDate = date.plusDays(6).toDate();
        return new Date[]{beginDate, endDate};
    }

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

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

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

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

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

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

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

    /**
     * 根据日期获取十六进制字符串
     *
     * @param date
     * @return
     */
    public static String getHexByDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);                    //放入Date类型数据
        StringBuffer sb = new StringBuffer();
        sb.append(ByteUtils.int2Hex(calendar.get(Calendar.YEAR)));//获取年份
        sb.append(ByteUtils.int2Hex(calendar.get(Calendar.MONTH) + 1));                    //获取月份
        sb.append(ByteUtils.int2Hex(calendar.get(Calendar.DATE)));                    //获取日

//        sb.append(calendar.get(Calendar.HOUR));					//时（12小时制）
        sb.append(ByteUtils.int2Hex(calendar.get(Calendar.HOUR_OF_DAY)));                //时（24小时制）
        sb.append(ByteUtils.int2Hex(calendar.get(Calendar.MINUTE)));                    //分
        sb.append(ByteUtils.int2Hex(calendar.get(Calendar.SECOND)));                    //秒
        return sb.toString();
    }

    public static String getDateByHex(String content) {
        String hex = content.substring(0, 4);
        String year = String.valueOf(Integer.valueOf(hex, 16));
        String hex1 = content.substring(4, 6);
        String month = StringUtils.appendString(String.valueOf(Integer.valueOf(hex1, 16)), 2, true, "0");
        String hex2 = content.substring(6, 8);
        String day = StringUtils.appendString(String.valueOf(Integer.valueOf(hex2, 16)), 2, true, "0");
        String hex3 = content.substring(8, 10);
        String hour = StringUtils.appendString(String.valueOf(Integer.valueOf(hex3, 16)), 2, true, "0");
        String hex4 = content.substring(10, 12);
        String minute = StringUtils.appendString(String.valueOf(Integer.valueOf(hex4, 16)), 2, true, "0");
        String hex5 = content.substring(12, 14);
        String second = StringUtils.appendString(String.valueOf(Integer.valueOf(hex5, 16)), 2, true, "0");
        String date = year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
        System.out.println("device-time : " + date);
        return date;
    }

    /**
     * 时间戳转日期格式
     *
     * @param lt
     * @return
     */
    public static String stampToTime(long lt) {
        String res;

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //将时间戳转换为时间
        Date date = new Date(lt);
        //将时间调整为yyyy-MM-dd HH:mm:ss时间样式
        res = simpleDateFormat.format(date);
        return res;
    }


    /**
     * 获取两个时间段之间集合
     * flag 为true的话包括结束使时间
     *
     * @param startTime endTime
     * @return
     */
    public static List<String> getDays(String startTime, String endTime, boolean flag) {
        List<String> days = new ArrayList<>();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);
            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);
            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            if (flag) {
                tempEnd.add(Calendar.DATE, +1);
            }
            while (tempStart.before(tempEnd)) {
                days.add(dateFormat.format(tempStart.getTime()));
                tempStart.add(Calendar.DAY_OF_YEAR, +1);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return days;
    }

    /**
     * 获取两个时间段之间集合
     * flag 为true的话包括结束使时间
     *
     * @param startTime endTime
     * @return
     */
    public static List<String> getDays2(String startTime, String endTime, boolean flag) {
        List<String> days = new ArrayList<>();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);
            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);
            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            if (flag) {
                tempEnd.add(Calendar.DATE, +1);
            }
            while (tempStart.before(tempEnd)) {
                DateFormat dateFormat1 = new SimpleDateFormat("dd");
                days.add(dateFormat1.format(tempStart.getTime()));
                tempStart.add(Calendar.DAY_OF_YEAR, +1);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return days;
    }

    /**
     * 判断是否周末
     *
     * @param date
     * @return
     */
    public static boolean isWeekend(String date) throws ParseException {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date1 = dateFormat.parse(date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date1);
        int week = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        // 周五或周六为周末
        return week == 6 || week == 5;
    }

    /**
     * 计算月份有多少天
     *
     * @param
     * @return
     */
    public static int calculationMonth(int year, int month) {
        int days = 0;
        if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
            days = 31;
        } else if (month == 4 || month == 6 || month == 9 || month == 11) {
            days = 30;
        } else if (month == 2) {
            if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
                days = 29;
            } else {
                days = 28;
            }
        }
        return days;
    }

    /**
     * date2比date1多的天数
     *
     * @param date1
     * @param date2
     * @return
     */
    public 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    //不同年
        {
            return day2 - day1;
        }
    }


    public static String dayForWeek(String pTime) throws Throwable {

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

        Date tmpDate = format.parse(pTime);

        Calendar cal = Calendar.getInstance();

        String[] weekDays = { "日", "一", "二", "三", "四", "五", "六" };

        try {

            cal.setTime(tmpDate);

        } catch (Exception e) {

            e.printStackTrace();

        }

        int w = cal.get(Calendar.DAY_OF_WEEK) - 1; // 指示一个星期中的某天。

        if (w < 0)

            w = 0;

        return weekDays[w];

    }

    public static void main(String[] args) throws Throwable {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date checkInTime1 = sdf.parse("2021-08-10");
        System.out.println(format(addDateDays(checkInTime1, 1), "yyyy-MM-dd"));
        if (checkInTime1.getTime() < DateUtils.addDateDays(new Date(), -2).getTime()) {
            System.out.println("入住时间有误！");
        }
        System.out.println(getDays2("2021-11-01", "2021-11-30", true));
        String time = "yyyy-MM-dd";
        System.out.println(time.substring(time.length() -2));

        System.out.println(DateUtils.getHexByDate(DateUtils.stringToDate("2020-04-05 12:10", "yyyy-MM-dd HH:mm")));
//        addDateDays
        String a = dayForWeek("2021-11-11");
        System.out.println(format(addDateDays(stringToDate("2021-11-13", "yyyy-MM-dd"), -5), "yyyy-MM-dd"));
//        Date date = stringToDate("2021-08-10", "yyyy-MM-dd");
//        System.out.println(differentDays(new Date(), date));
    }
}
