package com;

import com.alibaba.fastjson.JSON;

import org.apache.commons.lang.StringUtils;

import org.joda.time.DateTime;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import java.text.DateFormat;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.*;


public class StatisticsDateUtils {

	private static Logger Log = LoggerFactory

			.getLogger(StatisticsDateUtils.class);

	/**
	 * 
	 * 获得本周一与当前日期相差的天数
	 *
	 * 
	 * 
	 * @return
	 * 
	 */

	public static int getMondayPlus() {

		Calendar cd = Calendar.getInstance();

		int dayOfWeek = cd.get(Calendar.DAY_OF_WEEK);

		if (dayOfWeek == 1) {

			return -6;

		} else {

			return Calendar.MONDAY - dayOfWeek;

		}

	}

	/**
	 * 
	 * 获得当前周-周一的日期
	 * 
	 * 
	 * 
	 * @return
	 * 
	 */

	public static String getCurrentMonday() {

		int mondayPlus = getMondayPlus();

		Calendar currentDate = Calendar.getInstance();

		currentDate.add(Calendar.DATE, mondayPlus);

		Date monday = currentDate.getTime();

		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

		String preMonday = format.format(monday);

		return preMonday;

	}

	/**
	 * 
	 * 获得当前周- 周日的日期
	 * 
	 * 
	 * 
	 * @return
	 * 
	 */

	public static String getPreviousSunday() {

		int mondayPlus = getMondayPlus();

		Calendar currentDate = Calendar.getInstance();

		currentDate.add(Calendar.DATE, mondayPlus + 6);

		Date monday = currentDate.getTime();

		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

		String preMonday = format.format(monday);

		return preMonday;

	}

	/**
	 * 
	 * 获得当前月--开始日期
	 *
	 * 
	 * 
	 * @param date
	 * 
	 * @return
	 * 
	 */

	public static String getMinMonthDate(String date) {

		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

		Calendar calendar = Calendar.getInstance();

		try {

			calendar.setTime(dateFormat.parse(date));

			calendar.set(Calendar.DAY_OF_MONTH,

					calendar.getActualMinimum(Calendar.DAY_OF_MONTH));

			return dateFormat.format(calendar.getTime());

		} catch (Exception e) {

			Log.info("getMinMonthDate", e);

		}

		return null;

	}

	/**
	 * 
	 * 获得当前月--结束日期
	 *
	 * 
	 * 
	 * @param date
	 * 
	 * @return
	 * 
	 */

	public static String getMaxMonthDate(String date) {

		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

		Calendar calendar = Calendar.getInstance();

		try {

			calendar.setTime(dateFormat.parse(date));

			calendar.set(Calendar.DAY_OF_MONTH,

					calendar.getActualMaximum(Calendar.DAY_OF_MONTH));

			return dateFormat.format(calendar.getTime());

		} catch (Exception e) {

			Log.info("getMinMonthDate", e);

		}

		return null;

	}

	/**
	 * 
	 * 获取两个时间内的月数
	 * 
	 * 
	 * 
	 * @param startDate
	 * 
	 * @param endDate
	 * 
	 * @return
	 * 
	 * @throws ParseException
	 * 
	 */

	public static List<String> getMonthBetween(String startDate, String endDate)

			throws ParseException {

		ArrayList<String> result = new ArrayList<String>();

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 格式化为年月

		Calendar min = Calendar.getInstance();

		Calendar max = Calendar.getInstance();

		min.setTime(sdf.parse(startDate));

		min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

		max.setTime(sdf.parse(endDate));

		max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

		Calendar curr = min;

		while (curr.before(max)) {

			result.add(sdf.format(curr.getTime()));

			curr.add(Calendar.MONTH, 1);

		}

		return result;

	}

	/**
	 * 
	 * 获取某日的周天日期
	 * 
	 * 
	 * 
	 * @param date
	 * 
	 * @return
	 * 
	 * @throws Exception
	 * 
	 */

	public static Date getLastDayOfWeeks(Date date) throws Exception {

		// SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		// //设置时间格式

		// Calendar cal = Calendar.getInstance();

		// cal.setTime(date);

		// cal.setFirstDayOfWeek(Calendar.MONDAY);

		// int day = cal.get(Calendar.DAY_OF_WEEK);//获得当前日期是一个星期的第几天

		// cal.add(Calendar.DATE, cal.getFirstDayOfWeek() -

		// day);//根据日历的规则,给当前日期减去星期几与一个星期第一天的差值

		// Log.info("所在周星期一的日期:" + sdf.format(cal.getTime()));

		// cal.add(Calendar.DATE, 6);

		// Log.info("所在周星期日的日期:" + sdf.format(cal.getTime()));

		// return cal.getTime();

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 设置时间格式

		Calendar cal = Calendar.getInstance();

		cal.setTime(date);

		Log.info("要计算日期为:" + sdf.format(cal.getTime())); // 输出要计算日期

		// 判断要计算的日期是否是周日,如果是则减一天计算周六的,否则会出问题,计算到下一周去了

		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);// 根据日历的规则,给当前日期减去星期几与一个星期第一天的差值

