package com.jiayue.ipfcst.common.core.util;

import com.sun.istack.internal.NotNull;
import java.util.Calendar;

/**
 * 时刻工具类
 *
 * @author zzy
 * @version 2.0
 * @since 2018/11/2 11:31
 */
public abstract class DateMomentUtil {


    /**
     * 获取月份
     *
     * @param dateTime 时间，单位毫秒
     * @return 月份
     */
    public static Integer getMonth(@NotNull final Long dateTime) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(dateTime);
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取指定时间在当天所处于的时刻
     * 例如：dateTime：2018-10-22 16:44:00 momentLength: 15分钟，既 15*60*1000毫秒
     * 从0点0分开始计算，0点0分-0点15为第一个时刻，依次类推该时间的时刻数为67
     *
     * @param dateTime     时间毫秒
     * @param momentLength 时刻长度,单位毫秒
     * @return 时刻
     */
    public static int getMoment(@NotNull final Long dateTime, @NotNull final Long momentLength) {
        return (int) ((dateTime - DateMomentUtil.getDayStartTime(dateTime)) / momentLength) + 1;
    }

    /**
     * 获取指定时间所在时刻的标记时间 <br>
     * 例如：dateTime:2018-10-22 16:44:00 momentLength: 15*60*1000 <br>
     * 当前标记signType:1 那么该时刻的标记时间为2018-10-22 16:30:00
     * 当后标记singType:2 那么该时刻的标记时间为2018-10-22 16:45:00
     *
     * @param dateTime     时间毫秒
     * @param signType     标记方式：1前标记 2后标记
     * @param momentLength 时刻长度，单位：毫秒
     * @return 指定时间所在时刻的标记时间，单位：毫秒
     */
    public static long getMomentTime(@NotNull final Long dateTime, @NotNull final int signType, @NotNull final Long momentLength) throws Exception {
        if (24 * 3600 * 1000L % momentLength != 0)
            throw new Exception("时刻长度非法，时刻长度需要能够被一天整除");
        int moment = DateMomentUtil.getMoment(dateTime, momentLength);// 获取指定时间所在时刻数
        long differentTime = moment * momentLength;// 获取从0分0秒开始到现在的时间间隔，单位：毫秒
        long dayStartTime = DateMomentUtil.getDayStartTime(dateTime);
        switch (signType) {
            case 2:
                return dayStartTime + differentTime;
            default:
                return dayStartTime + differentTime - momentLength;
        }
    }

    /**
     * 获取指定时间所在天第一个时刻的标记时间 <br>
     * 例如：dateTime:2018-10-22 16:44:00 momentLength: 15*60*1000 <br>
     * 当前标记signType:1 那么第一个时刻的标记时间为2018-10-22 00:00:00
     * 当后标记singType:2 那么第一个时刻的标记时间为2018-10-22 00:15:00
     *
     * @param dateTime     时间毫秒
     * @param signType     标记方式：1前标记 2后标记
     * @param momentLength 时刻长度，单位：毫秒
     * @return 一天第一个时刻的标记时间，单位：毫秒
     */
    public static long getDayFirstMomentTime(@NotNull final Long dateTime, @NotNull final int signType, @NotNull final Long momentLength) throws Exception {
        if (24 * 3600 * 1000L % momentLength != 0)
            throw new Exception("时刻长度非法，时刻长度需要能够被一天整除");
        long dayStartTime = DateMomentUtil.getDayStartTime(dateTime);
        switch (signType) {
            case 2:
                return dayStartTime + momentLength;
            default:
                return dayStartTime;
        }
    }

    /**
     * 获取指定时间所在天的最后一个时刻的标记时间 <br>
     * 例如：dateTime:2018-10-22 16:44:00 momentLength: 15*60*1000 <br>
     * 当前标记signType:1 那么最后一个时刻的标记时间为2018-10-22 23:45:00
     * 当后标记singType:2 那么最后一个时刻的标记时间为2018-10-23 00:00:00
     *
     * @param dateTime     时间毫秒
     * @param signType     标记方式：1前标记 2后标记, 当null时按照前标记1处理
     * @param momentLength 时刻长度，单位：毫秒
     * @return 一天第一个时刻的标记时间，单位：毫秒
     */
    public static long getDayLastMomentTime(@NotNull final Long dateTime, @NotNull final int signType, @NotNull final Long momentLength) throws Exception {
        if (24 * 3600 * 1000L % momentLength != 0)
            throw new Exception("时刻长度非法，时刻长度需要能够被一天整除");
        Calendar date = Calendar.getInstance();
        date.setTimeInMillis(dateTime);
        date.add(Calendar.DATE, 1);
        date.set(Calendar.HOUR_OF_DAY, 0);
        date.set(Calendar.MINUTE, 0);
        date.set(Calendar.SECOND, 0);
        date.set(Calendar.MILLISECOND, 0);
        switch (signType) {
            case 2:
                return date.getTimeInMillis();
            default:
                return date.getTimeInMillis() - momentLength;
        }
    }

    /**
     * 获取指定时间所在天的0点0分
     *
     * @param dateTime 时间毫秒
     * @return 0点0分的毫秒
     */
    public static long getDayStartTime(@NotNull final Long dateTime) {
        Calendar date = Calendar.getInstance();
        date.setTimeInMillis(dateTime);
        date.set(Calendar.HOUR_OF_DAY, 0);
        date.set(Calendar.MINUTE, 0);
        date.set(Calendar.SECOND, 0);
        date.set(Calendar.MILLISECOND, 0);
        return date.getTimeInMillis();
    }

    /**
     * 获取指定时间所在天的23点59分59秒
     *
     * @param dateTime 时间毫秒
     * @return 23点59分59秒的毫秒
     */
    public static long getDayLastTime(@NotNull final Long dateTime) {
        Calendar date = Calendar.getInstance();
        date.setTimeInMillis(dateTime);
        date.set(Calendar.HOUR_OF_DAY, 23);
        date.set(Calendar.MINUTE, 59);
        date.set(Calendar.SECOND, 59);
        date.set(Calendar.MILLISECOND, 999);
        return date.getTimeInMillis();
    }

    /**
     * 获取两个时间间的间隔天数(自然天)
     * @param dateFrom 开始时间
     * @param dateTo 结束时间
     * @return 自然天数
     */
    public static Integer getDaysBetweenTwoDate(Long dateFrom, Long dateTo) {
        return (int) ((DateMomentUtil.getDayStartTime(dateTo) - DateMomentUtil.getDayStartTime(dateFrom)) / (1000 * 60 * 60 * 24L));
    }



    /**
     * 获取指定时间段有多少时刻
     * 例如：dateTime：2018-10-22 16:44:00 momentLength: 15分钟，既 15*60*1000毫秒
     * 从0点0分开始计算，0点0分-0点15为第一个时刻，依次类推该时间的时刻数为67
     *
     * @param momentLength 时刻长度,单位毫秒
     * @return 时刻
     */
    public static int getIntervalMoment(@NotNull final Long startTime,@NotNull final Long endTime, @NotNull final Long momentLength) {
        return (int) ((endTime - startTime) / momentLength) + 1;
    }

}
