package com.tofly.xrtygis.custom.util;

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @program: tofly-dyrq
 * @description: 时间工具类(包括LocalDate, LocalDateTime, Date)
 * @author: Sumer
 * @create: 2020-08-25 09:00
 */
public class DateTimeUtil {

    /**
     * yyyy-MM-dd
     */
    public static final String YEAR = "yyyy";
    /**
     * yyyy-MM-dd
     */
    public static final String DAY_FORMAT = "yyyy-MM-dd";

    /**
     * yyyy-MM
     */
    public static final String MONTHS_FORMAT = "yyyy-MM";

    /**
     * yyyy/MM/dd
     */
    public static final String DAY_SLASH_FORMAT = "yyyy/MM/dd";

    /**
     * yyyy年MM月dd日
     */
    public static final String DAY_SLASH_C_FORMAT = "yyyy年MM月dd日";

    /**
     * yyyyMM
     */
    public static final String MONTHS_YEARS_FORMAT = "yyyyMM";

    /**
     * yyyy/MM/dd HH:mm:ss
     */
    public static final String FULL_SLASH_FORMAT = "yyyy/MM/dd HH:mm:ss";

    /**
     * yyyy-MM-dd HH:mm:ss
     */
    public static final String FULL_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /**
     * yyyyMMdd
     */
    public static final String NUMBER_FORMAT = "yyyyMMdd";

    public static final String DAY_MONTH_YEAR = "dd/MM/yyyy";

