package com.yeejoin.amos.jpush.service.core.util;

import java.sql.Time;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Period;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import com.yeejoin.amos.jpush.service.exception.YeeException;

/**
 * <pre>
 * 日期
 * </pre>
 *
 * @author as-chenjiajun
 * @version $Id: DateUtil.java, v 0.1 2018年1月29日 下午5:08:40 as-chenjiajun Exp $
 */
public class DateUtil {
    public static String LONG_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static String MID_PATTERN = "yyyy-MM-dd HH:mm";
    public static String SHORT_PATTERN = "yyyy-MM-dd";


    public static long THREE_DAY_MILLSEC = 259200000L;
    public static long ONE_DAY_MILLSEC = 86400000L;
    public static long ONE_HOUR_MILLSEC = 3600000L;
    public static long THREE_HOURS_MILLSEC = 10800000L;
    public static long TWELVE_HOURS_MILLSEC = 43200000L;


    public static Date EMPTY_DATE = null;

    static {
        Calendar calendar = Calendar.getInstance();
        calendar.set(9999, 0, 0);
        EMPTY_DATE = calendar.getTime();
    }

    /**
     * <pre>
     * 获取当前北京时间
     * </pre>
     *
     * @return
     */
    public static Date getCurrentDate() {
        return getCurrentCalendar().getTime();
    }

    public static String getLongCurrentDate() {
        return new SimpleDateFormat(LONG_PATTERN)
                .format(getCurrentCalendar().getTime());
    }

    public static String getLongDate(Date date) {
        if (null == date)
            return getLongCurrentDate();
        else
            return new SimpleDateFormat(LONG_PATTERN).format(date);
    }

    public static String getLongDate(long value) {
        return new SimpleDateFormat(LONG_PATTERN).format(new Date(value));
    }

    public static String getShortCurrentDate() {
        return new SimpleDateFormat(SHORT_PATTERN).format(new Date());
    }

    public static String getShortDate(Date date) {
        if (null == date)
            return getShortCurrentDate();
        else
            return new SimpleDateFormat(SHORT_PATTERN).format(date);
    }

    public static String getShortDate(long value) {
        return new SimpleDateFormat(SHORT_PATTERN).format(new Date(value));
    }

    public static Date getShortCurrentDate(String shortDateStr) throws ParseException {
        return new SimpleDateFormat(SHORT_PATTERN).parse(shortDateStr);
    }

    public static Date getLongDate(String longDateStr) throws ParseException {
        return new SimpleDateFormat(LONG_PATTERN).parse(longDateStr);
    }

    public static String getMidCurrentDate() {
        return new SimpleDateFormat(MID_PATTERN).format(new Date());
    }

    public static String getMidDate(Date date) {
        if (null == date)
            return getMidCurrentDate();
        else
            return new SimpleDateFormat(MID_PATTERN).format(new Date());
    }

    public static String getMidDate(long value) {
        return new SimpleDateFormat(MID_PATTERN).format(new Date(value));
    }

    public static Date str2Date(String strDate, String dateFormat) {
        SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
        ParsePosition pos = new ParsePosition(0);
        Date strtodate = formatter.parse(strDate, pos);
        return strtodate;
    }

