package com.seeyon.apps.src_ydctdatasync.utils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class TimeUtils {
	public static final String DEFAULT_PATTERN = "yyyy-MM-dd";

	public static String format(Date date) {
		return format(date, DEFAULT_PATTERN);
	}

	public static String format(Date date, String pattern) {
		if (date == null) {
			return "";
		}
		DateFormat dateFormat = new SimpleDateFormat(pattern);
		return dateFormat.format(date);
	}

	/**
	 * UTC时间转换为本地时间；待解析的字符串必须以yyyy-MM-dd格式开头
	 */
	public static Date utcParse(String utcTimeStr) throws ParseException {
		String utcTimePattern = "yyyy-MM-dd";
		String subTime = utcTimeStr.substring(10);// UTC时间格式以 yyyy-MM-dd 开头,将utc时间的前10位截取掉,之后是含有多时区时间格式信息的数据
		// 处理当后缀为:+8:00时,转换为:+08:00 或 -8:00转换为-08:00
		if (subTime.indexOf("+") != -1) {
			subTime = changeUtcSuffix(subTime, "+");
		}
		if (subTime.indexOf("-") != -1) {
			subTime = changeUtcSuffix(subTime, "-");
		}
		utcTimeStr = utcTimeStr.substring(0, 10) + subTime;
		// 依据传入函数的utc时间,得到对应的utc时间格式
		// 步骤一:处理 T
		if (utcTimeStr.indexOf("T") != -1) {
			utcTimePattern = utcTimePattern + "'T'";
		}
		// 兼容yyyy-MM-dd的格式，这种格式不需要加空格
		if(utcTimeStr.indexOf("T") == -1 && subTime.length() > 0) {
			utcTimePattern = utcTimePattern + " ";
		}
		// 步骤二:处理毫秒SSS
		if (utcTimeStr.indexOf(".") != -1) {
			utcTimePattern = utcTimePattern + "HH:mm:ss.SSS";
		} else if (utcTimeStr.indexOf(":") != -1) {
			utcTimePattern = utcTimePattern + "HH:mm:ss";
		}
		// 步骤三:处理时区问题
		if (subTime.indexOf("+") != -1 || subTime.indexOf("-") != -1) {
			utcTimePattern = utcTimePattern + "XXX";
		} else if (subTime.indexOf("Z") != -1) {
			utcTimePattern = utcTimePattern + "'Z'";
		}
		DateFormat dateFormat = new SimpleDateFormat(utcTimePattern);
		if (subTime.indexOf("Z") != -1) {
			dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
		}
		return dateFormat.parse(utcTimeStr);
	}

	private static String changeUtcSuffix(String subTime, String sign) {
		String timeSuffix = null;
		String[] splitTimeArrayOne = subTime.split("\\\\" + sign);
		String[] splitTimeArrayTwo = splitTimeArrayOne[1].split(":");
		if (splitTimeArrayTwo[0].length() < 2) {
			timeSuffix = "+" + "0" + splitTimeArrayTwo[0] + ":" + splitTimeArrayTwo[1];
			subTime = splitTimeArrayOne[0] + timeSuffix;
			return subTime;
		}
		return subTime;
	}

	/**
	 * 所在周的开始
	 * @param date
	 * @return
	 */
	public static Date startOfWeek(Date date) {
		if (date == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.setFirstDayOfWeek(Calendar.MONDAY);
		c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		return c.getTime();
	}

	/**
	 * 所在周的结束
	 * @param date
	 * @return
	 */
	public static Date endOfWeek(Date date) {
		if (date == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.setFirstDayOfWeek(Calendar.MONDAY);
		c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
		c.set(Calendar.HOUR_OF_DAY, 23);
		c.set(Calendar.MINUTE, 59);
		c.set(Calendar.SECOND, 59);
		return c.getTime();
	}

	/**
	 * 所在月的开始
	 * @param date
	 * @return
	 */
	public static Date startOfMonth(Date date) {
		if (date == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.DAY_OF_MONTH, 1);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, c.getMinimum(Calendar.MILLISECOND));
		return c.getTime();
	}

	public static Date convertLocalDateTime2Date(Object date) {
		if(date instanceof Date) {
			return (Date)date;
		}else if(date instanceof LocalDateTime) {
			LocalDateTime time = (LocalDateTime) date;
			// 将LocalDateTime转换为Instant
			ZoneId zoneId = ZoneId.systemDefault(); // 获取系统默认时区
			return Date.from(time.atZone(zoneId).toInstant());
		}
		return null;
	}

	/**
	 * 所在月的结束
	 * @param date
	 * @return
	 */
	public static Date endOfMonth(Date date) {
		if (date == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
		c.set(Calendar.HOUR_OF_DAY, 23);
		c.set(Calendar.MINUTE, 59);
		c.set(Calendar.SECOND, 59);
		return c.getTime();
	}

	/**
	 * 本月开始
	 * @return
	 */
	public static Date startOfCurMonth() {
		return startOfMonth(new Date());
	}

	/**
	 * 本月结束
	 * @return
	 */
	public static Date endOfCurMonth() {
		return endOfMonth(new Date());
	}

	/**
	 * 上月开始
	 * @return
	 */
	public static Date startOfPreMonth() {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(startOfCurMonth());
		calendar.add(Calendar.MONTH, -1);
		return calendar.getTime();
	}

	/**
	 * 上月结束
	 * @return
	 */
	public static Date endOfPreMonth() {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MONTH, -1);
		calendar.setTime(endOfMonth(calendar.getTime()));
		return calendar.getTime();
	}

	/**
	 * 本周开始
	 * @return
	 */
	public static Date startOfCurWeek() {
		return startOfWeek(new Date());
	}

	/**
	 * 本周结束
	 * @return
	 */
	public static Date endOfCurWeek() {
		return endOfWeek(new Date());
	}

	/**
	 * 上周开始
	 * @return
	 */
	public static Date startOfPreWeek() {
		Date curMon = startOfCurWeek();
		Calendar c = Calendar.getInstance();
		c.setTime(curMon);
		c.add(Calendar.DAY_OF_WEEK, -7);
		return c.getTime();
	}

	/**
	 * 上周结束
	 * @return
	 */
	public static Date endOfPreWeek() {
		Date curSun = endOfCurWeek();
		Calendar c = Calendar.getInstance();
		c.setTime(curSun);
		c.add(Calendar.DAY_OF_WEEK, -7);
		return c.getTime();
	}

	/**
	 * 一天的结束
	 * @param date
	 * @return
	 */
	public static Date endOf(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		return calendar.getTime();
	}

	/**
	 * 一天的开始
	 * @param date
	 * @return
	 */
	public static Date startOf(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND,0);
		return calendar.getTime();
	}

	/**
	 * 昨天的开始
	 * @return
	 */
	public static Date startOfYesterday() {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		return startOf(calendar.getTime());
	}

	/**
	 * 昨天的结束
	 * @return
	 */
	public static Date endOfYesterday() {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		return endOf(calendar.getTime());
	}

	/**
	 * 获取几天之后的日期
	 *
	 * @param date
	 * @param after
	 * @return
	 */
	public static Date after(Date date, int after) {
		if (date == null) {
			return null;
		}
		if (after <= 0) {
			return date;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE, after);
		return calendar.getTime();
	}

	/**
	 * 获取几年后的日期
	 * @param date
	 * @param year
	 * @return
	 */
	public static Date afterYear(Date date, int year) {
		if(date == null) {
			return null;
		}
		if(year <= 0) {
			return date;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.YEAR, year);
		return calendar.getTime();
	}


	/**
	 * 获取几天之前的日期
	 *
	 * @param date
	 * @param before
	 * @return
	 */
	public static Date before(Date date, int before) {
		if (date == null) {
			return null;
		}
		if (before <= 0) {
			return date;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE, -1 * before);
		return calendar.getTime();
	}

	public static Date monthsAgo(Date date, int months) {
		Calendar ca = Calendar.getInstance();
		ca.setTime(date);
		ca.add(Calendar.MONTH, -months);
		return ca.getTime();
	}

	/**
	 * 获取几分钟之前的时间
	 * @return
	 */
	public static Date minsAgo(Date date, int mins){
		Calendar ca = Calendar.getInstance();
		ca.setTime(date);
		ca.add(Calendar.MINUTE,-mins);
		return ca.getTime();
	}

	public static Date startOfHour(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		return calendar.getTime();
	}

	public static Date endOfHour(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		return calendar.getTime();
	}

	/**
	 * 获取两个时间相差的月数
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static int getMonthSpace(Date date1,Date date2)
	{
		int iMonth = 0;
		int flag = 0;
		try{
			Calendar objCalendarDate1 = Calendar.getInstance();
			objCalendarDate1.setTime(date1);

			Calendar objCalendarDate2 = Calendar.getInstance();
			objCalendarDate2.setTime(date2);

			if (objCalendarDate2.equals(objCalendarDate1)) {
				return 0;
			}
			if (objCalendarDate1.after(objCalendarDate2)){
				Calendar temp = objCalendarDate1;
				objCalendarDate1 = objCalendarDate2;
				objCalendarDate2 = temp;
			}
			if (objCalendarDate2.get(Calendar.DAY_OF_MONTH) < objCalendarDate1.get(Calendar.DAY_OF_MONTH)) {
				flag = 1;
			}

			if (objCalendarDate2.get(Calendar.YEAR) > objCalendarDate1.get(Calendar.YEAR)) {
				iMonth = ((objCalendarDate2.get(Calendar.YEAR) - objCalendarDate1.get(Calendar.YEAR))
						* 12 + objCalendarDate2.get(Calendar.MONTH) - flag)
						- objCalendarDate1.get(Calendar.MONTH);
			} else {
				iMonth = objCalendarDate2.get(Calendar.MONTH)
						- objCalendarDate1.get(Calendar.MONTH) - flag;
			}

		} catch (Exception e){
			e.printStackTrace();
		}
		return iMonth;
	}

	/**
	 * 得到日期num个月时的日期
	 * num为正数  为date后num个月
	 * num为负数  为date前num个月
	 * @param date
	 * @param num
	 * @return
	 */
	public static Date getDateOfMonth(Date date,int num){
		if(date == null){
			return null;
		}
		Calendar calendar = Calendar.getInstance(); //得到日历
		calendar.setTime(date);                     //把当前时间赋给日历
		calendar.add(Calendar.MONTH, num);          //设置为前num月
		return calendar.getTime();
	}

	/**
	 * 获得两个时间相差的天数
	 * @param minDate
	 * @param maxDate
	 * @return
	 */
	public static int getDaySpace(Date minDate,Date maxDate){
		int days = (int) ((maxDate.getTime() - minDate.getTime()) / (1000*3600*24));
		return Math.abs(days);
	}

	/**
	 * 判断两个时间是否是同一天
	 *
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static boolean sameDay(Date d1, Date d2) {
		if (d1 == null || d2 == null) {
			return false;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(d1);
		int yearOfDate1 = calendar.get(Calendar.YEAR);
		int dayOfDate1 = calendar.get(Calendar.DAY_OF_YEAR);
		calendar.setTime(d2);
		int yearOfDate2 = calendar.get(Calendar.YEAR);
		int dayOfDate2 = calendar.get(Calendar.DAY_OF_YEAR);

		return yearOfDate1 == yearOfDate2 && dayOfDate1 == dayOfDate2; // 年份和一年当中的天数相同
	}

	public static Date preYear(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.YEAR, -1);
		return calendar.getTime();
	}

	public static Date endOfPreYear(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.YEAR, -1);
		calendar.set(Calendar.MONTH, calendar.getActualMaximum(Calendar.MONTH));
		return endOfMonth(calendar.getTime());
	}


	public static Date endOfYear(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.MONTH, calendar.getActualMaximum(Calendar.MONTH));
		return endOfMonth(calendar.getTime());
	}

	public static Date startOfYear(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.MONTH, calendar.getMinimum(Calendar.MONTH));
		return startOfMonth(calendar.getTime());
	}

	public static Date nextMonth(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.MONTH, +1);
		return calendar.getTime();
	}
}
