package com.qs.mp.common.utils;

import java.lang.management.ManagementFactory;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.Months;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import com.alibaba.fastjson.JSON;

/**
 * 时间工具类
 *
 * @author ygp
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{
    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

    public static String YYYYMM = "yyyyMM";

    public static String YYYY_MM_DD = "yyyy-MM-dd";

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String YYYYMMDD = "yyyyMMdd";

    public static String YYYYDOTMMDOTDD = "yyyy.MM.dd";

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    /**
     * 获取当前Date型日期
     *
     * @return Date() 当前日期
     */
    public static Date getNowDate()
    {
        return new Date();
    }

    public static Date getToday() {
        String s = parseDateToStr(YYYY_MM_DD, new Date());
        return dateTime(YYYY_MM_DD, s);
    }

    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     *
     * @return String
     */
    public static String getDate()
    {
        return dateTimeNow(YYYY_MM_DD);
    }

    public static final String getTime()
    {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }

    public static final String dateTimeNow()
    {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }

    public static final String dateTimeNow(final String format)
    {
        return parseDateToStr(format, new Date());
    }

    public static final String dateTime(final Date date)
    {
        return parseDateToStr(YYYY_MM_DD, date);
    }

    public static final String parseDateToStr(final String format, final Date date)
    {
        return new SimpleDateFormat(format).format(date);
    }

    public static final Date dateTime(final String format, final String ts)
    {
        try
        {
            return new SimpleDateFormat(format).parse(ts);
        }
        catch (ParseException e)
        {
            throw new RuntimeException(e);
        }
    }

    public static final Date parseDateToDay(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String s = sdf.format(date);
        try {
            return sdf.parse(s);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 计算两个日期之间相差多少天，一个月按30天算
     * @param begin
     * @param end
     * @return
     */
    public static final int diff(Date begin, Date end) {
        DateTimeFormatter formatter = DateTimeFormat.forPattern(YYYY_MM_DD);
        DateTime startDay = formatter.parseDateTime(parseDateToStr(YYYY_MM_DD, begin));
        DateTime endDay = formatter.parseDateTime(parseDateToStr(YYYY_MM_DD, end));
        int days = Days.daysBetween(startDay, endDay).getDays();
        return days;
    }

    /**
     * 计算两个日期之间相差多少个月
     * @param begin
     * @param end
     * @return
     */
    public static final int diffMonth(Date begin, Date end) {

        DateTimeFormatter formatter = DateTimeFormat.forPattern(YYYY_MM_DD);
        DateTime startDay = formatter.parseDateTime(parseDateToStr(YYYY_MM_DD, begin));
        DateTime endDay = formatter.parseDateTime(parseDateToStr(YYYY_MM_DD, end));
        int months = Months.monthsBetween(startDay, endDay).getMonths();
        return months;
    }

    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static final String datePath()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static final String dateTime()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }

    public static final Date parseStrToDate(String str, String pattern){
        if (str == null)
        {
            return null;
        }
        try
        {
            return parseDate(str, pattern);
        }
        catch (ParseException e)
        {
            return null;
        }
    }
    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str)
    {
        if (str == null)
        {
            return null;
        }
        try
        {
            return parseDate(str.toString(), parsePatterns);
        }
        catch (ParseException e)
        {
            return null;
        }
    }

    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate()
    {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 计算两个时间差
     */
    public static String getDatePoor(Date endDate, Date nowDate)
    {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }

    public static Date getNowAddMonth(Date now, int months) {
    	SimpleDateFormat sj = new SimpleDateFormat("yyyyMMdd");
        try {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(now);
            calendar.add(Calendar.MONTH, months);
            return calendar.getTime();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    // 首页统计日期处理
 	 /** 
 	 * 取得指定日期的前面几天日期
 	 */ 
 	 public static Date getPreDayOfNow(int days) { 
 		try {
			Calendar c = Calendar.getInstance();
		   	c.setFirstDayOfWeek(Calendar.MONDAY); 
		   	c.add(Calendar.DATE, - days);
		   	return c.getTime(); 
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
 	 }
    
    
  	 /** 
  	 * 取得指定日期的前面几天日期0点
  	 */ 
  	 public static Date getPreDayOfNowZero(int days) { 
  		try {
			Calendar c = Calendar.getInstance();
		   	c.setFirstDayOfWeek(Calendar.MONDAY); 
		   	c.add(Calendar.DATE, - days);
		   	c.set(Calendar.HOUR_OF_DAY, 0);
		   	c.set(Calendar.MINUTE, 0);
		   	c.set(Calendar.SECOND, 0);
		   	return c.getTime(); 
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
  	 }
  	 
  	/** 
   	 * 取得指定日期的最晚时间
   	 */ 
   	 public static Date getEndTimeOfNow(Date endDate) { 
   		try {
 			Calendar c = Calendar.getInstance();
 		   	c.setTime(endDate);
 		   	c.set(Calendar.HOUR_OF_DAY, 23);
 		   	c.set(Calendar.MINUTE, 59);
 		   	c.set(Calendar.SECOND, 59);
 		    c.set(Calendar.MILLISECOND, 59);
 		   	return c.getTime(); 
 		} catch (Exception e) {
 			e.printStackTrace();
 			return null;
 		}
   	 }
    
    /** 
     * @Title: getDateOfWeek 
     * @Description: 获取两个时间内所有周之间的时间段，并且获得是今年第几周
     * @param start_time    开始时间 
     * @param end_time      结束时间 
     */  
    public static List<Map<String,Object>> getDateOfWeek(Date startTime, Date endTime) {
    	List<Map<String,Object>> rtnList = new ArrayList<Map<String,Object>>();
    	try {  
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");  
            
            Calendar startCalendar = Calendar.getInstance();  
            startCalendar.setTime(startTime);  
            
            Calendar endCalendar = Calendar.getInstance();  
            endCalendar.setTime(endTime);  
            
            String firstWeekDay = getFirstDayOfWeek(startTime);  // 取得开始日期指定日期所在周的第一天
	        String lastWeekDay = getLastDayOfWeek(endTime);      // 取得结束日期指定日期所在周的最后一天
	        
            // 开始日期所在的周
            int startWeekOfYear = startCalendar.get(Calendar.WEEK_OF_YEAR);  
            System.out.println("startWeekOfYear == " +startWeekOfYear);
            
            // 截止日期所在的周
            int endWeekOfYear = endCalendar.get(Calendar.WEEK_OF_YEAR);  
            System.out.println("currentWeekOfYear_e == " +endWeekOfYear);
              
            int j = 12;  
            for (int i=0; i < endWeekOfYear + 53; i++) {  
            	
            	 //只取两个日期之间的周  
//                if(startWeekOfYear > endWeekOfYear - i){  
//                    break;  
//                }  
                int dayOfWeek = endCalendar.get(Calendar.DAY_OF_WEEK) - 2;  
                
                System.out.println("dayOfWeek == " +dayOfWeek);
            	List<String> list = new ArrayList<>();
                
                endCalendar.add(Calendar.DATE, - dayOfWeek); //得到本周的第一天  
                String s_date = sdf.format(endCalendar.getTime());  
                
                Long startTIme = endCalendar.getTimeInMillis();   
                
                endCalendar.add(Calendar.DATE, 6);  //得到本周的最后一天  
                String e_date = sdf.format(endCalendar.getTime());  
               
                //结束时间转换成时间戳
                Long endTIme = endCalendar.getTimeInMillis();
               
                //定义一个一天的时间戳时长
                Long oneDay = 1000 * 60 * 60 * 24L;
                Long time = startTIme;
                //循环得出
                while (time <= endTIme) {
                    list.add(new SimpleDateFormat("yyyyMMdd").format(new Date(time)));
                    time += oneDay;
                }
                endCalendar.add(Calendar.DATE, -j); //减去增加的日期  
                System.out.println("");
                //只取两个日期之间的周
	            if(compareDate(firstWeekDay, s_date) && compareDate(s_date, lastWeekDay)
	            		&& compareDate(firstWeekDay, e_date) && compareDate(e_date, lastWeekDay)){
	            	//超过选择的日期，按选择日期来算
	            	if(!compareDate(sdf.format(startTime), s_date)){
	 	            	s_date = sdf.format(startTime);
	 	            }
	            	if(!compareDate(e_date, sdf.format(endTime))){
	 	            	e_date = sdf.format(endTime);
	 	            }
	            	 Calendar yearCalendar = Calendar.getInstance();  
	            	 yearCalendar.setTime(startTime);  
	            	int year = yearCalendar.get(Calendar.YEAR);  
	            	String s = year+ "年的第" + (endWeekOfYear - i) + "周" + "(" + s_date + "至" + e_date + ")";     
	                System.out.println(s);  
	               // System.out.println("包含的日期 = " +list.toString());
	                Map<String,Object> map = new HashMap<String,Object>();
	                map.put("start", s_date);
	                map.put("end", e_date);
	                map.put("year", year);
	                map.put("week", endWeekOfYear - i);
	                map.put("dayList", list);
	                rtnList.add(map);
	            }
               
            }  
              
        } catch (Exception e) {  
            e.printStackTrace();  
        }
    	Collections.reverse(rtnList);
    	return rtnList;
    }
    
    
    /** 
   	 * 取得指定日期所在周的第一天 
   	 */ 
   	 public static String getFirstDayOfWeek(Date date) { 
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
			Calendar c = new GregorianCalendar(); 
		   	c.setFirstDayOfWeek(Calendar.MONDAY); 
		   	c.setTime(date); 
		   	c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek()); // Monday 
		   	return sdf.format(c.getTime()); 
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
        
	   	
   	 }
 
   	 /** 
   	 * 取得指定日期所在周的最后一天 
   	 */ 
   	 public static String getLastDayOfWeek(Date date) { 
   		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
			Calendar c = new GregorianCalendar(); 
		   	c.setFirstDayOfWeek(Calendar.MONDAY); 
		   	c.setTime(date); 
		   	c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6); // Sunday 
		   	return sdf.format(c.getTime()); 
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
   	 }
   	 
   	/**
 	 * compareDate方法
 	 * <p>方法说明：
 	 * 		比较endDate是否是晚于startDate；
 	 * 			如果是，返回true， 否则返回false
 	 * </p>
 	 */
  	public static boolean compareDate(String startDate, String endDate) {
 		try {
 			DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
 			java.util.Date date1 = dateFormat.parse(startDate);
 			java.util.Date date2 = dateFormat.parse(endDate);
 			if (date1.getTime() > date2.getTime())
 				return false;
 			return true; //startDate时间上早于endDate
 			
 		} catch (Exception e) {
 			return false; 
 		}
 	}


    /**
     * @param cntDateBeg 开始时间
     * @param cntDateEnd 结束时间
     * @return
     */
    public static List<String> addDates(String cntDateBeg, String cntDateEnd) {
        List<String> list = new ArrayList<>();
        //拆分成数组
        String[] dateBegs = cntDateBeg.split("-");
        String[] dateEnds = cntDateEnd.split("-");
        //开始时间转换成时间戳
        Calendar start = Calendar.getInstance();
        start.set(Integer.valueOf(dateBegs[0]), Integer.valueOf(dateBegs[1]) - 1, Integer.valueOf(dateBegs[2]));
        Long startTIme = start.getTimeInMillis();
        //结束时间转换成时间戳
        Calendar end = Calendar.getInstance();
        end.set(Integer.valueOf(dateEnds[0]), Integer.valueOf(dateEnds[1]) - 1, Integer.valueOf(dateEnds[2]));
        Long endTime = end.getTimeInMillis();
        //定义一个一天的时间戳时长
        Long oneDay = 1000 * 60 * 60 * 24L;
        Long time = startTIme;
        //循环得出
        while (time <= endTime) {
            list.add(new SimpleDateFormat("yyyyMMdd").format(new Date(time)));
            time += oneDay;
        }
        return list;
    }
    
    
    /** 
     * @Title: getDateOfWeek 
     * @Description: 获取两个时间内所有周之间的时间段，并且获得是今年第几周
     * @param start_time    开始时间 
     * @param end_time      结束时间 
     */  
    public static List<String> addMonths(Date startTime, Date endTime) {
    	List<String> list = new ArrayList<String>();
    	try {  
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startTime);
            // 获取开始年份和开始月份
            int startYear = calendar.get(Calendar.YEAR);
            int startMonth = calendar.get(Calendar.MONTH);
            // 获取结束年份和结束月份
            calendar.setTime(endTime);
            int endYear = calendar.get(Calendar.YEAR);
            int endMonth = calendar.get(Calendar.MONTH);
            //
            
            for (int i = startYear; i <= endYear; i++) {
                String date = "";
                if (startYear == endYear) {
                    for (int j = startMonth; j <= endMonth; j++) {
                        if (j < 9) {
                            date = i + "0" + (j + 1);
                        } else {
                            date = i + "" + (j + 1);
                        }
                        list.add(date);
                    }
                } else {
                    if (i == startYear) {
                        for (int j = startMonth; j < 12; j++) {
                            if (j < 9) {
                                date = i + "0" + (j + 1);
                            } else {
                                date = i + "" + (j + 1);
                            }
                            list.add(date);
                        }
                    } else if (i == endYear) {
                        for (int j = 0; j <= endMonth; j++) {
                            if (j < 9) {
                                date = i + "0" + (j + 1);
                            } else {
                                date = i + "" + (j + 1);
                            }
                            list.add(date);
                        }
                    } else {
                        for (int j = 0; j < 12; j++) {
                            if (j < 9) {
                                date = i + "0" + (j + 1);
                            } else {
                                date = i + "" + (j + 1);
                            }
                            list.add(date);
                        }
                    }
                }
            }
        } catch (Exception e) {  
            e.printStackTrace();  
        }
    	return list;
    }
    
    
    public static void main(String[] args) throws Exception {
//      List<String> list = addDates("2022-02-01", "2022-03-31");
//      list.forEach(i ->
//              System.out.println(i)
//      );
    	DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
//        String start_time = "2021-01-01";
//		String end_time = "2022-01-30";
//		List<Map<String,Object>> lsit = getDateOfWeek(dateFormat.parse(start_time), dateFormat.parse(end_time));  
//		System.out.println(JSON.toJSONString(lsit));
		
		System.out.println(dateFormat.format(getPreDayOfNowZero(1)));
		
//		List<String> monthList = addMonths(dateFormat.parse(start_time), dateFormat.parse(end_time));
//		System.out.println(JSON.toJSONString(monthList));
//       
//		
//		System.out.println(start_time.indexOf("2022-01"));
  }
}