		Log.info("所在周星期一的日期:" + sdf.format(cal.getTime()));

		Log.info(cal.getFirstDayOfWeek() + "-" + day + "+6="

				+ (cal.getFirstDayOfWeek() - day + 6));

		cal.add(Calendar.DATE, 6);

		Log.info("所在周星期日的日期:" + sdf.format(cal.getTime()));

		return cal.getTime();

	}

	/**
	 * 
	 * 获取两个时间内的年
	 * 
	 * 
	 * 
	 * @param startDate
	 * 
	 * @param endDate
	 * 
	 * @return
	 * 
	 * @throws ParseException
	 * 
	 */

	public static List<String> getYearBetween(String startDate, String endDate)

			throws ParseException {

		ArrayList<String> result = new ArrayList<String>();

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 格式化为年月

		Calendar min = Calendar.getInstance();

		Calendar max = Calendar.getInstance();

		min.setTime(sdf.parse(startDate));

		min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

		max.setTime(sdf.parse(endDate));

		max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

		Calendar curr = min;

		while (curr.before(max)) {

			result.add(sdf.format(curr.getTime()));

			curr.add(Calendar.YEAR, 1);

		}

		return result;

	}

	/**
	 * 
	 * 获取两个时间内的日期
	 * 
	 * 
	 * 
	 * @param start
	 * 
	 * @param end
	 * 
	 * @param containsWeekEnd
	 *            是否包含周末
	 * 
	 * @return
	 * 
	 */

	public static List<String> getBetweenDates(String start, String end, boolean containsWeekEnd) {

		List<String> result = new LinkedList<String>();

		try {

			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

			SimpleDateFormat ymd = new SimpleDateFormat("yyyy-MM-dd");

			Date startDate = sdf.parse(start);

			Date endDate = sdf.parse(end);

			Calendar tempStart = Calendar.getInstance();

			tempStart.setTime(startDate);

			Calendar tempEnd = Calendar.getInstance();

			tempEnd.setTime(endDate);

			while (tempStart.before(tempEnd) || tempStart.equals(tempEnd)) {

				int week = tempStart.get(Calendar.DAY_OF_WEEK) - 1;

				if (!containsWeekEnd) {

					if (week == 0 || week == 6) {

						// 空

					} else {

						result.add(ymd.format(tempStart.getTime()));

					}

				} else {

					result.add(ymd.format(tempStart.getTime()));

				}

				tempStart.add(Calendar.DAY_OF_YEAR, 1);

			}

		} catch (Exception e) {

			Log.error("getBetweenDates", e);

		}

		return result;

	}

	/**
	 * 
	 * 获取两个时间内的日期周末时间
	 * 
	 * 
	 * 
	 * @param start
	 * 
	 * @param end
	 * 
	 * @param containsWeekEnd
	 *            是否包含周末
	 * 
	 * @return
	 * 
	 */

	public static Set<String> getBetweenWeekend(String start, String end) {

		Set<String> result = new HashSet<String>();

		try {

			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

			SimpleDateFormat ymd = new SimpleDateFormat("yyyy-MM-dd");

			Date startDate = sdf.parse(start);

			Date endDate = sdf.parse(end);

			Calendar tempStart = Calendar.getInstance();

			tempStart.setTime(startDate);

			Calendar tempEnd = Calendar.getInstance();

			tempEnd.setTime(endDate);

			while (tempStart.before(tempEnd) || tempStart.equals(tempEnd)) {

				int week = tempStart.get(Calendar.DAY_OF_WEEK) - 1;

				if (week == 0 || week == 6) {

					result.add(ymd.format(tempStart.getTime()));

				}

				tempStart.add(Calendar.DAY_OF_YEAR, 1);

			}

		} catch (Exception e) {

			Log.error("getBetweenDates", e);

		}

		return result;

	}

	/**
	 * 
	 * 获取当月在一年的第几周
	 * 
	 * 
	 * 
	 * @param sdate
	 * 
	 * @return
	 * 
	 */

	public static String getYearOfWeek(String sdate) {

		if (StringUtils.isEmpty(sdate)) {

			return "";

		}

		try {

			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

			Date d = format.parse(sdate);

			Calendar cal = Calendar.getInstance();

			cal.setTime(d);

			cal.setFirstDayOfWeek(Calendar.MONDAY);

			// 意思是第一周的最小天数为4。也可以设置别的最小天数,这样一年的开始的第一周就能确定下来,以后的周数的都能准确的推算出来。

			cal.setMinimalDaysInFirstWeek(4);

			int weekNum = cal.get(Calendar.WEEK_OF_YEAR);

			// 从1计算

			Date sundayDate = StatisticsDateUtils.getLastDayOfWeeks(d);

			Calendar sunDayCal = Calendar.getInstance();

			sunDayCal.setTime(sundayDate);

			// 意思是第一周的最小天数为4。也可以设置别的最小天数,这样一年的开始的第一周就能确定下来,以后的周数的都能准确的推算出来。

			sunDayCal.setMinimalDaysInFirstWeek(4);

			int yearNum = sunDayCal.get(Calendar.YEAR);

			if (weekNum == 53) {

				yearNum = yearNum - 1; // 减去一年

			}

			return yearNum + "年第" + weekNum + "周";

		} catch (Exception e) {

			Log.error("getYearOfWeek", e);

		}

		return "";

	}

	/**
	 * 
	 * 获取年月<BR>
	 * 
	 * 方法名:getYearAndMonth <BR>
	 * 
	 * 时 间:2020-12-10 21:07 <BR>
	 *
	 * 
	 * 
	 * @param sdate:
	 * 
	 * @return java.lang.String <BR>
	 * 
	 * @since 1.0.0
	 * 
	 */

	public static String getYearAndMonth(String sdate) {

		return getFormatterDate(sdate, "yyyy年MM月");

	}

	/**
	 * 
	 * 获取年 <BR>
	 * 
	 * 方法名:getYear <BR>
	 * 
	 * 
	 * 
	 * @param sdate:
	 * 
	 * @return java.lang.String <BR>
	 * 
	 * @since 1.0.0
	 * 
	 */

	public static String getYear(String sdate) {

		return getFormatterDate(sdate, "yyyy");

	}

	/**
	 * 
	 * <BR>
	 * 
	 * 方法名:getYearAndMonth1 <BR>
	 * 
	 *
	 * 
	 * 
	 * @param sdate:
	 * 
	 * @return java.lang.String <BR>
	 * 
	 * @since 1.0.0
	 * 
	 */

	public static String getYearAndMonth1(String sdate) {

		return getFormatterDate(sdate, "yyyy-MM");

	}

	/**
	 * 
	 * 根据pattern格式时间 <BR>
	 * 
	 * 方法名:getFormatterDate <BR>
	 * 
	 * @param sdate:
	 * 
	 * @param pattern:
	 * 
	 * @return java.lang.String <BR>
	 * 
	 * @since 1.0.0
	 * 
	 */

	public static String getFormatterDate(String sdate, String pattern) {

		if (StringUtils.isEmpty(sdate)) {

			return "";

		}

		try {

			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

			Date d = format.parse(sdate);

			return new DateTime(d).toString(pattern);

		} catch (Exception e) {

			Log.error("getFormatterDate", e);

		}

		return "";

	}

	/**
	 * 
	 * 补全周数
	 * 
	 * 
	 * 
	 * @param startDate
	 * 
	 * @param endDate
	 * 
	 * @return
	 * 
	 */

	public static List<String> getBetweenWeeks(String startDate, String endDate) {

		List<String> result = new ArrayList<>();

		try {

			// 获取俩个日期之间的日期

			List<String> list = new ArrayList<String>();

			DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

			Calendar calBegin = Calendar.getInstance();

			calBegin.setTime(format.parse(startDate));

			Calendar calEnd = Calendar.getInstance();

			calEnd.setTime(format.parse(endDate));

			do {

				String dateTmep = format.format(calBegin.getTime());

				list.add(dateTmep);

				calBegin.add(Calendar.DAY_OF_MONTH, 1);

			} while (format.parse(endDate).after(calBegin.getTime()));

			// 遍历

			for (String date : list) {

				Calendar cal = Calendar.getInstance();

				cal.setTime(format.parse(date));

				cal.setFirstDayOfWeek(Calendar.MONDAY);

				// 意思是第一周的最小天数为4。也可以设置别的最小天数,这样一年的开始的第一周就能确定下来,以后的周数的都能准确的推算出来。

				cal.setMinimalDaysInFirstWeek(4);

				int weekNum = cal.get(Calendar.WEEK_OF_YEAR);

				Date sundayDate = StatisticsDateUtils.getLastDayOfWeeks(cal.getTime());

				Calendar sunDayCal = Calendar.getInstance();

				sunDayCal.setTime(sundayDate);

				// 意思是第一周的最小天数为4。也可以设置别的最小天数,这样一年的开始的第一周就能确定下来,以后的周数的都能准确的推算出来。

				sunDayCal.setMinimalDaysInFirstWeek(4);

				int yearNum = sunDayCal.get(Calendar.YEAR);

				String element = yearNum + "年第" + weekNum + "周";

				if (!result.contains(element)) {

					result.add(element);

				}

			}

		} catch (Exception e) {

			Log.error("getBetweenWeeks", e);

		}

		Log.info("getBetweenWeeks = " + JSON.toJSONString(result));

		return result;

	}

	public static void main(String args[]) {

		// System.out.println(getCurrentMonday());

		// System.out.println(getPreviousSunday());

		// System.out.println(getMinMonthDate("2020-03-16"));

		// System.out.println(getMaxMonthDate("2020-03-16"));

		// System.out.println(getBetweenDates("2020-12-01 00:00:00", "2020-12-30
		// 23:00:00", false));

		// String a = "2020-12-01 00:00:00";

		// String[] monthArr = a.split("-");

		// String sdate = monthArr[0] + "-"+ monthArr[1];

		// System.out.println(sdate);

	}

}