package cn.qinys.platform.base.utils;

import org.apache.commons.lang3.StringUtils;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Locale;
import java.util.Objects;

/**
 * code is far away from bug with the animal protecting
 *
 * @author v-lishiquan.gx@chinatelecom.cn
 * @description 日期工具类
 * @date Create in 2018/2/26 11:10
 */
public class DateUtils {

    private DateUtils() {
    }

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

    public static Date parseDate(String dateStr, String formatter) {
        try {
            return new SimpleDateFormat(formatter).parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    /**
     * 自定义日期格式
     *
     * @param date      LocalDate日期
     * @param formatter 自定义格式
     * @return 日期字符串
     */
    public static String dateFormatter(LocalDate date, String formatter) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(formatter);
        return Objects.isNull(date) ? "" : dtf.format(date);
    }

    /**
     * 自定义日期格式
     *
     * @param date      LocalDateTime日期
     * @param formatter 自定义格式
     * @return 日期字符串
     */
    public static String dateFormatter(LocalDateTime date, String formatter) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(formatter);
        return Objects.isNull(date) ? "" : dtf.format(date);
    }

    /**
     * 把dateString转换成LocalDate类型,只能格式化日期
     *
     * @param dateStr 日期字符串
     * @return LocalDate
     */
    public static LocalDate convertStringToLocalDate(String dateStr, DateTimeFormatter formatter) {
        return LocalDate.parse(dateStr, formatter);
    }

    /**
     * 把dateString转换成LocalTime类型,只能格式化时间
     *
     * @param dateStr 日期字符串
     * @return LocalTime
     */
    public static LocalTime convertStringToLocalTime(String dateStr, DateTimeFormatter formatter) {
        return LocalTime.parse(dateStr, formatter);
    }

    /**
     * 把dateString转换成LocalDateTime类型,只能格式化时间
     *
     * @param dateStr 日期字符串
     * @return LocalDateTime
     */
    public static LocalDateTime convertStringToLocalDateTime(String dateStr, DateTimeFormatter formatter) {
        return LocalDateTime.parse(dateStr, formatter);
    }

    /**
     * 获取传入日期为星期几
     *
     * @param date 日期Date
     * @return 星期几
     */
    public static int weekDay(LocalDate date) {
        return date.getDayOfWeek().getValue();
    }

    /**
     * 转成中文星期几
     *
     * @param date 日期
     * @return 结果
     */
    public static String chineseWeekDay(LocalDate date) {
        int weekDay = weekDay(date);
        return chineseWeekDay(weekDay);
    }

    /**
     * 中文星期几
     *
     * @param weekDay 日期, 范围1-7, 1为星期一, 7为星期天
     * @return 结果
     */
    public static String chineseWeekDay(int weekDay) {
        String[] weeks = {"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"};
        return weeks[weekDay - 1];
    }

    /**
     * 获取前一天的日期
     *
     * @return 前一天的日期
     */
    public static LocalDate preDay() {
        return LocalDate.now().minusDays(1L);
    }

    /**
     * 获取前N天的日期
     *
     * @return 前N天的日期
     */
    public static LocalDate preDay(int days) {
        return LocalDate.now().minusDays(days);
    }

    /**
     * 获取后一天的日期
     *
     * @return 后一天的日期
     */
    public static LocalDate nextDay() {
        return LocalDate.now().plusDays(1L);
    }

    /**
     * 获取后N天的日期
     *
     * @return 后N天的日期
     */
    public static LocalDate nextDay(int days) {
        return LocalDate.now().plusDays(days);
    }

    /**
     * 计算两个日期的天数差
     *
     * @param beginDate 开始日期
     * @param endDate   截止日期
     * @return 相差多少天
     */
    public static Long getDaysBetween(LocalDate beginDate, LocalDate endDate) {
        return endDate.toEpochDay() - beginDate.toEpochDay();
    }

    /**
     * 根据传入日期转换成默认时区的LocalDate
     *
     * @param date 日期
     * @return LocalDate
     */
    public static LocalDate asLocalDate(Date date) {
        return asLocalDate(date, ZoneId.systemDefault());
    }

    /**
     * 根据传入日期转换成默认时区的LocalDate
     *
     * @param date 日期
     * @param zone 时区
     * @return LocalDate
     */
    public static LocalDate asLocalDate(Date date, ZoneId zone) {
        if (date == null) {
            return null;
        }
        if (date instanceof java.sql.Date) {
            return ((java.sql.Date) date).toLocalDate();
        } else {
            return Instant.ofEpochMilli(date.getTime()).atZone(zone).toLocalDate();
        }
    }

