package org.fouram.core.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import org.apache.commons.lang.time.DurationFormatUtils;

public class DateUtil {

	public static final String yyyyMMdd = "yyyyMMdd";
	public static final String yyyyMMdd2 = "yyyy年MM月dd日";

	public static final SimpleDateFormat sdfYear = new SimpleDateFormat("yyyy");

	public static final SimpleDateFormat sdfMonth = new SimpleDateFormat("M");

	public static final SimpleDateFormat sdfYear_Month = new SimpleDateFormat("yyyy-M");

	public static final SimpleDateFormat sdfYear_MMonth = new SimpleDateFormat("yyyy-MM");

	public static final SimpleDateFormat sdfDate = new SimpleDateFormat("dd");

	public static final SimpleDateFormat sdfHour = new SimpleDateFormat("HH");

	public static final SimpleDateFormat sdfDay = new SimpleDateFormat("yyyy-MM-dd");

	public static final SimpleDateFormat sdfDay2 = new SimpleDateFormat("yyyy/MM/dd");

	public static final SimpleDateFormat sdfDays = new SimpleDateFormat("yyyyMMdd");

	public static final SimpleDateFormat sdfsTime = new SimpleDateFormat("yyyy-MM-dd HH:mm");

	public static final SimpleDateFormat sdfTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	public static final SimpleDateFormat timeStamp = new SimpleDateFormat("yyyyMMddHHmmss");

	private static final long ONE_MINUTE = 60000L;
	private static final long ONE_HOUR = 3600000L;
	private static final long ONE_DAY = 86400000L;
	private static final long ONE_WEEK = 604800000L;

	private static final String ONE_SECOND_AGO = "秒前";
	private static final String ONE_MINUTE_AGO = "分钟前";
	private static final String ONE_HOUR_AGO = "小时前";
	private static final String ONE_DAY_AGO = "天前";
	private static final String ONE_MONTH_AGO = "月前";
	private static final String ONE_YEAR_AGO = "年前";

	public static String getYear() {
		return sdfYear.format(new Date());
	}

	public static String getYear_Month() {
		return sdfYear_Month.format(new Date());
	}

	public static String getDate() {
		return sdfDate.format(new Date());
	}

	public static String getMonth() {
		return sdfMonth.format(new Date());
	}

	public static String getDay() {
		return sdfDay.format(new Date());
	}

	public static String getDay(Date date) {
		return sdfDay.format(date);
	}

	public static String getDay2(Date date) {
		return sdfDay2.format(date);
	}

	public static String getDays(Date date) {
		return sdfDays.format(date);
	}

	public static String getHour() {
		return sdfHour.format(new Date());
	}

	public static String getDays() {
		return sdfDays.format(new Date());
	}

	public static String getTime() {
		return sdfTime.format(new Date());
	}

	public static String getTime(Date date) {
		if (date == null) {
			return null;
		}
		return sdfTime.format(date);
	}

	public static String getTimeStamp() {
		return timeStamp.format(new Date());
	}

	public static boolean compareDate(String s, String e) {
		if ((fomatDate(s) == null) || (fomatDate(e) == null)) {
			return false;
		}
		return fomatDate(s).getTime() >= fomatDate(e).getTime();
	}

	public static Date fomatDate(String date) {
		DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
		try {
			return fmt.parse(date);
		} catch (ParseException e) {
			LoggerUtil.error(e);
		}
		return null;
	}

