package com.cirle.scientific.utils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

/**
 * 日期实用工具，我们在做统计功能的时候，经常要统计本周，本月，本季度 本年的数据，这就需要以某一天为基准，找出这些日期的范围；另外也有些
 * 方便的Date与String的转换函数。
 * 
 * @author zhougf
 * 
 */
public class DateUtil {
	public static final int HOUR = 1129 + 1;

	public static final int DATE = 1129 + 2;

	public static final int WEEK = 1129 + 3;

	public static final int MONTH = 1129 + 4;

	public static final int SEASON = 1129 + 5;

	public static final int YEAR = 1129 + 6;

	public static final int NEXTYEAR = 1129 + 7;

	public static final int PREYEAR = 1129 + 8;

	public static final int NEXTMONTH = 1129 + 9;

	public static final int PREMONTH = 1129 + 10;

	public static final String BEGIN = "begin";

	public static final String END = "end";

	public static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";
	public static final String GMT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
	public static TimeZone USER_TIMEZONE = TimeZone.getTimeZone("PRC");
	public static TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT");

	/**
	 * 根据指定的日期和范围标准来获取特定的日期范围，范围可以是当天、本周、本月、本季度和当年
	 * 
	 * @param ref
	 *            : 指定的日期
	 * @param range
	 *            : 范围标准（天、周、月、季度、年）
	 * @return 一个Map，key为begin或end,value为表明开始或结束日期
	 */