    /**
     * 获得当前时间的指定格式字符串
     *
     * @return String
     */
    public static String getCurrentDate(String dateFormat) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateFormat);
        LocalDate today = LocalDate.now();
        String nowDate = today.format(df);
        return nowDate;
    }

    /**
     * LocalDate转化为指定格式字符串
     *
     * @param fromDate
     * @param dateFormat
     * @return
     */
    public static String getLocalDate(LocalDate fromDate, String dateFormat) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateFormat);
        if (fromDate != null) {
            String dateStr = fromDate.format(df);
            return dateStr;
        }
        return null;

    }

    public static String getLocalDate(Date fromDate, String dateFormat){
        SimpleDateFormat sdf =new SimpleDateFormat(dateFormat);
        if(fromDate!=null)
            return sdf.format(fromDate);
        return null;
    }

    public static String getLocalDateTime(LocalDateTime fromDateTime, String dateTimeFotmat) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateTimeFotmat);
        if (fromDateTime != null) {
            String localTime = fromDateTime.format(df);
            return localTime;
        }
        return null;

    }

    /**
     * 获得一年后的日期格式字符串
     */
    public static String getOneYearLaterDate(String beginDate, String dateFormat) {
        LocalDate fromDate = fromString2LocalDate(beginDate, dateFormat);
        if (fromDate != null) {
            LocalDate toDate = fromDate.plus(1, ChronoUnit.YEARS);
            return getLocalDate(toDate, dateFormat);
        }
        return null;

    }

    /**
     * 时间格式字符串转化为指定格式的时间
     *
     * @param beginDate
     * @param dateFormat
     * @return
     */
    public static LocalDate fromString2LocalDate(String beginDate, String dateFormat) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateFormat);
        try {
            LocalDate fromDate = LocalDate.parse(beginDate, df);
            return fromDate;
        } catch (Exception e) {
            return null;
        }

    }

    /**
     * 时间格式字符串转化为指定格式的时间
     *
     * @param beginDateTime
     * @param dateFormat
     * @return
     */
    public static LocalDateTime fromString2LocalDateTime(String beginDateTime, String dateFormat) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateFormat);
        try {
            LocalDateTime fromDateTime = LocalDateTime.parse(beginDateTime, df);
            return fromDateTime;
        } catch (Exception e) {
            return null;
        }

    }

    /**
     * LocalDate 转 Date
     */
    public static Date localDateToDate(LocalDate localDate) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
        return Date.from(instant);
    }

    /**
     * 获得毫秒数
     *
     * @param localDateTime
     * @return
     */
    public static long getTimestampOfDateTime(LocalDateTime localDateTime) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        return instant.toEpochMilli();
    }


    /**
     * 根据出生日期(yyyy-MM-dd)字符串计算年龄
     *
     * @param birthDay
     * @return
     */
    public static Integer getAgeByBirthDay(String birthDay) {
        LocalDate birthDate = fromString2LocalDate(birthDay, DAY_FORMAT);
        LocalDate currentDate = LocalDate.now();
        if (birthDate != null) {
            //判断birthDay是否合法
            if (currentDate.isBefore(birthDate)) {
                return 0;
            } else {
                int age = birthDate.until(currentDate).getYears();
                return age;
            }

        } else {
            return null;
        }

    }

    /**
     * Long类型时间戳转化为LocalDateTime
     *
     * @param dateTimeLong
     * @return
     */
    public static LocalDateTime fromLong2LocalDateTime(Long dateTimeLong) {
        LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(dateTimeLong), ZoneId.systemDefault());
        return dateTime;
    }


    /**
     * 获取本年第一天
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDate getFirstDayOfCurrentYear() {
        LocalDate currentDay = LocalDate.now();
        return currentDay.with(TemporalAdjusters.firstDayOfMonth());
    }

    /**
     * 获取本年最后一天
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDate getLastDayOfCurrentYear() {
        LocalDate currentDay = LocalDate.now();
        return currentDay.with(TemporalAdjusters.lastDayOfYear());
    }
    /**
     * 获取本月第一天
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDate getFirstDayOfCurrentMonth() {
        LocalDate currentDay = LocalDate.now();
        return currentDay.with(TemporalAdjusters.firstDayOfMonth());
    }

    /**
     * 获取本月最后一天
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDate getLastDayOfCurrentMonth() {
        LocalDate currentDay = LocalDate.now();
        return currentDay.with(TemporalAdjusters.lastDayOfMonth());
    }

    /**
     * 获取指定月第一天
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDate getFirstDayOfCurrentSpecifiedMonth(LocalDateTime currentDay) {
        return currentDay.toLocalDate().with(TemporalAdjusters.firstDayOfMonth());
    }

    /**
     * 获取指定月最后一天
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDate getLastDayOfCurrentSpecifiedMonth(LocalDateTime currentDay) {
        return currentDay.toLocalDate().with(TemporalAdjusters.lastDayOfMonth());
    }

    /**
     * 获取当天开始时间 2019-06-12 00:00:00
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDateTime getTodayBeginTime() {
        LocalDate currentDay = LocalDate.now();
        return LocalDateTime.of(currentDay, LocalTime.MIN);
    }

    /**
     * 获取当天结束时间 2019-06-12 23:59:59
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDateTime getTodayEndTime() {
        LocalDate currentDay = LocalDate.now();
        return LocalDateTime.of(currentDay, LocalTime.MAX);
    }

    /**
     * 获取本周开始时间 2019-06-10 00:00:00
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDateTime getWeekBeginTime() {
        LocalDateTime currentDateTime = LocalDateTime.now();
        int currentOrdinal = currentDateTime.getDayOfWeek().ordinal();
        return currentDateTime.minusDays(currentOrdinal)
                .withHour(0).withMinute(0).withSecond(0).withNano(0);
    }

    /**
     * 获取本周开始时间 2019-06-10 00:00:00
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static String getWeekBeginTimeString() {
        LocalDateTime currentDateTime = LocalDateTime.now();
        int currentOrdinal = currentDateTime.getDayOfWeek().ordinal();
        LocalDateTime weekBeginDateTime = currentDateTime.minusDays(currentOrdinal)
                .withHour(0).withMinute(0).withSecond(0).withNano(0);
        return getLocalDateTime(weekBeginDateTime, FULL_FORMAT);
    }

    /**
     * 获取本周结束时间 2019-06-16 23:59:59
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDateTime getWeekEndTime() {
        LocalDateTime currentDateTime = LocalDateTime.now();
        int currentOrdinal = currentDateTime.getDayOfWeek().ordinal();
        return currentDateTime.plusDays(6 - currentOrdinal)
                .withHour(23).withMinute(59).withSecond(59).withNano(999999999);
    }

    /**
     * 获取本周结束时间字符串 2019-06-16 23:59:59
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static String getWeekEndTimeString() {
        LocalDateTime currentDateTime = LocalDateTime.now();
        int currentOrdinal = currentDateTime.getDayOfWeek().ordinal();
        LocalDateTime weekEndDateTime = currentDateTime.plusDays(6 - currentOrdinal)
                .withHour(23).withMinute(59).withSecond(59).withNano(999999999);
        return getLocalDateTime(weekEndDateTime, FULL_FORMAT);
    }

    /**
     * LocalDateTime转换为Date
     *
     * @param time
     * @return
     */
    public static Date convertLDTToDate(LocalDateTime time) {
        return Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * LocalDateTime相差天数
     *
     * @param startLocalDateTime
     * @param endLocalDateTime
     * @return
     */
    public static Long differDays(LocalDateTime startLocalDateTime, LocalDateTime endLocalDateTime) {
        LocalDate sLocalDate = startLocalDateTime.toLocalDate();
        LocalDate eLocalDate = endLocalDateTime.toLocalDate();
        return eLocalDate.toEpochDay() - sLocalDate.toEpochDay();

    }

    /**
     * 日期时间的加减
     *
     * @param localDateTime
     * @param num
     * @param chronoUnit
     * @return
     */
    public static LocalDateTime timeCalculate(LocalDateTime localDateTime, Integer num, ChronoUnit chronoUnit) {
        return localDateTime.plus(num, chronoUnit);
    }

    /**
     * 获取指定天开始时间 2019-06-12 00:00:00
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDateTime getAssignTodayBeginTime(LocalDateTime localDateTime) {
        LocalDate currentDay = localDateTime.toLocalDate();
        return LocalDateTime.of(currentDay, LocalTime.MIN);
    }

    /**
     * 获取指定天结束时间 2019-06-12 23:59:59
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDateTime getAssignTodayEndTime(LocalDateTime localDateTime) {
        LocalDate currentDay = localDateTime.toLocalDate();
        return LocalDateTime.of(currentDay, LocalTime.MAX);
    }
    public static LocalDate UDateToLocalDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        LocalDate localDate = localDateTime.toLocalDate();
        return localDate;
    }

    /**
     * 获取传入日期区间中所有日期
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<String> getsAllDatesInTheDateRange(LocalDate startDate, LocalDate endDate) {
        List<String> localDateList = new ArrayList<>();
        // 开始时间必须小于结束时间
        if (startDate.isAfter(endDate)) {
            return null;
        }
        while (startDate.isBefore(endDate)) {
            localDateList.add(DateTimeUtil.getLocalDate(startDate,DateTimeUtil.DAY_FORMAT));
            startDate = startDate.plusDays(1);
        }
        localDateList.add(DateTimeUtil.getLocalDate(endDate,DateTimeUtil.DAY_FORMAT));
        return localDateList;
    }

    /**
     * 获取指定天结束时间 2019-06-12 23:59:59
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDateTime getAssignTodayBeginDate(LocalDate currentDay) {
        return LocalDateTime.of(currentDay, LocalTime.MIN);
    }

    public static LocalDateTime getAssignTodayEndDate(LocalDate currentDay) {
        return LocalDateTime.of(currentDay, LocalTime.MAX);
    }
}