    /**
     * 根据传入日期转换成默认时区的LocalDateTime
     *
     * @param date 日期
     * @return LocalDateTime
     */
    public static LocalDateTime asLocalDateTime(Date date) {
        return asLocalDateTime(date, ZoneId.systemDefault());
    }

    /**
     * 根据传入日期转换成默认时区的LocalDateTime
     *
     * @param date 日期
     * @param zone 时区
     * @return LocalDateTime
     */
    public static LocalDateTime asLocalDateTime(Date date, ZoneId zone) {
        if (date == null) {
            return null;
        }
        if (date instanceof java.sql.Timestamp) {
            return ((java.sql.Timestamp) date).toLocalDateTime();
        } else {
            return Instant.ofEpochMilli(date.getTime()).atZone(zone).toLocalDateTime();
        }
    }

    /**
     * Object对象转成java.util.Date
     *
     * @param date 日期
     * @return java.util.Date
     */
    public static Date asUtilDate(Object date) {
        return asUtilDate(date, ZoneId.systemDefault());
    }

    /**
     * 从各种日期格式创建{@link Date} 当前支持的有:
     * <ul>
     * <li>{@link Date}
     * <li>{@link java.sql.Date}
     * <li>{@link java.sql.Timestamp}
     * <li>{@link LocalDate}
     * <li>{@link LocalDateTime}
     * <li>{@link ZonedDateTime}
     * <li>{@link Instant}
     * </ul>
     * <p>
     * Object对象转成java.util.Date
     *
     * @param date 日期
     * @param zone 时区,只有LocalDate或LocalDateTime时候才用到
     * @return java.util.Date
     */
    public static Date asUtilDate(Object date, ZoneId zone) {
        if (date == null) {
            return null;
        } else if (date instanceof java.sql.Date || date instanceof java.sql.Timestamp) {
            return new Date(((Date) date).getTime());
        } else if (date instanceof Date) {
            return (Date) date;
        } else if (date instanceof LocalDate) {
            return Date.from(((LocalDate) date).atStartOfDay(zone).toInstant());
        } else if (date instanceof LocalDateTime) {
            return Date.from(((LocalDateTime) date).atZone(zone).toInstant());
        } else if (date instanceof ZonedDateTime) {
            return Date.from(((ZonedDateTime) date).toInstant());
        } else if (date instanceof Instant) {
            return Date.from((Instant) date);
        }
        throw new UnsupportedOperationException("Do not convert " + date.getClass().getName() + " to java.util.Date");
    }

    /**
     * 日期转换成Instant
     *
     * @param date 日期
     * @return Instant
     */
    public static Instant asInstant(Date date) {
        return date == null ? null : Instant.ofEpochMilli(date.getTime());
    }

    /**
     * 日期转换成ZonedDateTime
     *
     * @param date 日期
     * @return ZonedDateTime
     */
    public static ZonedDateTime asZonedDateTime(Date date) {
        return asZonedDateTime(date, ZoneId.systemDefault());
    }

    /**
     * 日期转换成ZonedDateTime
     *
     * @param date 日期
     * @param zone 时区
     * @return ZonedDateTime
     */
    public static ZonedDateTime asZonedDateTime(Date date, ZoneId zone) {
        return date == null ? null : asInstant(date).atZone(zone);
    }

    /**
     * 计算人的年龄
     *
     * @param birthday 出生日期
     * @return 年龄
     */
    public static int calPersonAge(Date birthday) {
        return LocalDate.now().getYear() - asLocalDate(birthday).getYear();
    }

    /**
     * 获取当前时间的毫秒值
     *
     * @param ldt 当前时间
     * @return 毫秒值
     */
    public static long getTimeMilli(LocalDateTime ldt) {
        return ldt.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
    }

    /**
     * 转换日期格式
     *
     * @param oldDate 日期字符串
     * @param format  转换后日期格式
     * @return
     */
    public static String dealDateFormat(String oldDate, String format) {
        Date date1 = null;
        DateFormat df2 = null;
        if (!StringUtils.isNotBlank(oldDate)) {
            return "";
        }
        try {
            oldDate = oldDate.replace("Z", " UTC");
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS Z");
            Date date = df.parse(oldDate);
            SimpleDateFormat df1 = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.UK);
            date1 = df1.parse(date.toString());
            df2 = new SimpleDateFormat(format);
        } catch (Exception e) {
            try {
                oldDate = oldDate.substring(0, 22);
                DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
                Date date = df.parse(oldDate);
                SimpleDateFormat df1 = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.UK);
                date1 = df1.parse(date.toString());
                df2 = new SimpleDateFormat(format);
            } catch (Exception e1) {
                e1.printStackTrace();
                return "";
            }

        }
        return df2.format(date1);
    }

}
