package com.zcxk.util;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
/*
 * 由于为了以后使用方便,所有方法的返回类型都设为了 java.utils.Date 请在使用时根据自己的需要进行日期格式化处理,如:
 * 
 * import java.text.SimpleDateFormat;SimpleDateFormat simpleDateFormat = new
 * SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String todayBegin =
 * simpleDateFormat.format
 * (DateUtils.getDayBegin());System.out.println(todayBegin );//输出结果为2017-10-26
 * 00:00:00
 */

/**
 * 日期工具类
 */
public class DatesUtil {
	public static final String DATE_TIME_FORMAT="yyyy-MM-dd HH:mm:ss";
	public static final String DATE_FORMAT = "yyyy-MM-dd";

	// 获取当天的开始时间
	public static Date getDayBegin() {
		Calendar cal = new GregorianCalendar();
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}

	// 获取当天的结束时间
	public static Date getDayEnd() {
		Calendar cal = new GregorianCalendar();
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		return cal.getTime();
	}

	// 获取昨天的开始时间
	public static Date getBeginDayOfYesterday() {
		Calendar cal = new GregorianCalendar();
		cal.setTime(getDayBegin());
		cal.add(Calendar.DAY_OF_MONTH, -1);
		return cal.getTime();
	}

	// 获取昨天的结束时间
	public static Date getEndDayOfYesterDay() {
		Calendar cal = new GregorianCalendar();
		cal.setTime(getDayEnd());
		cal.add(Calendar.DAY_OF_MONTH, -1);
		return cal.getTime();
	}

	// 获取明天的开始时间
	public static Date getBeginDayOfTomorrow() {
		Calendar cal = new GregorianCalendar();
		cal.setTime(getDayBegin());
		cal.add(Calendar.DAY_OF_MONTH, 1);
		return cal.getTime();
	}

	// 获取明天的结束时间
	public static Date getEndDayOfTomorrow() {
		Calendar cal = new GregorianCalendar();
		cal.setTime(getDayEnd());
		cal.add(Calendar.DAY_OF_MONTH, 1);
		return cal.getTime();
	}

