package com.sunxung.factoring.component.util;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.sunxung.factoring.component.exception.BusinessException;

import jodd.datetime.JDateTime;

/** 日期辅助工具类 */
public class DateUtil {

    private static Logger log = LogManager.getLogger(DateUtil.class);
    public static final String generalDateFormat = "yyyy-MM-dd HH:mm:ss";
    private static final String monthFormat = "yyyy-MM";
    public static final String dayFormat = "yyyy-MM-dd";
    private static final String HHmmss = "HH:mm:ss";
    public static final String dayFormat_ymd = "yyyyMMdd";
    private static final String generalDateTFormat = "yyyy-MM-dd'T'HH:mm:ss";
    private static final String yearFormat = "yyyy";
    public static final String dayMonthYearFormat = "dd/MM/yy HH:mm:ss";

    /**
     * 获取“yyyy-MM-dd HH:mm:ss”格式的当前日期
     * 
     * @return
     */
    public static String getCurrentDate() {
        return getGeneralDateFormat(new Date());
    }

    /**
     * 获取一般格式(yyyy-MM-dd HH:mm:ss)的日期字符串
     * 
     * @param date
     * @return
     */
    public static String getGeneralDateFormat(Date date) {
        return dateToString(date, generalDateFormat);
    }

    /**
     * 根据一般格式(yyyy-MM-dd HH:mm:ss)的日期字符串获取日期
     * 
     * @param str
     * @return
     */
    public static Date getGeneralDate(String str) {
        return stringToDate(str, generalDateFormat);
    }

    /**
     * 根据一般格式(yyyy-MM-dd)的日期字符串获取日期
     * 
     * @param str
     * @return
     */
    public static Date getGeneralDateYMD(String str) {
        return stringToDate(str, dayFormat);
    }

    /**
     * 获取日期的年月日字符串(yyyy-MM-dd)
     * 
     * @param date
     * @return
     */
    public static String getDayStringFormat(Date date) {
        return dateToString(date, dayFormat);
    }
    
    /**
     * 获取日期的年月字符串(yyyy-MM)
     * 
     * @param date
     * @return
     */
    public static String getMonthStringFormat(Date date) {
        return dateToString(date, monthFormat);
    }

    /**
     * 将yyyy-MM-dd'T'HH:mm:ss格式转成时间. <br/>
     * 
     * @param dateStr
     * @return
     */
    public static Date getDate(String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat(generalDateTFormat);
        try {
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            throw new BusinessException(CodeUtil.FAIL, "时间转换失败");
        }
    }

    /**
     * 清空时分秒
     * 
     * @param date 日期实例
     * @return
     */
    public static Date setTimeToMin(Date date) {
        if (date == null) {
            return date;
        }
        return new JDateTime(date).setTime(0, 0, 0, 0).convertToDate();
    }

    /**
     * 设置时分秒最大
     * 
     * @param date 日期实例
     * @return
     */
    public static Date setTimeToMax(Date date) {
        if (date == null) {
            return date;
        }
        return new JDateTime(date).setTime(23, 59, 59, 999).convertToDate();
    }

    /**
     * 设置具体日期中午-->下午临界的时分秒
     * 
     * @param date 日期实例
     * @return
     */
    public static Date setTimeToPM(Date date) {
        if (date == null) {
            return date;
        }
        return new JDateTime(date).setTime(11, 59, 59, 999).convertToDate();
    }

    /**
     * 填充时分秒字符串时间
     * 
     * @param dateStr
     * @return
     */
    public static Date getHHmmssDate(String dateStr) {
        return stringToDate(dateStr, HHmmss);
    }

    /**
     * 把日期字符串格式转换成日期类型
     * 
     * @param str
     * @return
     */
    public static Date stringToDate(String dateStr, String formatStr) {
        SimpleDateFormat format = new SimpleDateFormat(formatStr);
        format.setLenient(false);
        if (StringUtil.isNotEmpty(dateStr)) {
            try {
                return format.parse(dateStr);
            } catch (ParseException e) {
                log.error("日期字符串格式转换成日期类型出错", e);
            }
        }
        return null;
    }