	public static Map getDateRange(Date ref, int range) {
		Map m = new HashMap();
		Calendar cal = Calendar.getInstance();
		cal.setTime(ref);

		// 本周
		if (range == WEEK) {
			int cnt = 0;
			for (; cal.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY; cnt++) {
				cal.add(Calendar.DATE, -1);
			}
			m.put(BEGIN, cal.getTime());
			cal.add(Calendar.DATE, cnt);
			while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
				cal.add(Calendar.DATE, 1);
			}
			m.put(END, cal.getTime());

			// 本月
		} else if (range == MONTH) {
			cal.set(Calendar.DATE, 1);
			m.put(BEGIN, cal.getTime());
			System.out.println(">>>>>>>>>>>>>>>>> " + cal.get(Calendar.MONTH));
			int month = cal.get(Calendar.MONTH) + 1;
			switch (month) {
			case 1:
			case 3:
			case 5:
			case 7:
			case 8:
			case 10:
			case 12:
				cal.set(Calendar.DATE, 31);
				break;
			case 4:
			case 6:
			case 9:
			case 11:
				cal.set(Calendar.DATE, 30);
				break;
			case 2:
				int year = cal.get(Calendar.YEAR);
				if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
					cal.set(Calendar.DATE, 29);
				} else {
					cal.set(Calendar.DATE, 28);
				}
				break;
			}
			m.put(END, cal.getTime());

		}
		// 上一月
		else if (range == PREMONTH) {
			cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) - 1);
			cal.set(Calendar.DATE, 1);
			m.put(BEGIN, cal.getTime());
			int month = cal.get(Calendar.MONTH) + 1;
			switch (month) {
			case 1:
			case 3:
			case 5:
			case 7:
			case 8:
			case 10:
			case 12:
				cal.set(Calendar.DATE, 31);
				break;
			case 4:
			case 6:
			case 9:
			case 11:
				cal.set(Calendar.DATE, 30);
				break;
			case 2:
				int year = cal.get(Calendar.YEAR);
				if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
					cal.set(Calendar.DATE, 29);
				} else {
					cal.set(Calendar.DATE, 28);
				}
				break;
			}
			m.put(END, cal.getTime());
		}
		// 下一月
		else if (range == NEXTMONTH) {
			cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + 1);
			cal.set(Calendar.DATE, 1);
			m.put(BEGIN, cal.getTime());
			int month = cal.get(Calendar.MONTH) + 1;
			switch (month) {
			case 1:
			case 3:
			case 5:
			case 7:
			case 8:
			case 10:
			case 12:
				cal.set(Calendar.DATE, 31);
				break;
			case 4:
			case 6:
			case 9:
			case 11:
				cal.set(Calendar.DATE, 30);
				break;
			case 2:
				int year = cal.get(Calendar.YEAR);
				if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
					cal.set(Calendar.DATE, 29);
				} else {
					cal.set(Calendar.DATE, 28);
				}
				break;
			}
			m.put(END, cal.getTime());

		}
		// 本季度
		else if (range == SEASON) {
			int month = cal.get(Calendar.MONTH);
			switch (month / 3) {
			case 0: // 01-01 to 03-31
				cal.set(Calendar.MONTH, 0);
				cal.set(Calendar.DATE, 1);
				m.put(BEGIN, cal.getTime());
				cal.set(Calendar.MONTH, 2);
				cal.set(Calendar.DATE, 31);
				m.put(END, cal.getTime());
				break;
			case 1: // 04-01 to 06-30
				cal.set(Calendar.MONTH, 3);
				cal.set(Calendar.DATE, 1);
				m.put(BEGIN, cal.getTime());
				cal.set(Calendar.MONTH, 5);
				cal.set(Calendar.DATE, 30);
				m.put(END, cal.getTime());

				break;
			case 2: // 07-01 to 09-30
				cal.set(Calendar.MONTH, 6);
				cal.set(Calendar.DATE, 1);
				m.put(BEGIN, cal.getTime());
				cal.set(Calendar.MONTH, 8);
				cal.set(Calendar.DATE, 30);
				m.put(END, cal.getTime());
				break;
			case 3: // 10-01 to 12-31
				cal.set(Calendar.MONTH, 9);
				cal.set(Calendar.DATE, 1);
				m.put(BEGIN, cal.getTime());
				cal.set(Calendar.MONTH, 11);
				cal.set(Calendar.DATE, 31);
				m.put(END, cal.getTime());
				break;
			}
		}
		// 当年
		else if (range == YEAR) {
			cal.set(Calendar.MONTH, 0);
			cal.set(Calendar.DATE, 1);
			m.put(BEGIN, cal.getTime());
			cal.set(Calendar.MONTH, 11);
			cal.set(Calendar.DATE, 31);
			m.put(END, cal.getTime());
		}
		// 上年
		else if (range == PREYEAR) {
			cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) - 1);
			cal.set(Calendar.MONTH, 0);
			cal.set(Calendar.DATE, 1);
			m.put(BEGIN, cal.getTime());
			cal.set(Calendar.MONTH, 11);
			cal.set(Calendar.DATE, 31);
			m.put(END, cal.getTime());
		}
		// 下年
		else if (range == NEXTYEAR) {
			cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + 1);
			cal.set(Calendar.MONTH, 0);
			cal.set(Calendar.DATE, 1);
			m.put(BEGIN, cal.getTime());
			cal.set(Calendar.MONTH, 11);
			cal.set(Calendar.DATE, 31);
			m.put(END, cal.getTime());
		}
		// 默认是当天
		else {
			m.put(BEGIN, cal.getTime());
			m.put(END, cal.getTime());
		}
		setTime(m); // 设定时间
		return m;
	}

	/**
	 * 根据指定的日期和范围标准来获取特定的日期范围，范围可以是当天、本周、本月、本季度和当年
	 * 
	 * @author zhougf
	 * @param ref
	 *            : 指定的日期字符串，格式为"yyyy-mm-dd"
	 * @param range
	 *            : 范围标准（天、周、月、季度、年）
	 * @return 一个Map，key为begin或end,value为表明开始或结束日期
	 */
	public static Map getDateRange(String ref, int range) {
		if (!ref.matches("\\d{4}-\\d{1,2}-\\d{1,2}")) {
			return null;
		}
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, Integer.parseInt(ref.split("-")[0]));
		cal.set(Calendar.MONTH, Integer.parseInt(ref.split("-")[1]) - 1);
		cal.set(Calendar.DATE, Integer.parseInt(ref.split("-")[2]));
		Date d = cal.getTime();
		return getDateRange(d, range);
	}

	/**
	 * 将指定的日期以特定的格式转换成字符串
	 * 
	 * @param d
	 *            指定的日期
	 * @param format
	 *            指定的格式
	 * @return 转换后的日期字符串
	 */
	public static String dateToStr(Date d, String format) {
		SimpleDateFormat df = (SimpleDateFormat) SimpleDateFormat.getDateInstance();
		df.applyPattern(format);
		return df.format(d);
	}

	/**
	 * 标准长日期转化为标准短日期
	 * 
	 * @param strDate
	 * @param format
	 * @return
	 */
	public static String formatDateStr(String strDate, String format) {
		Date rtdate = null;
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		SimpleDateFormat df = (SimpleDateFormat) SimpleDateFormat.getDateInstance();
		try {
			rtdate = sdf.parse(strDate);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		df.applyPattern(format);
		return df.format(rtdate);
	}

	/**
	 * 以格式"yyyy-MM-dd"将日期转换成字符串
	 * 
	 * @param d
	 *            指定日期
	 * @return 转换后的日期字符串
	 */
	public static String dateToStr(Date d) {
		return dateToStr(d, "yyyy-MM-dd HH:mm");
	}

	/**
	 * 将一个字符串转换成日期类型，只支持"yyyy-MM-dd HH:mm:ss"格式，如果不是，则返回 null
	 * 
	 * @param strDate
	 *            日期字符串
	 * @return 如果格式匹配，返回Date类型；否则返回 null
	 */
	public static Date strToDate(String strDate) {
		// 用正则匹配日期字符串
		if (!strDate.matches("\\d{4}-\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}")
				&& !strDate.matches("\\d{4}-\\d{1,2}-\\d{1,2}"))
			return null;
		Calendar cal = Calendar.getInstance();
		String[] ser = strDate.split(" ");
		String type = "";
		String date = "";
		String hour = "";
		if (ser.length == 1) {
			type = "y";
			date = ser[0];
		} else {
			type = "yh";
			date = ser[0];
			hour = ser[1];
		}

		if (!"".equals(type) && type.equals("yh")) {
			// 设定日期
			cal.set(Calendar.YEAR, Integer.parseInt(date.split("-")[0]));
			cal.set(Calendar.MONTH, Integer.parseInt(date.split("-")[1]) - 1);
			cal.set(Calendar.DATE, Integer.parseInt(date.split("-")[2]));
			// 设定时间
			cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hour.split(":")[0]));
			cal.set(Calendar.MINUTE, Integer.parseInt(hour.split(":")[1]));
			cal.set(Calendar.SECOND, Integer.parseInt(hour.split(":")[2]));
		} else if (!"".equals(type) && type.equals("y")) {
			// 设定日期
			cal.set(Calendar.YEAR, Integer.parseInt(date.split("-")[0]));
			cal.set(Calendar.MONTH, Integer.parseInt(date.split("-")[1]) - 1);
			cal.set(Calendar.DATE, Integer.parseInt(date.split("-")[2]));
		}
		return cal.getTime();
	}

	/**
	 * 给日期范围Map中的起始和结束日期设定时间，默认开始为"00:00:00" 结束为"23:59:59"
	 * 
	 * @param m
	 *            : 日期范围Map
	 */

	private static void setTime(Map m) {
		Calendar cal = Calendar.getInstance();
		cal.setTime((Date) m.get(BEGIN));
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		m.put(BEGIN, cal.getTime());

		cal.setTime((Date) m.get(END));
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		m.put(END, cal.getTime());
	}

	/**
	 * 通过字符串转化为Calendar
	 * 
	 * @param dateStr
	 * @return
	 */
	public static Calendar getCalendarByStr(String dateStr) {
		Calendar ce = Calendar.getInstance();
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		try {
			Date date = df.parse(dateStr);
			ce.setTime(date);
		} catch (ParseException e) {
			// TODO 自动生成 catch 块
			e.printStackTrace();
		}
		return ce;
	}

	/**
	 * 传入年份、月份得到月份的天数
	 * 
	 * @param month
	 * @param year
	 * @return
	 */
	public static int monthDateCount(int month, int year) {
		int date = 0;
		if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
			date = 31;
		} else if (month == 4 || month == 6 || month == 9 || month == 11) {
			date = 30;
		} else if (month == 2) {
			if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
				date = 29;
			} else {
				date = 28;
			}
		}
		return date;
	}

	/**
	 * 根据日期字符串返回相应的Calendar
	 * 
	 * @param datastr
	 *            日期字符串
	 * @param gs
	 *            日期格式标记，1-"2005-03-12 12:23:32" 2-"2005-03-12"
	 * @return Calendar
	 */
	public static Calendar getCalendarFromString(String dateStr, String format) {
		Date date = new Date();
		SimpleDateFormat dateFormat = new SimpleDateFormat(format);
		try {
			date = dateFormat.parse(dateStr);
			Calendar myCal = Calendar.getInstance();
			myCal.setTime(date);
			return myCal;
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 根据日期字符串返回相应的Calendar
	 * 
	 * @param datastr
	 *            日期字符串
	 * @param gs
	 *            日期格式标记，1-"2005-03-12 12:23:32" 2-"2005-03-12"
	 * @return Calendar
	 */
	public static Calendar getCalendarFromString(String dateStr, String format, Locale locale) {
		Date date = new Date();
		SimpleDateFormat dateFormat = new SimpleDateFormat(format, locale);
		try {
			date = dateFormat.parse(dateStr);
			Calendar myCal = Calendar.getInstance();
			myCal.setTime(date);
			return myCal;
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 将指定的日期以格林威治时间格式转换成字符串
	 * 
	 * @param d
	 * @return
	 */
	public static String dateToGMTStr(Date d) {
		SimpleDateFormat df = (SimpleDateFormat) SimpleDateFormat.getDateInstance();
		df.applyPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
		// df.setTimeZone(TimeZone.getTimeZone("GMT"));
		return df.format(d);
	}

	/**
	 * get a dateformat for any timezone
	 * 
	 * @param timeZone
	 * @return
	 */
	public static SimpleDateFormat getDateFormat(TimeZone timeZone) {
		SimpleDateFormat formater = new SimpleDateFormat(DATE_PATTERN);
		formater.setTimeZone(timeZone);
		return formater;
	}

	/**
	 * convert a GMT calendar to any local time string
	 * 
	 * @param calendar
	 * @return
	 */
	public static String convertToLocalTimeString(Calendar calendar) {
		if (null == calendar) {
			return null;
		}
		SimpleDateFormat df = getDateFormat(GMT_TIMEZONE);
		df.applyPattern(DATE_PATTERN);
		return getDateFormat(USER_TIMEZONE).format(calendar.getTime());
	}

	public static Calendar convertToLocalTimeCalendar(Calendar calendar) {
		String time = convertToLocalTimeString(calendar);
		return getCalendarFromString(time, DATE_PATTERN);
	}

	/**
	 * convert any date string to a gmt calendar
	 * 
	 * @param time
	 * @return
	 * @throws ParseException
	 */
	public static String convertToGMTTimeString(Calendar calendar) {
		if (null == calendar) {
			return null;
		}
		SimpleDateFormat df = getDateFormat(GMT_TIMEZONE);
		df.applyPattern(GMT_PATTERN);
		return df.format(calendar.getTime());
	}

	public static Calendar convertToGMTTimeCalendar(String datestring) {
		if (null == datestring) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		SimpleDateFormat df = getDateFormat(GMT_TIMEZONE);
		if (datestring.length() > 20) {
			df.applyPattern(GMT_PATTERN);
		} else {
			df.applyPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
		}
		try {
			Date date = df.parse(datestring);
			c.setTime(date);
		} catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
		return c;
	}

	/**
	 * 计算给定的时间与当前时间的差值，并分类给出结果
	 * 
	 * @param selCal
	 * @return
	 */
	public static String generateTimeStr(Calendar selCal) {
		Calendar nc = Calendar.getInstance();

		if (selCal == null || nc.getTimeInMillis() < selCal.getTimeInMillis()) {
			return "刚刚";
		}

		long dif = nc.getTimeInMillis() - selCal.getTimeInMillis();

		long tenmin = 1000 * 600L;

		long onehour = 1000 * 3600L;

		long oneday = 24 * 3600 * 1000L;

		long onemonth = 30 * 24 * 3600 * 1000L;

		long oneyear = 365 * 24 * 3600 * 1000L;

		if (dif < tenmin) {
			return "刚刚";
		} else if (dif >= tenmin && dif < onehour) {
			long bfm = dif / (60 * 1000);
			return (bfm + "分钟前");
		} else if (dif >= onehour && dif < oneday) {
			long bfm = dif / onehour;
			return (bfm + "小时前");
		} else if (dif >= oneday) {
			return dateToStr(selCal.getTime());
		} else {
			return "";
		}
	}

	/**
	 * 计算给定的时间与当前时间的差值，并分类给出结果
	 * 
	 * @param selCal
	 * @return
	 */
	public static String generateTimeStrDjs(Calendar selCal) {
		Calendar nc = Calendar.getInstance();

		if (selCal.getTimeInMillis() < nc.getTimeInMillis()) {
			return "0分";
		}

		long dif = selCal.getTimeInMillis() - nc.getTimeInMillis();

		long onemin = 60 * 1000L;

		long onehour = 1000 * 3600L;

		long oneday = 24 * 3600 * 1000L;

		StringBuffer rs = new StringBuffer();
		long bfm = dif / oneday;

		rs.append(bfm < 10 ? "0" + bfm + "天" : bfm + "天");

		long hoursy = dif - bfm * oneday;

		long hournum = (hoursy < onehour) ? 0 : (hoursy / onehour);

		rs.append(hournum < 10 ? "0" + hournum + "时" : hournum + "时");

		long minsy = hoursy - hournum * onehour;

		long minnum = (minsy < onemin) ? 0 : (minsy / onemin);

		rs.append(minnum < 10 ? "0" + minnum + "分" : minnum + "分");

		return rs.toString();
	}

	public static int inc(int temp) {
		if (temp > 0) {
			return temp * 2;
		}
		return -1;
	}


	/**
	 * date2比date1多的天数
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static int differentDays(Date date1,Date date2)
	{
		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(date1);

		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(date2);
		int day1= cal1.get(Calendar.DAY_OF_YEAR);
		int day2 = cal2.get(Calendar.DAY_OF_YEAR);

		int year1 = cal1.get(Calendar.YEAR);
		int year2 = cal2.get(Calendar.YEAR);
		if(year1 != year2)   //同一年
		{
			int timeDistance = 0 ;
			for(int i = year1 ; i < year2 ; i ++)
			{
				if(i%4==0 && i%100!=0 || i%400==0)    //闰年
				{
					timeDistance += 366;
				}
				else    //不是闰年
				{
					timeDistance += 365;
				}
			}

			return timeDistance + (day2-day1) ;
		}
		else    //不同年
		{
			System.out.println("判断day2 - day1 : " + (day2-day1));
			return day2-day1;
		}
	}

	public static void main(String... strings) {
		// Calendar c = getCalendarFromString("2017-03-29 15:10:00", "yyyy-MM-dd
		// HH:mm:ss");
		//
		// System.out.println(generateTimeStrDjs(c));

		int num = 90;
		char c = (char) num;
		System.out.println(c);

	}
}
