/**
 * Date工具模块
 * @date 2022-03
 * @author 何华东
 */

import * as dayjs from 'dayjs';
import { ParamInvalidError } from './Errors';

/**
 * 日期格式化字符串 => YYYY-MM-DD
 */
export let DATE_FORMAT = 'YYYY-MM-DD';

/**
 * 日期+时间格式化字符串 => YYYY-MM-DD HH:mm:ss
 */
export let DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';

export default class DateUtils {

    /**
     * 时间格式化
     * @param date 需要格式化的时间
     * @param format 时间格式字符串，默认为：'YYYY-MM-DD HH:mm:ss'
     * @returns 
     */
    static format(date: any, format?: string): string {
        return dayjs(date).format(format || 'YYYY-MM-DD HH:mm:ss');
    }

    /**
     * 获取unix时间戳
     * @param date 
     * @returns 
     */
    static getUnixTimestamp(date?: any) {
        return dayjs(date).valueOf();
    }

    /**
     * 求两个时间相差年份数
     * @param dateFrom 开始时间
     * @param dateTo 结束时间
     */
    static diffYears(dateFrom: any, dateTo: any) {
        return dayjs(dateTo).diff(dayjs(dateFrom), 'year');
    }

    /**
     * 求两个时间相差月份数
     * @param dateFrom 开始时间
     * @param dateTo 结束时间
     */
    static diffMonths(dateFrom: any, dateTo: any) {
        return dayjs(dateTo).diff(dayjs(dateFrom), 'month');
    }

    /**
     * 求两个时间相差天数
     * @param dateFrom 开始时间
     * @param dateTo 结束时间
     */
    static diffDays(dateFrom: any, dateTo: any) {
        return dayjs(dateTo).diff(dayjs(dateFrom), 'day');
    }

    /**
     * 求两个时间相差分钟数
     * @param dateFrom 开始时间
     * @param dateTo 结束时间
     */
    static diffMinutes(dateFrom: any, dateTo: any) {
        return dayjs(dateTo).diff(dayjs(dateFrom), 'minute');
    }

    /**
     * 求两个时间相差秒数
     * @param dateFrom 开始时间
     * @param dateTo 结束时间
     */
    static diffSeconds(dateFrom: any, dateTo: any) {
        return dayjs(dateTo).diff(dayjs(dateFrom), 'second');
    }

    /**
     * 求两个时间相差毫秒数
     * @param dateFrom 开始时间
     * @param dateTo 结束时间
     */
    static diffMilliseconds(dateFrom: any, dateTo: any) {
        return dayjs(dateTo).diff(dayjs(dateFrom), 'millisecond');
    }

    /**
     * 对Date的时间部分清零
     * @param date 需要清理的时间
     * @returns 
     */
    static clearTime(date: Date) {
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setMilliseconds(0);

        return date;
    }

    /**
     * 验证时间是否为有效的时间格式
     */
    static isValid(date: any) {
        if (!date) return false;

        return dayjs(date).isValid();
    }

    /**
     * 获取前一个日期的时间,保留时间部分
     */
    static getPrevDate(date?: any) {
        return dayjs(date).add(-1, 'day').toDate();
    }

    /**
     * 获取下一个日期的时间,保留时间部分
     */
    static getNextDate(date?: any) {
        return dayjs(date).add(1, 'day').toDate();
    }

    /**
     * 获取当月第一天的时间,保留时间部分
     */
    static getFirstDayOfMonth(date?: any) {
        return dayjs(date).date(1).toDate();
    }

    /**
     * 获取当月最后一天的时间,保留时间部分
     */
    static getLastDayOfMonth(date?: any) {
        return dayjs(date).date(1).add(1, 'month').add(-1, 'day').toDate();
    }

    /**
     * 按天分割时间
     * 
     * 例如：
        
        2022-5-1 13:23:22~2022-5-31 13:23:22 分割天数为7天

        2022-05-01 13:23:22 ~ 2022-05-07 23:59:59

        2022-05-08 00:00:00 ~ 2022-05-14 23:59:59

        2022-05-15 00:00:00 ~ 2022-05-21 23:59:59

        2022-05-22 00:00:00 ~ 2022-05-28 23:59:59

        2022-05-29 00:00:00 ~ 2022-05-31 13:23:22
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param days 分割天数
     */
    static splitDateByDay(dateFrom: any, dateTo: any, days = 6): { dateFrom: Date, dateTo: Date }[] {
        if (days < 1) throw new ParamInvalidError('days');

        let start = dayjs(dateFrom);
        let end = dayjs(dateTo);
        let times = [];

        while (start.isBefore(end)) {
            let curentEnd = start.add(days, 'day').endOf('day');
            if (curentEnd.isAfter(end)) curentEnd = end;

            times.push({ dateFrom: start.toDate(), dateTo: curentEnd.toDate() });

            start = curentEnd.add(1, 'second');
        }

        return times;
    }
}

export { DateUtils }