    /**
     * 日期转换成指定格式的字符串
     * 
     * @param date
     * @param formatStr
     * @return
     */
    public static String dateToString(Date date, String formatStr) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat format = new SimpleDateFormat(formatStr);
        format.setLenient(false);
        return format.format(date);
    }

    /**
     * 取得某天所在周的第一天
     * 
     * @param year
     * @return
     */
    public static Date getFirstDayOfWeek(Date date) {
        Calendar c = new GregorianCalendar();
        c.setTime(date);
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
        return c.getTime();
    }

    /**
     * 取得某天所在周的第一天并清除时分秒
     * 
     * @param day
     * @return Date
     */
    public static Date getFirstDayOfWeekClear(Date date) {
        return setTimeToMin(getFirstDayOfWeek(date));
    }

    /**
     * 取得某天所在周的最后一天并设置时分秒最小
     * 
     * @param day
     * @return Date
     */
    public static Date getLastDayOfWeekClearMin(Date date) {
        return setTimeToMin(getLastDayOfWeek(date));
    }

    /**
     * 取得某天所在周的最后一天并设置时分秒最大
     * 
     * @param day
     * @return Date
     */
    public static Date getLastDayOfWeekClear(Date date) {
        return setTimeToMax(getLastDayOfWeek(date));
    }

    /**
     * 取得某天所在周的最后一天+1天并清除时分秒
     * 
     * @param day
     * @return Date
     */
    public static Date getLastDayOfWeekAddClear(Date date) {
        return setTimeToMin(addDays(getLastDayOfWeek(date), 1));
    }

    /**
     * 取得某天所在周的最后一天
     * 
     * @param date
     * @return
     */
    public static Date getLastDayOfWeek(Date date) {
        Calendar c = new GregorianCalendar();
        c.setTime(date);
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6);
        return c.getTime();
    }

    /**
     * 取得某年某周的第一天 对于交叉:2008-12-29到2009-01-04属于2008年的最后一周,2009-01-05为2009年第一周的第一天
     * 
     * @param year
     * @param week
     * @return
     */
    public static Date getFirstDayOfWeek(int year, int week) {
        Calendar calFirst = Calendar.getInstance();
        calFirst.set(year, 0, 7);
        Date firstDate = getFirstDayOfWeek(calFirst.getTime());
        Calendar firstDateCal = Calendar.getInstance();
        firstDateCal.setTime(firstDate);
        Calendar c = new GregorianCalendar();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, Calendar.JANUARY);
        c.set(Calendar.DATE, firstDateCal.get(Calendar.DATE));
        Calendar cal = (GregorianCalendar) c.clone();
        cal.add(Calendar.DATE, (week - 1) * 7);
        firstDate = getFirstDayOfWeek(cal.getTime());
        return firstDate;
    }

    /**
     * 取得某年某周的最后一天 对于交叉:2008-12-29到2009-01-04属于2008年的最后一周, 2009-01-04为 2008年最后一周的最后一天
     * 
     * @param year
     * @param week
     * @return
     */
    public static Date getLastDayOfWeek(int year, int week) {
        Calendar calLast = Calendar.getInstance();
        calLast.set(year, 0, 7);
        Date firstDate = getLastDayOfWeek(calLast.getTime());
        Calendar firstDateCal = Calendar.getInstance();
        firstDateCal.setTime(firstDate);
        Calendar c = new GregorianCalendar();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, Calendar.JANUARY);
        c.set(Calendar.DATE, firstDateCal.get(Calendar.DATE));
        Calendar cal = (GregorianCalendar) c.clone();
        cal.add(Calendar.DATE, (week - 1) * 7);
        Date lastDate = getLastDayOfWeek(cal.getTime());
        return lastDate;
    }

    private static Date add(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        } else {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(calendarField, amount);
            return c.getTime();
        }
    }

    /**
     * 增加年
     * 
     * @param date
     * @param amount
     * @return
     */
    public static Date addYears(Date date, int amount) {
        return add(date, 1, amount);
    }

    /**
     * 增加月
     * 
     * @param date
     * @param amount
     * @return
     */
    public static Date addMonths(Date date, int amount) {
        return add(date, 2, amount);
    }

    /**
     * 增加周
     * 
     * @param date
     * @param amount
     * @return
     */
    public static Date addWeeks(Date date, int amount) {
        return add(date, 3, amount);
    }

    /**
     * 增加天
     * 
     * @param date
     * @param amount
     * @return
     */
    public static Date addDays(Date date, int amount) {
        return add(date, 5, amount);
    }

    /**
     * 增加时
     * 
     * @param date
     * @param amount
     * @return
     */
    public static Date addHours(Date date, int amount) {
        return add(date, 11, amount);
    }

    /**
     * 增加分
     * 
     * @param date
     * @param amount
     * @return
     */
    public static Date addMinutes(Date date, int amount) {
        return add(date, 12, amount);
    }

    /**
     * 增加秒
     * 
     * @param date
     * @param amount
     * @return
     */
    public static Date addSeconds(Date date, int amount) {
        return add(date, 13, amount);
    }

    /**
     * 增加毫秒
     * 
     * @param date
     * @param amount
     * @return
     */
    public static Date addMilliseconds(Date date, int amount) {
        return add(date, 14, amount);
    }

    /**
     * 返回:2017-03-31
     */
    public static String formateYMD(Date date) {
        if (date == null) {
            return "";
        }
        return String.format("%1$tY-%1$tm-%1$td", date);
    }

    /**
     * 返回:2017-03
     */
    public static String formateYM(Date date) {
        if (date == null) {
            return "";
        }
        return String.format("%1$tY-%1$tm", date);
    }

    /**
     * 返回:2017-03-31 21:08:17
     */
    public static String formateYMDHMS(Date date) {
        if (date == null) {
            return "";
        }
        return String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS", date);
    }

    /**
     * 返回:年份
     */
    public static List<Integer> getYearList(int number) {
        List<Integer> yearList = new ArrayList<>();
        Calendar a = Calendar.getInstance();
        Integer year = a.get(Calendar.YEAR);
        for (int i = 1; i < number; i++) {
            yearList.add(year - i);
        }
        return yearList;
    }

    /**
     * 给予日期添加小时数
     * 
     * @param date 被操作日期
     * @param hours 被添加的小时数
     * @return 返回添加小时数后的日期
     */
    public static Date addHour(Date date, int hours) {
        if (date == null) {
            return null;
        }
        JDateTime jdTime = new JDateTime(date).addHour(hours);
        return jdTime.convertToDate();
    }

    /**
     * 给予日期减去小时数
     * 
     * @param date 被操作日期
     * @param hours 被减去的小时数
     * @return 返回减去小时数后的日期
     */
    public static Date subHour(Date date, int hours) {
        if (date == null) {
            return null;
        }
        JDateTime jdTime = new JDateTime(date).subHour(hours);
        return jdTime.convertToDate();
    }

    /**
     * 给予日期添加分钟数
     * 
     * @param date 被操作日期
     * @param minute 被添加的分钟数
     * @return 返回添加分钟数后的日期
     */
    public static Date addMinute(Date date, int minute) {
        if (date == null) {
            return null;
        }
        JDateTime jdTime = new JDateTime(date).addMinute(minute);
        return jdTime.convertToDate();
    }

    /**
     * 给予日期减去分钟数
     * 
     * @param date 被操作日期
     * @param minute 被减去的分钟数
     * @return 返回减去分钟数后的日期
     */
    public static Date subMinute(Date date, int minute) {
        if (date == null) {
            return null;
        }
        JDateTime jdTime = new JDateTime(date).subMinute(minute);
        return jdTime.convertToDate();
    }

    /**
     * 给予日期添加天数
     * 
     * @param date 被操作日期
     * @param days 被添加的天数
     * @return 返回添加天数后的日期
     */
    public static Date addDay(Date date, int days) {
        if (date == null) {
            return null;
        }
        JDateTime jdTime = new JDateTime(date).addDay(days);
        return jdTime.convertToDate();
    }

    /**
     * 给予日期减去天数
     * 
     * @param date 被操作日期
     * @param days 被减去的天数
     * @return 返回减去天数后的日期
     */
    public static Date subDay(Date date, int days) {
        if (date == null) {
            return null;
        }
        JDateTime jdTime = new JDateTime(date).subDay(days);
        return jdTime.convertToDate();
    }

    /**
     * 给予日期添加月数
     * 
     * @param date 被操作日期
     * @param months 被添加的月数
     * @return 返回添加月数后的日期
     */
    public static Date addMonth(Date date, int months) {
        if (date == null) {
            return null;
        }
        JDateTime jdTime = new JDateTime(date).addMonth(months);
        return jdTime.convertToDate();
    }

    /**
     * 给予日期减去月数
     * 
     * @param date 被操作日期
     * @param months 被减去的月数
     * @return 返回减去月数后的日期
     */
    public static Date subMonth(Date date, int months) {
        if (date == null) {
            return null;
        }
        JDateTime jdTime = new JDateTime(date).subMonth(months);
        return jdTime.convertToDate();
    }

    /**
     * 获取日期是一年的第几周
     * 
     * @param date 日期
     * @return
     */
    public static Integer getWeekByDay(Date date) {
        Calendar c = Calendar.getInstance();
        c.setFirstDayOfWeek(Calendar.MONDAY); // 设置每周的第一天为星期一
        c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);// 每周从周一开始
        c.setMinimalDaysInFirstWeek(7);
        c.setTime(date);
        return c.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * 获取昨天的日期
     */
    public static Date getYesterdat() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -1);
        Date time = cal.getTime();
        return time;
    }

    /**
     * 比较日期是否相同（通常比较不包含时分秒）注：该方法采用Java8中Java.time提供的方法. <br/>
     * 
     * @param d1
     * @param d2
     * @return
     */
    public static boolean sameDate(Date d1, Date d2) {
        LocalDate localDate1 = ZonedDateTime.ofInstant(d1.toInstant(), ZoneId.systemDefault()).toLocalDate();
        LocalDate localDate2 = ZonedDateTime.ofInstant(d2.toInstant(), ZoneId.systemDefault()).toLocalDate();
        return localDate1.isEqual(localDate2);
    }

    /**
     * 获取指定时间所在月的第一天 <br/>
     * 
     * @return
     */
    public static Date getFirstDayOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        return cal.getTime();
    }

    /**
     * 获取指定时间所在月的最后一天 <br/>
     * 
     * @return
     */
    public static Date getLastDayOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.add(Calendar.MONTH, 1);
        cal.add(Calendar.DAY_OF_MONTH, -1);
        return cal.getTime();
    }

    /**
     * 获取指定年的最大周数 . <br/>
     * 
     * @param year
     * @return
     */
    public static int getMaxWeekNumOfYear(int year) {
        if (year < 1900 || year > 9999) {
            throw new NullPointerException("年度必须大于等于1900年小于等于9999年");
        }
        int result = 52;// 每年至少有52个周 ，最多有53个周。
        String date = DateUtil.dateToString(DateUtil.getFirstDayOfOneWeek(year, 53), "yyyy");
        if (date.equals(year + "")) { // 判断年度是否相符，如果相符说明有53个周。
            result = 53;
        }
        return result;
    }

    /**
     * 获取某年的第几周的开始日期. <br/>
     * 
     * @param year
     * @param week
     * @return
     */
    public static Date getFirstDayOfOneWeek(int year, int week) {
        if (year < 1900 || year > 9999) {
            throw new NullPointerException("年度必须大于等于1900年小于等于9999年");
        }
        Calendar cal = Calendar.getInstance();
        cal.setFirstDayOfWeek(Calendar.MONDAY); // 设置每周的第一天为星期一
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);// 每周从周一开始
        // 上面两句代码配合，才能实现，每年度的第一个周，是包含第一个星期一的那个周。
        cal.setMinimalDaysInFirstWeek(7); // 设置每周最少为7天
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.WEEK_OF_YEAR, week);
        return cal.getTime();
    }

    /**
     * 获取某年的第几周的结束日期 . <br/>
     * 
     * @param year
     * @param week
     * @return
     */
    public static Date getLastDayOfOneWeek(int year, int week) {
        if (year < 1900 || year > 9999) {
            throw new NullPointerException("年度必须大于等于1900年小于等于9999年");
        }
        Calendar cal = Calendar.getInstance();
        cal.setFirstDayOfWeek(Calendar.MONDAY); // 设置每周的第一天为星期一
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);// 每周从周一开始
        // 上面两句代码配合，才能实现，每年度的第一个周，是包含第一个星期一的那个周。
        cal.setMinimalDaysInFirstWeek(7); // 设置每周最少为7天
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.WEEK_OF_YEAR, week);
        return cal.getTime();
    }

    /**
     * 将毫秒数转换成对应的时间. <br/>
     * 
     * @param timeMillis
     * @return
     */
    public static Date getDateByTimeMillis(Long timeMillis) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(timeMillis);
        return c.getTime();
    }

    /**
     * 得到两个日期之间所有的日期
     *
     * @param begin 开始日期
     * @param end 结束日期
     * @return List<Date> 返回日期的List集合
     */
    public static List<Date> getBetweenDates(String beginStr, String endStr) {
        SimpleDateFormat sdf = new SimpleDateFormat(dayFormat);
        Date begin = null;
        Date end = null;
        try {
            begin = sdf.parse(beginStr);
            end = sdf.parse(endStr);
        } catch (ParseException e) {
            throw new BusinessException(CodeUtil.FAIL, "日期格式转换失败" + e.getMessage());
        }
        List<Date> result = new ArrayList<Date>();
        Calendar tempStart = Calendar.getInstance();
        tempStart.setTime(begin);
        while (begin.getTime() <= end.getTime()) {
            result.add(tempStart.getTime());
            tempStart.add(Calendar.DAY_OF_YEAR, 1);
            begin = tempStart.getTime();
        }
        return result;
    }

    /**
     * 提取字符串中包含的日期
     *
     * @param value :18-03-01 星期四
     * @return Date
     */
    public static Date getDateTimeByString(String value) {
        SimpleDateFormat sdf = new SimpleDateFormat(dayFormat);
        String dateStr = "";
        if (StringUtil.isNotEmpty(value)) {
            Pattern p = Pattern.compile("(\\d{4})-(\\d{1,2})-(\\d{1,2})");
            Matcher m = p.matcher(value);
            while (m.find()) {
                dateStr = m.group();
            }
        }
        if (StringUtil.isNotEmpty(dateStr)) {
            try {
                return sdf.parse(dateStr);
            } catch (ParseException e) {
                log.error("DateUtil类中的getDateTimeByString出错：" + e.getMessage());
                throw new BusinessException(CodeUtil.FAIL, "日期格式转换失败" + e.getMessage());
            }
        }
        return null;
    }

    /**
     * 获取日期的年月日字符串(yyyyMMdd)
     * 
     * @param date
     * @return 返回的字符串是：20180302
     */
    public static String getDayStringFormatYMD(Date date) {
        return dateToString(date, dayFormat_ymd);
    }

    /**
     * 根据当前日期得到当前年
     */
    public static String getYearStringFormatYear(Date date) {
        return dateToString(date, yearFormat);
    }

    /**
     * 得到两个日期之间所有的日期
     *
     * @param begin 开始日期
     * @param end 结束日期
     * @return List<Date> 返回日期的List集合
     */
    public static List<String> getBetweenDates(Date begin, Date end) {
        SimpleDateFormat sdf = new SimpleDateFormat(dayFormat_ymd);
        List<String> result = new ArrayList<String>();
        Calendar tempStart = Calendar.getInstance();
        tempStart.setTime(begin);
        while (begin.getTime() <= end.getTime()) {
            result.add(sdf.format(tempStart.getTime()));
            tempStart.add(Calendar.DAY_OF_YEAR, 1);
            begin = tempStart.getTime();
        }
        return result;
    }

    public static Map<String, Object> getBetweenDatesMap(Date begin, Date end) {
        SimpleDateFormat sdf = new SimpleDateFormat(dayFormat_ymd);
        Map<String, Object> result = new HashMap<>();
        Calendar tempStart = Calendar.getInstance();
        tempStart.setTime(begin);
        while (begin.getTime() <= end.getTime()) {
            result.put("day" + sdf.format(tempStart.getTime()), " ");
            tempStart.add(Calendar.DAY_OF_YEAR, 1);
            begin = tempStart.getTime();
        }
        return result;
    }

    public static String getWeekOfDate(String valueStr) {
        if (valueStr == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String[] weekDays = {
                "日", "一", "二", "三", "四", "五", "六"
        };
        Calendar cal = Calendar.getInstance();
        String week;
        try {
            Date dt = sdf.parse(valueStr);
            cal.setTime(dt);
            int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
            if (w < 0)
                w = 0;
            week = weekDays[w];
            return week;
        } catch (Exception e) {
            log.error("DateUtil类中的getWeekOfDate出错：" + e.getMessage());
            throw new BusinessException(CodeUtil.FAIL, "根据日期获取星期失败" + e.getMessage());
        }
    }

    /**
     * 根据日期，获取年份
     *
     * @param date 日期
     * @return String
     */
    public static String getTheYear(Date date) {
        if (null != date) {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            int year = c.get(Calendar.YEAR);
            return String.valueOf(year);
        }
        return null;
    }

    /**
     * 根据日期，获取月份
     *
     * @param date 日期
     * @return String
     */
    public static String getTheMonth(Date date) {
        if (null != date) {
            Calendar c = Calendar.getInstance();
            DecimalFormat df = new DecimalFormat("00");
            c.setTime(date);
            int month = c.get(Calendar.MONTH) + 1;
            String str = df.format(month);
            return str;
        }
        return null;
    }

    /**
     * 去年同期：去年的当前月； 获取去年的当前月，针对年份和月份的比较，日没有要求。
     *
     * @param date
     * @return Date
     */
    public static Date getLastYearCurrentMonth(Date date) {
        if (null != date) {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(Calendar.YEAR, -1);
            c.set(Calendar.DATE, 1);
            return c.getTime();
        }
        return null;
    }

    /**
     * 年末期：去年的12月;获取去年的当前月，针对年份和月份的比较，日没有要求
     *
     * @param date
     * @return Date
     */
    public static Date getLastYearLastMonth(Date date) {
        if (null != date) {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(Calendar.YEAR, -1);
            c.set(Calendar.MONTH, 11);
            c.set(Calendar.DATE, 1);
            return c.getTime();
        }
        return null;
    }

    /**
     * 前年末期：前年的12月；获取去年的当前月，针对年份和月份的比较，日没有要求
     *
     * @param date
     * @return Date
     */
    public static Date getBeforeYearLastMonth(Date date) {
        if (null != date) {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(Calendar.YEAR, -2);
            c.set(Calendar.MONTH, 11);
            c.set(Calendar.DATE, 1);
            return c.getTime();
        }
        return null;
    }

    /**
     * 获取指定时间，属于上午还是下午（时段）
     * 
     * @param date 日期
     * @return
     */
    public static String getCnameOfAMPM(Date date) {
        if (null == date) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        if (cal.get(Calendar.HOUR_OF_DAY) >= 12 && cal.get(Calendar.HOUR_OF_DAY) <= 23) {
            return ConstantUtil.PM_CNAME;
        } else {
            return ConstantUtil.AM_CNAME;
        }
    }

    /**
     * 获取两个时间差（格式：xxx天xxx小时xxx分），如果天数为0则仅显示小时分，以此类推
     * 
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @return
     */
    public static String autoTimeConsuming(Date startDate, Date endDate) {
        if (null != startDate && null != endDate) {
            long oldms = startDate.getTime();
            long nowms = endDate.getTime();
            long poor = 0;
            if (nowms > oldms) {
                poor = nowms - oldms;
            } else {
                poor = oldms - nowms;
            }
            int day = (int) (poor / (1000 * 60 * 60 * 24));
            int hour = (int) (poor / (1000 * 60 * 60) % 24);
            int min = (int) (poor / (1000 * 60) % 60);
            if (day == 0) {
                if (hour == 0) {
                    return min + "分";
                }
                return hour + "时" + min + "分";
            }
            return day + "天" + hour + "时" + min + "分";
        }
        return null;
    }

    /**
     * 获取两个时间差（最小单位：0.5天）
     * 
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @return
     */
    public static String autoOverdue(Date startDate, Date endDate) {
        if (null != startDate && null != endDate) {
            long oldms = startDate.getTime();
            long nowms = endDate.getTime();
            long poor = 0;
            if (nowms > oldms) {
                poor = nowms - oldms;
            } else {
                poor = oldms - nowms;
            }
            int day = (int) (poor / (1000 * 60 * 60 * 24));
            int hour = (int) (poor / (1000 * 60 * 60) % 24);
            int min = (int) (poor / (1000 * 60) % 60);
            Float overdue = 0f;
            if (hour > 11) {
                overdue = 1f;
            }
            if ((hour > 0 && hour <= 11) || (hour == 0 && min > 0)) {
                overdue = 0.5f;
            }
            if (day > 0) {
                overdue = day + overdue;
            }
            return overdue.toString();
        }
        return null;
    }

    /**
     * 获取两个时间差（最小单位：1天）
     * 
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @return
     */
    public static int autoOverdueDay(Date startDate, Date endDate) {
        if (null != startDate && null != endDate) {
            long oldms = startDate.getTime();
            long nowms = endDate.getTime();
            long poor = 0;
            if (nowms > oldms) {
                poor = nowms - oldms;
            } else {
                poor = oldms - nowms;
            }
            int day = (int) (poor / (1000 * 60 * 60 * 24));
            int hour = (int) (poor / (1000 * 60 * 60) % 24);
            int min = (int) (poor / (1000 * 60) % 60);
            int overdue = 0;
            if (hour > 0 || min > 0) {
                overdue = 1;
            }
            if (day > 0) {
                overdue = day + overdue;
            }
            return overdue;
        }
        return 0;
    }

    public static String getYear(Date date) {
        if (null != date) {
            Calendar now = Calendar.getInstance();
            now.setTime(date);
            int year = now.get(Calendar.YEAR);
            return String.valueOf(year);
        }
        return null;
    }

    public static String getMonth(Date date) {
        if (null != date) {
            Calendar now = Calendar.getInstance();
            now.setTime(date);
            int month = now.get(Calendar.MONTH) + 1;
            return String.valueOf(month);
        }
        return null;
    }

    public static String getDay(Date date) {
        if (null != date) {
            Calendar now = Calendar.getInstance();
            now.setTime(date);
            int day = now.get(Calendar.DAY_OF_MONTH);
            return String.valueOf(day);
        }
        return null;
    }
}
