package com.house365.ws.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import org.apache.commons.lang.math.NumberUtils;
import org.springframework.util.SocketUtils;

/**
 * 日期时间工具类
 *
 * @author nizhengjia
 * @version 1.0
 */
public class DateUtils {
    /**
     * 年月 格式
     */
    public static final String YEARMONTH = "yyyyMM";
    /**
     * 年-月 格式化
     */
    public static final String YEAR_MONTH = "yyyy-MM";
    /**
     * 日期 格式化:yyyy-MM-dd
     */
    public static final String DATE = "yyyy-MM-dd";
    /**
     * 日期 格式化:yyyyMMdd
     */
    public static final String DATE_WITHOUT_SEPERATOR = "yyyyMMdd";

    public static final String DATE_WITHOUT_SEPERATOR_MIN = "yyyyMMddHHMM";
    /**
     * 日期-小时 格式化
     */
    public static final String DATE_HOUR = "yyyyMMddHH";

    public static final String DATE_HOUR_SECOND = "yyyyMMddHHmmss";
    /**
     * 日期小时 格式化
     */
    public static final String DATE_SPACE_HOUR = "yyyy-MM-dd HH";
    /**
     * 日期小时分钟 格式化
     */
    public static final String DATE_SPACE_MINUTE = "yyyy-MM-dd HH:mm";
    /**
     * 日期时间 格式化
     */
    public static final String TIMESTAMP = "yyyy-MM-dd HH:mm:ss";

    /**
     * 1年之中的月份
     */
    public static final int ONE_YEAR_MONTHS = 12;
    /**
     * 1周的天数
     */
    public static final int ONE_WEEK_DAYS = 7;
    /**
     * 一秒的毫秒数
     */
    public static int ONE_SECOND_MILLI_SECONDS = 1000;
    /**
     * 一分钟的秒数
     */
    public static int ONE_MINUTE_SECONDS = 60;
    /**
     * 一分钟的毫秒数
     */
    public static int ONE_MINUTE_MILLISECONDS = ONE_MINUTE_SECONDS * ONE_SECOND_MILLI_SECONDS;
    /**
     * 一小时的秒数
     */
    public static final int ONE_HOUR_SECONDS = 60 * ONE_MINUTE_SECONDS;
    /**
     * 一小时的毫秒数
     */
    public static final int ONE_HOUR_MILLISECONDS = 60 * 60 * 1000;
    /**
     * 一天的秒数
     */
    public static int ONE_DAY_SECONDS = 24 * 60 * 60;
    /**
     * 两天的秒数
     */
    public static int TWO_DAY_SECONDS = ONE_DAY_SECONDS * 2;
    /**
     * 一周的秒数
     */
    public static int ONE_WEEK_SECONDS = ONE_DAY_SECONDS * ONE_WEEK_DAYS;
    /**
     * 一天 365 天的秒数
     */
    public static int ONE_YEAR_SECONDS = ONE_DAY_SECONDS * 365;
    /**
     * 一天的毫秒数
     */
    public static int ONE_DAY_MILLI_SECONDS = 24 * 60 * 60 * 1000;

    private static final int LAST_SECOND_OF_MINUTE = 59;
    private static final int LAST_MINUTE_OF_HOUR = 59;
    private static final int LAST_HOUR_OF_DAY = 23;


    /**
     * 功能描述: <br>
     * 根据指定格式对当前日期进行格式化
     * (传入：String，返回：String)
     *
     * @param date   date 传入日期类型日期
     * @param format format 需要转化的格式
     * @return String 转换后的字符串格式日期
     */
    public static String parseDate(Date date, String format) {
        SimpleDateFormat dateformat = new SimpleDateFormat(format);
        return dateformat.format(date);
    }

    /**
     * 功能描述: <br>
     * 根据指定格式对当前日期进行格式化
     * (传入：String，返回：String)
     *
     * @param date date 传入日期类型日期
     * @return String 转换后的字符串格式日期
     */
    public static String dateToStr(Date date) {
        SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");
        return dateformat.format(date);
    }

    /**
     * 功能描述: <br>
     * 是否同一天
     *
     * @return String 转换后的字符串格式日期
     */
    public static boolean isSameDay(Date date, Date date2) {
        if (date == null || date2 == null) {
            return false;
        }
        if (dateToStr(date).equals(dateToStr(date2))) {
            return true;
        } else {
            return false;
        }
    }