    public static int getYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = calendar.get(Calendar.YEAR);
        return year;
    }

    public static int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int month = calendar.get(Calendar.MONTH) + 1;
        return month;
    }

    public static int getDay(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int day = c.get(Calendar.DATE);
        return day;
    }

    public static int getHour(Date date) {

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int hour = c.get(Calendar.HOUR_OF_DAY);
        return hour;
    }

    public static int getMinite(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int minite = c.get(Calendar.MINUTE);
        return minite;
    }

    /**
     * <pre>
     * 获取当前北京时间
     * </pre>
     *
     * @return
     */
    public static Calendar getCurrentCalendar() {
        TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
        return Calendar.getInstance();
    }

    /**
     * <pre>
     * 获取当前两个时间差
     * </pre>
     *
     * @return
     */
    public static String getTimeDifference(Date dateBefore, Date dateAfter) {
        long l = dateAfter.getTime() - dateBefore.getTime();
        long day = l / (24 * 60 * 60 * 1000);
        long hour = (l / (60 * 60 * 1000) - day * 24);
        long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = (l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        return "" + day + "天" + hour + "小时" + min + "分" + s + "秒";
    }

    /**
     * 获取某年某月的第一天日期
     *
     * @param date
     * @param format
     * @return
     */
    public static String getStartMonthDate(String date, String format) {
        if (date == null || date.length() < 6 || format == null) {
            return null;
        }
        int year = Integer.parseInt(date.substring(0, 4));
        int month = Integer.parseInt(date.substring(4, 6));
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, 1);
        return new SimpleDateFormat(format).format(calendar.getTime());
    }

    /**
     * 获取某年某月的最后一天日期
     *
     * @param date
     * @param format
     * @return
     */
    public static String getEndMonthDate(String date, String format) {
        if (date == null || date.length() < 6 || format == null) {
            return null;
        }
        int year = Integer.parseInt(date.substring(0, 4));
        int month = Integer.parseInt(date.substring(4, 6));
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, 1);
        int day = calendar.getActualMaximum(5);
        calendar.set(year, month - 1, day);
        return new SimpleDateFormat(format).format(calendar.getTime());
    }

    /**
     * 获取某天的间隔天数
     *
     * @param date
     * @param interval 间隔天数。负数为前，正数为后
     * @param format   输出格式化
     * @return
     */
    public static String getIntervalDateStr(Date date, int interval, String format) {
        if (date == null || format == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, interval);
        return new SimpleDateFormat(format).format(calendar.getTime());
    }

    /**
     * 获取某天的年初第一天
     *
     * @param date
     * @param format 输出格式化
     * @return
     */
    public static String getFirstDayOfYear(String date, String format) {
        int year = Integer.parseInt(date.substring(0, 4));
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, Calendar.JANUARY, 1);
        return new SimpleDateFormat(format).format(calendar.getTime());
    }

    /**
     * 获取某天的年初第一天
     *
     * @param date
     * @param format 输出格式化
     * @return date
     */
    public static Date getFirstDayOfYearDate(String date) {
        int year = Integer.parseInt(date.substring(0, 4));
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, Calendar.JANUARY, 1);
        return calendar.getTime();
    }

    /**
     * 获取某天的年末最后一天
     *
     * @param date
     * @param format 输出格式化
     * @return date
     */
    public static Date getLastDayOfYearDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        final int last = calendar.getActualMaximum(Calendar.DAY_OF_YEAR);
        calendar.set(Calendar.DAY_OF_YEAR, last);
        return calendar.getTime();
    }


    /**
     * 获取某天的间隔天数
     *
     * @param date
     * @param interval 间隔天数。负数为前，正数为后
     * @param format   输出格式化
     * @return
     */
    public static Date getIntervalDate(Date date, int interval) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, interval);
        return calendar.getTime();
    }

    /**
     * 获得指定日期的间隔周末
     *
     * @param exeDate
     * @param init
     * @return
     */
    public static Date getIntervalWeekDate(Date exeDate, int init) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(exeDate);
        calendar.add(Calendar.DATE, init * 7);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        return calendar.getTime();
    }

    /**
     * 获得制定日期间隔的上个月最后一天
     *
     * @param exeDate
     * @param inter
     * @return
     */
    public static Date getEndMonthDate(Date exeDate, int inter) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(exeDate);
        calendar.add(Calendar.MONTH, inter - 1);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return calendar.getTime();
    }

    /**
     * 获取间隔周的
     *
     * @param mounthFirstDate
     * @param whatWeek
     * @param weekDay
     * @return
     */
    public static Date getIntMonthWeekDate(Date mounthFirstDate, int week, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(mounthFirstDate);
        if (day == 7) {
            day = 1;
            week = week + 1;
        } else {
            day = day + 1;
        }
        calendar.set(Calendar.WEEK_OF_MONTH, week);
        calendar.set(Calendar.DAY_OF_WEEK, day);
        return calendar.getTime();
    }

    /**
     * 获取间隔的年日期
     *
     * @param planDegin
     * @param init
     * @return
     */
    public static String getIntervalYearDate(Date planDegin, int init) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(planDegin);
        calendar.add(Calendar.YEAR, init);
        return new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
    }

    /**
     * 格式化日期
     *
     * @param beginDate
     * @param string
     * @return
     */
    public static String formatDatrToStr(Date beginDate, String formart) {
        SimpleDateFormat df = new SimpleDateFormat(formart);
        String strDate = df.format(beginDate);
        return strDate;
    }

    public static Time formatStrToTime(String strDate) {
        String str = strDate;
        SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss");
        Date d = null;
        try {
            d = format.parse(str);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Time date = new Time(d.getTime());
        return date;
    }

    /**
     * 获得间隔分钟的时间
     *
     * @param strBeginTime 被操作时间
     * @param duration     间隔分钟数
     * @param string       格式化的格式
     * @return
     */
    public static String getIntMinStrDate(String strBeginTime, int duration, String formart) {
        SimpleDateFormat df = new SimpleDateFormat(formart);
        Date date;
        try {
            date = df.parse(strBeginTime);
        } catch (ParseException e) {
            throw new YeeException("格式化日期失败");
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, duration);
        String strDate = df.format(calendar.getTime());
        return strDate;
    }

    public static String cronTime(Date date) {

        StringBuilder cron = new StringBuilder();
        cron.append(date.getSeconds()).append(" ")
                .append(date.getMinutes()).append(" ")
                .append(date.getHours()).append(" ")
                .append(date.getDay()).append(" ")
                .append(date.getMonth()).append(" ")
                .append("?").append(" ")
                .append(date.getYear());
        return cron.toString();

    }

    /**
     * 获取指定日期的周一
     */
    public static Date getThisWeekMonday(Date date) {
        Calendar cal = getCurrentCalendar();
        cal.setTime(date);
        // 获得当前日期是一个星期的第几天
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }
        // 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        // 获得当前日期是一个星期的第几天
        int day = cal.get(Calendar.DAY_OF_WEEK);
        // 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
        return cal.getTime();
    }

    /**
     * 获取指定日期的月份第一天
     */
    public static Date getThisMonthFirstDay(Date date) {
        Calendar cal = getCurrentCalendar();
        cal.setTime(date);
        //获取某月最小天数
        int firstDay = cal.getMinimum(Calendar.DATE);
        //设置日历中月份的最小天数
        cal.set(Calendar.DAY_OF_MONTH, firstDay);
        return cal.getTime();
    }

    public static Date getCurrYearFirst() {
        Calendar currCal = getCurrentCalendar();
        int currentYear = currCal.get(Calendar.YEAR);
        return getYearFirst(currentYear);
    }

    public static Date getCurrYearLast() {
        Calendar currCal = getCurrentCalendar();
        int currentYear = currCal.get(Calendar.YEAR);
        return getYearLast(currentYear);
    }

    public static Date getYearFirst(int year) {
        Calendar calendar = getCurrentCalendar();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        return calendar.getTime();
    }

    public static Date getYearLast(int year) {
        Calendar calendar = getCurrentCalendar();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        return calendar.getTime();
    }
    
    /**
     * 获得指定日期所在周第一天
     * @param planBegin
     * @return
     */
	public static String getFirstDayOfWeekAtDay(String planBegin) {
		Calendar calendar = Calendar.getInstance();
		calendar.setFirstDayOfWeek(Calendar.MONDAY);
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		Date date;
		try {
			date = df.parse(planBegin);
		} catch (ParseException e) {
			throw new YeeException("日期格式化失败");
		}
		
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_WEEK,Calendar.MONDAY);
		return df.format(calendar.getTime());
	}
	
	/**
	 * 获得指定日期所在周第一天
	 * @param planEnd
	 * @return
	 */
	public static String getEndDayOfWeekAtDay(String planEnd) {
		Calendar calendar = Calendar.getInstance();
		calendar.setFirstDayOfWeek(Calendar.MONDAY);
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		Date date;
		try {
			date = df.parse(planEnd);
		} catch (ParseException e) {
			throw new YeeException("日期格式化失败");
		}
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_WEEK,Calendar.SUNDAY);
		return df.format(calendar.getTime());
	}
	
	/**
	 * 获得日期在周的天数
	 * @param planBegin
	 * @return
	 * @throws ParseException
	 */
	public static int getDayOfWeek(String planBegin) {
		Calendar calendar = Calendar.getInstance();	
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		Date date;
		try {
			date = df.parse(planBegin);
		} catch (ParseException e) {
			throw new YeeException("日期格式化失败");
		}
		calendar.setFirstDayOfWeek(Calendar.MONDAY);
		calendar.setTime(date);
		int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
		if(dayOfWeek == 0) {
			dayOfWeek = 7;
		}
		return dayOfWeek;
	}

	/**
	 * 计算两个日期间隔天数
	 * @param beginData
	 * @param endData
	 * @return
	 */
	public static int calInterverDay(String beginDate,String endDate){
		LocalDate ld1 = LocalDate.parse(beginDate);
		LocalDate ld2 = LocalDate.parse(endDate);
		Period pe = Period.between(ld1, ld2);
		return pe.getDays();
	}
	
	/**
	 * 获得日期所在周
	 * @param beginData
	 * @return
	 * @throws ParseException
	 */
	public static int calAtWeekOfDay(String srtdate){
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		Date date1;
		try {
			date1 = df.parse(srtdate);
		} catch (ParseException e) {
			throw new YeeException("日期格式化失败");
		}
		Calendar calendar = Calendar.getInstance();	
		calendar.setFirstDayOfWeek(Calendar.MONDAY);
		calendar.setTime(date1);
		return calendar.get(Calendar.WEEK_OF_YEAR);
	}

    public static Date getDateByNumber(Date date, Integer dayNumber) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, dayNumber);
        return cal.getTime();
    }

    public static Date getHourBeginOfDay(int hour) {
    	Calendar cal = Calendar.getInstance();
    	cal.set(Calendar.HOUR_OF_DAY, hour);
    	cal.set(Calendar.MINUTE, 0);
    	cal.set(Calendar.SECOND, 0);
    	return cal.getTime();
    }
}