	// 获取本周的开始时间
	@SuppressWarnings("unused")
	public static Date getBeginDayOfWeek() {
		Date date = new Date();
		if (date == null) {
			return null;
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
		if (dayofweek == 1) {
			dayofweek += 7;
		}
		cal.add(Calendar.DATE, 2 - dayofweek);
		return getDayStartTime(cal.getTime());
	}

	// 获取本周的结束时间
	public static Date getEndDayOfWeek() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getBeginDayOfWeek());
		cal.add(Calendar.DAY_OF_WEEK, 6);
		Date weekEndSta = cal.getTime();
		return getDayEndTime(weekEndSta);
	}

	// 获取上周的开始时间
	@SuppressWarnings("unused")
	public static Date getBeginDayOfLastWeek() {
		Date date = new Date();
		if (date == null) {
			return null;
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
		if (dayofweek == 1) {
			dayofweek += 7;
		}
		cal.add(Calendar.DATE, 2 - dayofweek - 7);
		return getDayStartTime(cal.getTime());
	}

	// 获取上周的结束时间
	public static Date getEndDayOfLastWeek() {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getBeginDayOfLastWeek());
		cal.add(Calendar.DAY_OF_WEEK, 6);
		Date weekEndSta = cal.getTime();
		return getDayEndTime(weekEndSta);
	}

	// 获取本月的开始时间
	public static Date getBeginDayOfMonth() {
		Calendar calendar = Calendar.getInstance();
		calendar.set(getNowYear(), getNowMonth() - 1, 1);
		return getDayStartTime(calendar.getTime());
	}

	// 获取本月的结束时间
	public static Date getEndDayOfMonth() {
		Calendar calendar = Calendar.getInstance();
		calendar.set(getNowYear(), getNowMonth() - 1, 1);
		int day = calendar.getActualMaximum(5);
		calendar.set(getNowYear(), getNowMonth() - 1, day);
		return getDayEndTime(calendar.getTime());
	}

	// 获取上月的开始时间
	public static Date getBeginDayOfLastMonth() {
		Calendar calendar = Calendar.getInstance();
		calendar.set(getNowYear(), getNowMonth() - 2, 1);
		return getDayStartTime(calendar.getTime());
	}

	// 获取上月的结束时间
	public static Date getEndDayOfLastMonth() {
		Calendar calendar = Calendar.getInstance();
		calendar.set(getNowYear(), getNowMonth() - 2, 1);
		int day = calendar.getActualMaximum(5);
		calendar.set(getNowYear(), getNowMonth() - 2, day);
		return getDayEndTime(calendar.getTime());
	}

	// 获取本年的开始时间
	public static Date getBeginDayOfYear() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, getNowYear());
		cal.set(Calendar.MONTH, Calendar.JANUARY);
		cal.set(Calendar.DATE, 1);
		return getDayStartTime(cal.getTime());
	}

	// 获取本年的结束时间
	public static Date getEndDayOfYear() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, getNowYear());
		cal.set(Calendar.MONTH, Calendar.DECEMBER);
		cal.set(Calendar.DATE, 31);
		return getDayEndTime(cal.getTime());
	}

	// 获取某个日期的开始时间
	public static Timestamp getDayStartTime(Date d) {
		Calendar calendar = Calendar.getInstance();
		if (null != d) {
			calendar.setTime(d);
		}
		calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
				calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return new Timestamp(calendar.getTimeInMillis());
	}

	// 获取某个日期的结束时间
	public static Timestamp getDayEndTime(Date d) {
		Calendar calendar = Calendar.getInstance();
		if (null != d) {
			calendar.setTime(d);
		}
		calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
				calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
		calendar.set(Calendar.MILLISECOND, 999);
		return new Timestamp(calendar.getTimeInMillis());
	}

	// 获取今年是哪一年
	public static Integer getNowYear() {
		Date date = new Date();
		GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
		gc.setTime(date);
		return Integer.valueOf(gc.get(1));
	}

	// 获取本月是哪一月
	public static int getNowMonth() {
		Date date = new Date();
		GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
		gc.setTime(date);
		return gc.get(2) + 1;
	}

	// 两个日期相减得到的天数
	public static int getDiffDays(Date beginDate, Date endDate) {
		if (beginDate == null || endDate == null) {
			throw new IllegalArgumentException("getDiffDays param is null!");
		}
		long diff = (endDate.getTime() - beginDate.getTime())
				/ (1000 * 60 * 60 * 24);
		int days = new Long(diff).intValue();
		return days;
	}

	// 两个日期相减得到的毫秒数
	public static long dateDiff(Date beginDate, Date endDate) {
		long date1ms = beginDate.getTime();
		long date2ms = endDate.getTime();
		return date2ms - date1ms;
	}

	// 获取两个日期中的最大日期
	public static Date max(Date beginDate, Date endDate) {
		if (beginDate == null) {
			return endDate;
		}
		if (endDate == null) {
			return beginDate;
		}
		if (beginDate.after(endDate)) {
			return beginDate;
		}
		return endDate;
	}

	// 获取两个日期中的最小日期
	public static Date min(Date beginDate, Date endDate) {
		if (beginDate == null) {
			return endDate;
		}
		if (endDate == null) {
			return beginDate;
		}
		if (beginDate.after(endDate)) {
			return endDate;
		}
		return beginDate;
	}

	// 返回某月该季度的第一个月
	public static Date getFirstSeasonDate(Date date) {
		final int[] SEASON = { 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4 };
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int sean = SEASON[cal.get(Calendar.MONTH)];
		cal.set(Calendar.MONTH, sean * 3 - 3);
		return cal.getTime();
	}

	// 返回某个日期下几天的日期
	public static Date getNextDay(Date date, int i) {
		Calendar cal = new GregorianCalendar();
		cal.setTime(date);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.DATE, cal.get(Calendar.DATE) + i);
		return cal.getTime();
	}

	public static Date getNextMonth(Date date ,int i){
		Calendar cal = new GregorianCalendar();
		cal.setTime(date);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.add(Calendar.MONTH, 0);
		cal.set(Calendar.DAY_OF_MONTH, 1);
		cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + i);
		return cal.getTime();
	}

	// 返回某个日期前几天的日期
	public static Date getFrontDay(Date date, int i) {
		Calendar cal = new GregorianCalendar();
		cal.setTime(date);
		cal.set(Calendar.DATE, cal.get(Calendar.DATE) - i);
		return cal.getTime();
	}

	// 获取某年某月到某年某月按天的切片日期集合(间隔天数的集合)
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static List getTimeList(int beginYear, int beginMonth, int endYear,
			int endMonth, int k) {
		List list = new ArrayList();
		if (beginYear == endYear) {
			for (int j = beginMonth; j <= endMonth; j++) {
				list.add(getTimeList(beginYear, j, k));
			}
		} else {
			{
				for (int j = beginMonth; j < 12; j++) {
					list.add(getTimeList(beginYear, j, k));
				}
				for (int i = beginYear + 1; i < endYear; i++) {
					for (int j = 0; j < 12; j++) {
						list.add(getTimeList(i, j, k));
					}
				}
				for (int j = 0; j <= endMonth; j++) {
					list.add(getTimeList(endYear, j, k));
				}
			}
		}
		return list;
	}

	// 获取某年某月按天切片日期集合(某个月间隔多少天的日期集合)
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static List getTimeList(int beginYear, int beginMonth, int k) {
		List list = new ArrayList();
		Calendar begincal = new GregorianCalendar(beginYear, beginMonth, 1);
		int max = begincal.getActualMaximum(Calendar.DATE);
		for (int i = 1; i < max; i = i + k) {
			list.add(begincal.getTime());
			begincal.add(Calendar.DATE, k);
		}
		begincal = new GregorianCalendar(beginYear, beginMonth, max);
		list.add(begincal.getTime());
		return list;
	}

	public static String formatNow(String format) {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		String formatStr = sdf.format(new Date());
		return formatStr;
	}
	public static String formatNow() {
		SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_FORMAT);
		String formatStr = sdf.format(new Date());
		return formatStr;
	}
	public static String formatDate(Date date ,String format) {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		String formatStr = sdf.format(date);
		return formatStr;
	}
	// 当前日期的后几天
	public static Date afterNow(int day) {
		Calendar cal=Calendar.getInstance();
    	cal.add(Calendar.DATE,Math.abs(day));
    	Date time=cal.getTime();
		return time;
	}
	// 当前日期的前几天
	public static Date beforeNow(int day) {
		Calendar cal=Calendar.getInstance();
    	cal.add(Calendar.DATE,-Math.abs(day));
    	Date time=cal.getTime();
		return time;
	}
	public static Date before(Date date ,int n) {
		Calendar cal=Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DATE,-n);
		return cal.getTime();
	}
	public static Date after(Date date,int n) {
		Calendar cal=Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DATE,n);
		return cal.getTime();
	}
	public static List<String>  beforeNowDateArray(int day){
		List<String> dates = new ArrayList<String>();
		Calendar cal=Calendar.getInstance();
		for(int i =1 ;i<=Math.abs(day);i++) {
			cal.add(Calendar.DATE,-1);
			dates.add(formatDate(cal.getTime(),"yyyyMMdd"));
		}
		return dates;
	}
	public static Set<String> betweenDate(Date startDate ,Date endDate){
		Set<String> dates = new HashSet<String>();
		Calendar cal=Calendar.getInstance();
		cal.setTime(endDate);
		while(endDate.after(startDate)) {
			dates.add(formatDate(cal.getTime(),"yyyyMMdd"));
			cal.add(Calendar.DATE,-1);
			cal.setTime(cal.getTime());
			endDate = cal.getTime();
		}
		dates.add(formatDate(startDate,"yyyyMMdd"));
		return dates;
	}

	public static Set<String> betweenMonth(Date startDate ,Date endDate){
		Set<String> dates = new HashSet<>();
		Calendar cal=Calendar.getInstance();
		cal.setTime(endDate);
		while(endDate.after(startDate)) {
			dates.add(formatDate(cal.getTime(),"yyyyMM"));
			cal.add(Calendar.MONTH,-1);
			cal.setTime(cal.getTime());
			endDate = cal.getTime();
		}
		dates.add(formatDate(startDate,"yyyyMM"));
		return dates;
	}
	public static Date parseDate(String dateStr,String format) {
		Date date = null ;
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		try {
			date = sdf.parse(dateStr);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return date;
	}
	/**
	 * 判断某一时间是否在一个区间内
	 *
	 * @param sourceTime
	 *            时间区间,半闭合,如[10:00-20:00]
	 * @param curTime
	 *            需要判断的时间 如10:00
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static boolean isInTime(String sourceTime, String curTime) {
	    if (sourceTime == null || !sourceTime.contains("-") || !sourceTime.contains(":")) {
	        throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);
	    }
	    if (curTime == null || !curTime.contains(":")) {
	        throw new IllegalArgumentException("Illegal Argument arg:" + curTime);
	    }
	    String[] args = sourceTime.split("-");
	    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
	    try {
	        long now = sdf.parse(curTime).getTime();
	        long start = sdf.parse(args[0]).getTime();
	        long end = sdf.parse(args[1]).getTime();
	        if (args[1].equals("00:00")) {
	            args[1] = "24:00";
	        }
	        if (end < start) {
	            if (now > end && now < start) {
	                return false;
	            } else {
	                return true;
	            }
	        }
	        else {
	            if (now >= start && now <= end) {
	                return true;
	            } else {
	                return false;
	            }
	        }
	    } catch (ParseException e) {
	        e.printStackTrace();
	        throw new IllegalArgumentException("Illegal Argument arg:" + sourceTime);
	    }
	}
	public static Date before(Date d ,long milSeconds) {
		return new Date(d.getTime()-milSeconds);
	}
	public static Date yesterdayLastDate() {
	    Calendar calendar = Calendar.getInstance();
	    calendar.setTime(new Date());
	    calendar.add(Calendar.DATE, -1);
	    calendar.set(Calendar.HOUR_OF_DAY, 23);
	    calendar.set(Calendar.MINUTE, 59);
	    calendar.set(Calendar.SECOND, 59);
	    calendar.set(Calendar.MILLISECOND, 999);
	    return calendar.getTime();
	}

	public static Date dateToISODate(Date date) {
		//T代表后面跟着时间，Z代表UTC统一时间
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
		format.setCalendar(new GregorianCalendar(new SimpleTimeZone(0, "GMT")));
		String isoDate = format.format(date);
		try {
			return format.parse(isoDate);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static Date beforeMonth(int month){
		Date date = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date); // 设置为当前时间
		calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1); // 设置为上一个月
		date = calendar.getTime();
		return date ;
	}

	public static Date beforeYear(int year){
		Date date = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date); // 设置为当前时间
		calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) - 1); // 设置为上一年
		date = calendar.getTime();
		return date ;
	}
	// Wed Jan 02 03:09:49 CST 2019 -> 2019-02-02 03:09:49
	public static String  format(String timeString){
		try {
			SimpleDateFormat sfStart = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH) ;
			SimpleDateFormat sfEnd = new SimpleDateFormat(DATE_TIME_FORMAT);
			String format = sfEnd.format(sfStart.parse(timeString));
			return format ;
		}catch (Exception e){
			e.printStackTrace();
		}
		return null ;
	}


	/**
	* @Author lihui
	* @Description 获取月份具体天数
	* @Date  2021/4/15
	* @Param [timeString]
	* @return int
	**/
	public static int getMouthDays(String timeString) {
		SimpleDateFormat simpleDate = new SimpleDateFormat("yyyy-MM");
		Calendar rightNow = Calendar.getInstance();
		try{
			rightNow.setTime(simpleDate.parse(timeString));
		}catch(ParseException e){
			e.printStackTrace();
		}

		int days = rightNow.getActualMaximum(Calendar.DAY_OF_MONTH);//根据年月 获取月份天数
		return days;
	}

	public static boolean isInTime(String startTime, String endTime, String inTime, String pattern) {
		SimpleDateFormat simpleDate = new SimpleDateFormat(pattern);
		try {
			//  10:00  11:00 = > 10:15
			Date startDate = simpleDate.parse(startTime);
			Date endDate   = simpleDate.parse(endTime);
			Date inDate    = simpleDate.parse(inTime);
			return startDate.before(inDate) && endDate.after(inDate);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean isInTime(String startTime, String endTime, Date inTime, String pattern) {
		SimpleDateFormat simpleDate = new SimpleDateFormat(pattern);
		try {
			//  10:00  11:00 = > 10:15
			Date startDate = simpleDate.parse(startTime);
			Date endDate   = simpleDate.parse(endTime);
			Date inDate    = simpleDate.parse(simpleDate.format(inTime));
			return startDate.before(inDate) && endDate.after(inDate);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return false;
	}

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

	public static Date addMinuteOfDate(Date date,int i){
		if (date == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.MINUTE, i);
		Date newDate = c.getTime();
		return newDate;
	}

	public static LocalDate parseLocalDate(Date date){
		Instant instant =  date.toInstant();
		ZoneId zoneId = ZoneId.systemDefault();
		return  instant.atZone(zoneId).toLocalDate();
	}

	public static LocalDate formatLocalDate(String date){
		DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		return LocalDate.parse(date, fmt);
	}

	public static long minutesBetween(Date startTime, Date endTime){
		return ChronoUnit.MINUTES.between(Instant.ofEpochMilli(startTime.getTime()), Instant.ofEpochMilli(endTime.getTime()));
	}


	public static void main(String[] args) {
		//String d = "2019-11-14 13:10:16";
		//System.out.println(DatesUtil.parseDate(d, DatesUtil.DATE_TIME_FORMAT));
//		System.out.println(DatesUtil.formatDate(getNextDay(DatesUtil.beforeNow(7),1), DatesUtil.DATE_TIME_FORMAT));
//		System.out.println(DatesUtil.formatDate(getNextDay(DatesUtil.beforeMonth(1),1), DatesUtil.DATE_TIME_FORMAT));
//		Set<String> iter = DatesUtil.betweenDate(DatesUtil.beforeMonth(1), new Date());
//		System.out.println(DatesUtil.formatDate(getNextMonth(DatesUtil.beforeYear(1),1), DatesUtil.DATE_TIME_FORMAT));
//		Set<String> iter1 = DatesUtil.betweenMonth(DatesUtil.beforeYear(1),new Date());
//		System.out.println(JSON.toJSONString(iter));
//		System.out.println(JSON.toJSONString(iter1));
		System.out.println(DatesUtil.formatDate(DatesUtil.addDayOfDate(new Date(), -(3-1)),"yyyy-MM-dd") + " 00:00:00");
	}
}