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);
	}
}                










