package com.tofly.dc.util;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;

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

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

    /**
     * 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
     */
    public static final String YEARS_FORMAT = "yyyy";

    /**
     * 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";
    /**
     * yyyy/MM
     */
    public static final String FULL_MONTH_FORMAT = "yyyy/MM";

    /**
     * yyyy-MM-dd HH
     */
    public static final String HOUR_FORMAT = "yyyy-MM-dd HH";

    /**
     * yyyyMMdd
     */
    public static final String NUMBER_FORMAT = "yyyyMMdd";

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

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

    }

    
    public static String getLocalDateTime(LocalDateTime fromDateTime, String dateTimeFotmat) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateTimeFotmat);
        if (fromDateTime != null) {
            return fromDateTime.format(df);
        }
        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 {
            return LocalDate.parse(beginDate, df);
        } catch (Exception e) {
            return null;
        }

    }

    /**
     * 时间格式字符串转化为指定格式的时间
     *
     * @param beginDateTime
     * @param dateFormat
     * @return
     */
    public static LocalDateTime fromString2LocalDateTime(String beginDateTime, String dateFormat) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateFormat);
        try {
            return LocalDateTime.parse(beginDateTime, df);
        } 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 {
                return birthDate.until(currentDate).getYears();
            }

        } else {
            return null;
        }

    }

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


    /**
     * 获取本月第一天
     *
     * @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());
    }

    public static Date fromLocalDateToDate(LocalDate nowLocalDate){
        return Date.from(nowLocalDate.atStartOfDay(ZoneOffset.ofHours(8)).toInstant());
    }

    /**
     * 获取指定月第一天
     *
     * @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();

    }

    /**
     * LocalDateTime相差时长
     *
     * @param startLocalDateTime
     * @param endLocalDateTime
     * @return
     */
    public static Long differHours(LocalDateTime startLocalDateTime, LocalDateTime endLocalDateTime) {
        Duration between = Duration.between(startLocalDateTime, endLocalDateTime);
        return between.toHours();
    }

    /**
     * 日期时间的加减
     *
     * @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);
    }

}