    /**
     * 功能描述: <br>
     * 根据指定格式对当前日期进行格式化
     * (传入：String，返回：Date)
     *
     * @param datestr     传入字符串类型日期
     * @param dateFormate 需要转化的格式
     * @return Date 转换后的日期类型日期
     */
    public static Date parseDate(String datestr, String dateFormate) {
        SimpleDateFormat df = new SimpleDateFormat(dateFormate);
        Date date = null;
        try {
            date = df.parse(datestr);
        } catch (java.text.ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 功能描述: <br>
     * 根据指定格式对当前日期进行格式化
     * (传入：String，返回：String)
     *
     * @param datestr 传入字符串类型日期
     *                需要转化的格式为yyyy-MM-dd
     * @return String 转换后的日期类型日期
     */
    public static String parseDate(String datestr) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String str = null;
        Date date = null;
        try {
            date = df.parse(datestr);
            str = df.format(date);
        } catch (java.text.ParseException e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 功能描述: <br>
     * 获取指定日期的月份第一天的时间
     * (传入：Date，返回：String)
     *
     * @param date 日期类型
     * @return 如2014-06-01 00:00:00 字符串
     */
    public static String getMonthBegin(Date date) {
        return parseDate(date, "yyyy-MM") + "-01 00:00:00";
    }

    /**
     * 功能描述: <br>
     * 获取指定日期的月份最后一天的时间
     * (传入：Date，返回：String)
     *
     * @param targetDate 日期类型
     * @return 如2014-06-30 23:59:59 字符串
     */
    public static String getMonthEnd(Date targetDate) {
        Date date = parseDate(getMonthBegin(targetDate), "yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 1);
        calendar.add(Calendar.DAY_OF_YEAR, -1);
        String strResult = "";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        strResult = simpleDateFormat.format(calendar.getTime());
        simpleDateFormat = null;
        calendar = null;
        return strResult + " 23:59:59";
    }

    /**
     * 功能描述: <br>
     * 获取指定日期的月份最后一天的时间
     * (传入：Date,int ，返回：String)
     *
     * @param dt 日期类型
     * @return 如2014-06-30 23:59:59 字符串
     * @int y 指定int类型的月份(1:前一个月，2：前二个月，3：前三个月，4：前四个月，5：前五个月)
     */
    public static String getMonthsAgo(Date dt, int y) {
        Date nextDate = null;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MONTH, -y);
        nextDate = calendar.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        String dateTime = sdf.format(nextDate);
        return dateTime;

    }

    /**
     * 功能描述: <br>
     * date转毫秒
     */
    public static long millionSeconds(Date dt) {
        long hm = dt.getTime();
        return hm;
    }


    /**
     * 获取一个月的最后一天
     *
     * @param year  yyyy
     * @param month MM
     * @return
     */
    public static String getLastDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DATE));
        return new SimpleDateFormat("yyyy-MM-dd ").format(cal.getTime());
    }