	public static Date formatDateToYYYYMMDDHHMMSS(String date) {
		DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			return fmt.parse(date);
		} catch (ParseException e) {
			LoggerUtil.error(e);
		}
		return null;
	}

	public static boolean isValidDate(String s) {
		DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
		try {
			fmt.parse(s);
			return true;
		} catch (Exception e) {
		}
		return false;
	}

	public static boolean isValidDateYYYYMMDD(String s) {
		DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
		try {
			fmt.parse(s);
			return true;
		} catch (Exception e) {
		}
		return false;
	}

	public static int getDiffYear(String startTime, String endTime) {
		DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
		try {
			return (int) ((fmt.parse(endTime).getTime() - fmt.parse(startTime).getTime()) / 86400000L / 365L);
		} catch (Exception e) {
		}
		return 0;
	}

	public static long getDaySub(String beginDateStr, String endDateStr) {
		long day = 0L;
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		Date beginDate = null;
		Date endDate = null;
		try {
			beginDate = format.parse(beginDateStr);
			endDate = format.parse(endDateStr);
		} catch (ParseException e) {
			LoggerUtil.error(e);
		}
		day = (endDate.getTime() - beginDate.getTime()) / 86400000L;

		return day;
	}

	public static String getAfterDayDate(int daysInt) {
		Calendar canlendar = Calendar.getInstance();
		canlendar.add(5, daysInt);
		Date date = canlendar.getTime();

		SimpleDateFormat sdfd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String dateStr = sdfd.format(date);

		return dateStr;
	}

	public static String getAfterDay(int daysInt) {
		Calendar canlendar = Calendar.getInstance();
		canlendar.add(5, daysInt);
		Date date = canlendar.getTime();

		SimpleDateFormat sdfd = new SimpleDateFormat("yyyy-MM-dd");
		String dateStr = sdfd.format(date);

		return dateStr;
	}

	public static String getAfterDayWeek(String days) {
		int daysInt = Integer.parseInt(days);

		Calendar canlendar = Calendar.getInstance();
		canlendar.add(5, daysInt);
		Date date = canlendar.getTime();

		SimpleDateFormat sdf = new SimpleDateFormat("E");
		String dateStr = sdf.format(date);

		return dateStr;
	}

	public static String[] splitDate(String date) {
		return date.split("-");
	}

	public static int daysBetween(Date smdate, Date bdate) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		smdate = sdf.parse(sdf.format(smdate));
		bdate = sdf.parse(sdf.format(bdate));
		Calendar cal = Calendar.getInstance();
		cal.setTime(smdate);
		long time1 = cal.getTimeInMillis();
		cal.setTime(bdate);
		long time2 = cal.getTimeInMillis();
		long between_days = (time2 - time1) / (1000 * 3600 * 24);

		return Integer.parseInt(String.valueOf(between_days));
	}

	public static int daysBetween(String smdate, String bdate) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Calendar cal = Calendar.getInstance();
		cal.setTime(sdf.parse(smdate));
		long time1 = cal.getTimeInMillis();
		cal.setTime(sdf.parse(bdate));
		long time2 = cal.getTimeInMillis();
		long between_days = (time2 - time1) / (1000 * 3600 * 24);

		return Integer.parseInt(String.valueOf(between_days));
	}

	public static int daysBetween(String smdate, String bdate, String pattern) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		Calendar cal = Calendar.getInstance();
		cal.setTime(sdf.parse(smdate));
		long time1 = cal.getTimeInMillis();
		cal.setTime(sdf.parse(bdate));
		long time2 = cal.getTimeInMillis();
		long between_days = (time2 - time1) / (1000 * 3600 * 24);

		return Integer.parseInt(String.valueOf(between_days));
	}

	public static int secondsBetween(Date smdate, Date bdate) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		smdate = sdf.parse(sdf.format(smdate));
		bdate = sdf.parse(sdf.format(bdate));
		Calendar cal = Calendar.getInstance();
		cal.setTime(smdate);
		long time1 = cal.getTimeInMillis();
		cal.setTime(bdate);
		long time2 = cal.getTimeInMillis();
		long between_days = (time2 - time1) / 1000;

		return Integer.parseInt(String.valueOf(between_days));
	}

	public static String fullAge(String birthday) {
		return fullAge(birthday, "y岁M个月零d天");
	}

	public static String fullAge(String birthday, String format) {
		String date = DurationFormatUtils.formatPeriod(fomatDate(birthday).getTime(),
				Calendar.getInstance().getTime().getTime(), format);
		return date;
	}

	public static String fullAgeYM(String birthday) {
		String date = DurationFormatUtils.formatPeriod(fomatDate(birthday).getTime(),
				Calendar.getInstance().getTime().getTime(), "y岁M个月");
		return date;
	}

	private final static int[] dayArr = new int[] { 20, 19, 21, 20, 21, 22, 23, 23, 23, 24, 23, 22 };
	private final static String[] constellationArr = new String[] { "摩羯座", "水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座",
			"狮子座", "处女座", "天秤座", "天蝎座", "射手座", "摩羯座" };

	public static final String[] zodiacArr = { "猴", "鸡", "狗", "猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊" };

	/**
	 * 根据日期获取生肖
	 * 
	 * @return
	 */
	@SuppressWarnings("deprecation")
	public static String getZodica(String birthday) {
		return zodiacArr[fomatDate(birthday).getYear() % 12];
	}

	@SuppressWarnings("deprecation")
	public static String getConstellation(String birthday) {
		Date date = fomatDate(birthday);
		int month = date.getMonth() + 1;
		int day = date.getDate();
		return day < dayArr[month - 1] ? constellationArr[month - 1] : constellationArr[month];
	}

	public static void main(String[] args) throws ParseException {
		System.out.println(getLastDay("2020-05"));
	}

	// 根据开始日期 增加 月份后 算出 日期(yyyy-mm)
	public static String getDate(String begin_date, String addMonth) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(DateUtil.fomatDate(begin_date).getTime());
		calendar.add(Calendar.MONTH, Integer.parseInt(addMonth));
		return sdfYear_MMonth.format(calendar.getTime());
	}

	public static String formatTime(String dateStr) {
		try {
			Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateStr);
			long delta = new Date().getTime() - date.getTime();
			if (delta < 1L * ONE_MINUTE) {
				long seconds = toSeconds(delta);
				return (seconds <= 0 ? 1 : seconds) + ONE_SECOND_AGO;
			}
			if (delta < 45L * ONE_MINUTE) {
				long minutes = toMinutes(delta);
				return (minutes <= 0 ? 1 : minutes) + ONE_MINUTE_AGO;
			}
			if (delta < 24L * ONE_HOUR) {
				long hours = toHours(delta);
				return (hours <= 0 ? 1 : hours) + ONE_HOUR_AGO;
			}
			if (delta < 48L * ONE_HOUR) {
				return "昨天";
			}
			if (delta < 30L * ONE_DAY) {
				long days = toDays(delta);
				return (days <= 0 ? 1 : days) + ONE_DAY_AGO;
			}
			if (delta < 12L * 4L * ONE_WEEK) {
				long months = toMonths(delta);
				return (months <= 0 ? 1 : months) + ONE_MONTH_AGO;
			} else {
				long years = toYears(delta);
				return (years <= 0 ? 1 : years) + ONE_YEAR_AGO;
			}
		} catch (Exception e) {
			System.out.println(dateStr);
			LoggerUtil.error(e);
		}
		return "";
	}

	private static long toSeconds(long date) {
		return date / 1000L;
	}

	private static long toMinutes(long date) {
		return toSeconds(date) / 60L;
	}

	private static long toHours(long date) {
		return toMinutes(date) / 60L;
	}

	private static long toDays(long date) {
		return toHours(date) / 24L;
	}

	private static long toMonths(long date) {
		return toDays(date) / 30L;
	}

	private static long toYears(long date) {
		return toMonths(date) / 365L;
	}

	public static String getSeason() {
		int month = Integer.parseInt(getMonth());
		if (month == 3 || month == 4 || month == 5) {
			return "spring";
		} else if (month == 6 || month == 7 || month == 8) {
			return "summer";
		} else if (month == 9 || month == 10 || month == 11) {
			return "autumn";
		} else {
			return "winter";
		}
	}

	public static String getDayOrNight() {
		int hour = Integer.parseInt(getHour());
		if (hour >= 7 && hour < 19) {
			return "daytime";
		}
		return "night";
	}

	public static Date getNewDateByAddHour(int hour) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date());
		cal.add(Calendar.HOUR, hour);
		return cal.getTime();
	}

	public static Date getNewDateByAddMinute(int minute) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date());
		cal.add(Calendar.MINUTE, minute);
		return cal.getTime();
	}

	public static String getAppFormatTime(String date) {
		Date d = DateUtil.formatDateToYYYYMMDDHHMMSS(date);
		return new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(d);
	}

	public static Date getExcelDate(Integer days) {
		Calendar calendar = new GregorianCalendar(1900, 0, -1);
		Date d = calendar.getTime();
		Calendar cal = Calendar.getInstance();
		cal.setTime(d);
		cal.add(Calendar.DATE, days);
		return cal.getTime();
	}

	public static long fromDateStringToLong(String inVal) {
		Date date = null;
		SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		try {
			date = inputFormat.parse(inVal);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return date.getTime();
	}

	public static String getLastDay(String yearMonth) {
		int year = Integer.parseInt(yearMonth.split("-")[0]);  //年
		int month = Integer.parseInt(yearMonth.split("-")[1]); //月
		Calendar cal = Calendar.getInstance();
		// 设置年份
		cal.set(Calendar.YEAR, year);
		// 设置月份
		// cal.set(Calendar.MONTH, month - 1);
		cal.set(Calendar.MONTH, month); //设置当前月的上一个月
		// 获取某月最大天数
		//int lastDay = cal.getActualMaximum(Calendar.DATE);
		int lastDay = cal.getMinimum(Calendar.DATE); //获取月份中的最小值，即第一天
		// 设置日历中月份的最大天数
		//cal.set(Calendar.DAY_OF_MONTH, lastDay);
		cal.set(Calendar.DAY_OF_MONTH, lastDay - 1); //上月的第一天减去1就是当月的最后一天
		// 格式化日期
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		return sdf.format(cal.getTime());
	}
}