    /**
     * 获取一个月的第一天
     *
     * @param year  yyyy
     * @param month MM
     * @return
     */
    public static String getFirstDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH, cal.getMinimum(Calendar.DATE));
        return new SimpleDateFormat("yyyy-MM-dd ").format(cal.getTime());
    }


    /**
     * 获取某年中某一个月的天数
     *
     * @param dyear  yyyy
     * @param dmouth MM
     * @return
     */
    public static int calDayByYearAndMonth(String dyear, String dmouth) {
        SimpleDateFormat simpleDate = new SimpleDateFormat("yyyy/MM");
        Calendar rightNow = Calendar.getInstance();
        try {
            rightNow.setTime(simpleDate.parse(dyear + "/" + dmouth));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return rightNow.getActualMaximum(Calendar.DAY_OF_MONTH);// 根据年月 获取月份天数
    }

    /**
     * 计算两个日期之间相差的天数(四舍五入)
     *
     * @param smdate 较小的时间
     * @param bdate  较大的时间
     * @return 相差天数
     * @throws ParseException
     */
    public static int daysBetween(Date smdate, Date bdate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            /*smdate = sdf.parse(sdf.format(smdate));
            bdate = sdf.parse(sdf.format(bdate));*/
        //System.out.println("smdate:"+sdf.format(smdate)+"-----bdate:"+sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days = (time2 - time1) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * 字符串的日期格式的计算
     *
     * @param smdate yyyy-MM-dd
     * @param bdate  yyyy-MM-dd
     * @return
     * @throws ParseException
     */
    public static int daysBetween(String smdate, String bdate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        cal.setTime(sdf.parse(smdate));
        long time1 = cal.getTimeInMillis();
        cal.setTime(sdf.parse(bdate));
        long time2 = cal.getTimeInMillis();
        long between_days = (time2 - time1) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * 获取当前日期的季度 1.
     * 第一季度：1月1号，3月31号 2.
     * 第二季度：4月1号，6月30号 3.
     * 第三季度：7月1号，9月30号 4.
     * 第四季度：10月1号，12月31号
     */
    public static int getCurrentQuarter() throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String nowDate = sdf.format(new Date());
        Calendar cal = Calendar.getInstance();
        int currentYear = cal.get(Calendar.YEAR);
        if (daysBetween(currentYear + "-4-1", nowDate) < 0) {
            return 1;
        } else if (daysBetween(currentYear + "-7-1", nowDate) < 0) {
            return 2;
        } else if (daysBetween(currentYear + "-10-1", nowDate) < 0) {
            return 3;
        } else {
            return 4;
        }
    }

    /**
     * 获取当前时间在当前季度中所属天数
     *
     * @return
     * @throws ParseException
     */
    public static int getCurrentDaysCountInCurrentQuarter() throws ParseException {
        int i = getCurrentQuarter();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String nowDate = sdf.format(new Date());
        Calendar cal = Calendar.getInstance();
        int currentYear = cal.get(Calendar.YEAR);
        switch (i) {
            case 1:
                return daysBetween(currentYear + "-1-1", nowDate) + 1;
            case 2:
                return daysBetween(currentYear + "-4-1", nowDate) + 1;
            case 3:
                return daysBetween(currentYear + "-7-1", nowDate);
            case 4:
                return daysBetween(currentYear + "-10-1", nowDate);
            default:
                return 0;
        }
    }

    /**
     * 获取日期的季度
     */
    public static int getQuarterByDateString(String dateStr) {
        return 1;
    }


    public static String dateToString(Date date) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        return sdf.format(date);
    }

    public static Date getSomeDate(int i) {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.DATE, i);
        return c.getTime();
    }

    public static Date getFirstDayOfCurrentMonth() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        String date = sdf.format(new Date()) + "-01";
        sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date newDate = sdf.parse(date);
            return newDate;
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }

    }

    /**
     * 获取N天之前的那天
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param i
     * @return
     * @author yinchangming
     * @version [v1.0.0, 2015年10月29日]
     * @since [产品/模块版本](可选)
     */
    public static Date getSeveralDaysBefore(int i) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DATE, cal.get(Calendar.DATE) - i);
        return cal.getTime();
    }

    /**
     * 日期转换为指定格式的字符
     *
     * @param date       日期
     * @param dateFormat 日期格式
     * @return
     */
    public static String dateToString(Date date, String dateFormat) {
        String returnValue = "";
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(dateFormat);
            returnValue = df.format(date);
        }
        return returnValue;
    }

    /**
     * 传入格式，返回今天的日期字串
     */
    public static String getTodayStr(String format) {
        String todayStr = dateToString(new Date(), format);
        return todayStr;
    }

    /**
     * 获取上个月的月份字串【yyyyMM】
     */
    public static String getLastMonthStr() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -1);
        String lastMonthStr = dateToString(calendar.getTime(), YEARMONTH);
        return lastMonthStr;
    }

    /**
     * 获取今天所在的月份字串【yyyyMM】
     */
    public static String getCurMonthStr() {
        String todayStr = dateToString(new Date(), YEARMONTH);
        return todayStr;
    }

    /**
     * 以当期日期为基准，返回指定日期类型日期增量日期。
     *
     * @param dateType 日期类型
     * @param count    增加数量，可以为负数
     * @return
     */
    public static Date getMagicDate(int dateType, int count) {
        Calendar calendar = new GregorianCalendar();
        Date todayTime = new Date();
        calendar.setTime(todayTime);
        calendar.add(dateType, count);
        return calendar.getTime();
    }

    /**
     * 返回指定日期类型日期增量日期
     *
     * @param dateType 日期类型
     * @param count    增加数量，可以为负数
     * @param baseDate 参照日期
     * @return
     */
    public static Date getMagicDate(int dateType, int count, Date baseDate) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(baseDate);
        calendar.add(dateType, count);
        return calendar.getTime();
    }

    /**
     * 获取interval个月之后的日期，interval可以为负数，表示n个月之前的一个月
     *
     * @param interval 间隔的月份，interval可以为负数，表示n个月之前的一个月
     * @return interval个月之后的日期
     */
    public static Date getMagicMonth(int interval) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.MONTH, (calendar.get(Calendar.MONTH) + interval));
        Date date = calendar.getTime();
        return date;
    }

    /**
     * 获取interval个月之后的月份，interval可以为负数，表示n个月之前的一个月
     *
     * @param interval 间隔的月份，interval可以为负数，表示n个月之前的一个月
     * @return interval个月之后的月份
     */
    public static int getMagicYearMonth(int interval) {
        Date date = getMagicMonth(interval);
        String yearMonth = parseDate2Str(YEARMONTH, date);

        return NumberUtils.isNumber(yearMonth) ? Integer.parseInt(yearMonth) : 0;
    }

    /**
     * 转换时间
     *
     * @param format
     * @param date
     * @return
     */
    public static String parseDate2Str(String format, Date date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(date);
    }

    public static Date getDayBefore(int diffDay) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, diffDay);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }


    public static void main(String[] args) {
        Date test = getSeveralDaysBefore(7);
        System.out.println(test);

        for (int i = 0; i <= 52; i++) {
            Date date = getDayBefore(-i);
            System.out.println(parseDate(date, TIMESTAMP));
        }

    }
}
