计算工作日期

来源:互联网 发布:js 不等于多个值 编辑:程序博客网 时间:2024/05/17 22:48
/**
 *
 */
package com.widom.jyxd.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.widom.jyxd.common.Constant;

/**
 * Date:2013-4-9
 * <p>
 * comment:计算工作日<br>
 *
 * <p>
 *
 * @author Liao, Ku-Cheng
 */
public final class DateCalculationUtil
{

    private final static Log log = LogFactory.getLog(DateCalculationUtil.class);
    /**
     * 系统参数默认值,便于判断数据库中参数是否发生改变,如果发生变化,重新初始化国定假日,休息工作日数据。
     */
    private static String HOLIDAY_PARAMVALUE = "";
    /**
     * 国定假日 如国庆假日等等
     */
    private static List<Holiday> COUNTRY_HOLIDAY;
    /**
     * 休息工作日 ,因国定放假调休导致的周末工作情况
     */
    private static List<Holiday> REST_WORK;
    /**
     * 当前时间,偏于缓存工作日的计算结果
     */
    private static Calendar currentDate;
    /**
     * 计算时间的日期,结合currentDate,便于缓存计算结果。
     */
    private static int beforeNum;
    /**
     * 时间运算结果
     */
    private static Date result;

    /**
     * 返回一段时间之前的时间点,只计算工作日
     *
     * @param days
     *            如果days小于等于0,返回当前日期
     * @return
     */
    public static Date getWorkTimeBefore(int days)
    {
        if (log.isDebugEnabled())
        {
            log.debug(" getWorkTimeBefore(" + days + ")");
        }
        Calendar current = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try
        {
            Date currentDate = sdf.parse(sdf.format(new Date()));
            current.setTime(currentDate);
        } catch (ParseException e)
        {
            log.warn("", e);
        }
        // 如果结果已经计算,直接返回
        if (null != currentDate && null != result)
        {
            if (beforeNum == days && current.getTime().getTime() == currentDate.getTime().getTime())
            {
                return result;
            }
        }
        else
        {
            Calendar clone = (Calendar) current.clone();
            currentDate = clone;

            // 采用递归方式计算前几天是否为工作日,如果是工作日,修改计算
            while (days > 0)
            {
                current.add(Calendar.DATE, -1);
                if (!isHoliday(current))
                {
                    days--;
                }
            }
        }

        result = current.getTime();
        if (log.isInfoEnabled())
        {
            log.info(" result : " + DateUtil.formateDate(result, "yyyy-MM-dd"));
        }
        return result;
    }

    /**
     * 判断日期是否为假期<br>
     * 1,计算当前日期是否为国定假日,如果是,将当前时间设定到国定假日的开始时间,同时返回true。否则返回false<br>
     * 2,如果当前日期不是国定假日,计算当前日期是否为周末(包含休息工作日),如果当前日期是周末,返回true,否者返回fasle<br>
     *
     * @param cal
     * @return
     */
    private static boolean isHoliday(final Calendar cal)
    {
        return isCountryHoliday(cal) ? true : isWorkEnd(cal);
    }

    /**
     * 是否为休息工作日<br>
     * 1,获取休息工作日的配置时间<br>
     * 2,判断当前时间是否包含在休息工作日当中,如果在休息工作日当中,返回true,否者返回false.
     *
     * @param cal
     * @return
     */
    private static boolean isRestForWork(final Calendar cal)
    {
        if (log.isDebugEnabled())
        {
            log.debug("isCountryHoliday (" + DateUtil.formateDate(cal.getTime(), "yyyy-MM-dd") + ")");
        }
        String key = "key : " + Constant.SYSTEM + " key : " + Constant.HOLIDAY;
        Object data = CacheUtil.get(key);
        String paramValue = null;
        if (null == data)
        {
            paramValue = SystemParamUtil.getSystemParam(Constant.SYSTEM, Constant.HOLIDAY).trim();
            CacheUtil.put(key, paramValue);
        }
        else
        {
            paramValue = data.toString();
        }

        if (!HOLIDAY_PARAMVALUE.equals(paramValue))
        {
            HOLIDAY_PARAMVALUE = paramValue;
            initHoliday(paramValue);
        }
        return iteratorRestForWork(cal);
    }

    /**
     * 遍历休息工作日,判断日期是否包含在休息工作日当中
     *
     * @param cal
     * @return
     */
    private static boolean iteratorRestForWork(Calendar cal)
    {
        if (null != REST_WORK)
        {
            for (Holiday holiday : REST_WORK)
            {
                if (holiday.isContain(cal.getTime()))
                {
                    cal.setTime(holiday.startDate);
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 是否为周末<br>
     * 如果为周末,检查是否为休息工作日.返回true,同时将时间移动到周末开始时间,否则返回fasle
     *
     * @param cal
     * @return
     */
    private static boolean isWorkEnd(final Calendar cal)
    {

        if (log.isDebugEnabled())
        {
            log.debug("isWorkEnd ()");
            log.debug(DateUtil.formateDate(cal.getTime(), "yyyy-MM-dd"));
        }

        int num = cal.get(Calendar.DAY_OF_WEEK);
        if (num == Calendar.SUNDAY)
        {
            if (isRestForWork(cal))
            {
                return false;
            }
            cal.add(Calendar.DATE, -1);
            return true;
        }
        if (num == Calendar.SATURDAY)
        {
            if (isRestForWork(cal))
            {
                return false;
            }

            return true;
        }
        return false;
    }

    /**
     * 是否为国定假日,如果是国定假日,将日期移动到国定假日开始的日期,返回true,否则返回false;
     *
     * @param cal
     * @return
     */
    private static boolean isCountryHoliday(final Calendar cal)
    {

        if (log.isDebugEnabled())
        {
            log.debug("isCountryHoliday (" + DateUtil.formateDate(cal.getTime(), "yyyy-MM-dd") + ")");
        }
        String key = "key : " + Constant.SYSTEM + " key : " + Constant.HOLIDAY;
        Object data = CacheUtil.get(key);
        String paramValue = null;
        if (null == data)
        {
            paramValue = SystemParamUtil.getSystemParam(Constant.SYSTEM, Constant.HOLIDAY).trim();
            CacheUtil.put(key, paramValue);
        }
        else
        {
            paramValue = data.toString();
        }

        if (!HOLIDAY_PARAMVALUE.equals(paramValue))
        {
            HOLIDAY_PARAMVALUE = paramValue;
            initHoliday(paramValue);
        }

        return iteratorHoliday(cal);
    }

    /**
     * 遍历国定假日,如果当前日期在国定假日之内,将当前时间移动到假期的开始时间
     *
     * @param cal
     */
    private static boolean iteratorHoliday(final Calendar cal)
    {
        if (null != COUNTRY_HOLIDAY)
        {
            for (Holiday holiday : COUNTRY_HOLIDAY)
            {
                if (holiday.isContain(cal.getTime()))
                {
                    cal.setTime(holiday.startDate);
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 初始国定假期数据
     */
    private static void initHoliday(String paramValue)
    {
        if (null == paramValue)
        {
            COUNTRY_HOLIDAY = Collections.emptyList();
        }
        try
        {
            String[] sts = paramValue.split(";");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            List<Holiday> result = new LinkedList<Holiday>();
            List<Holiday> rest = new LinkedList<Holiday>();
            for (String st : sts)
            {
                if (st.contains("@"))
                {
                    String[] daysStr = st.split("@");
                    if (daysStr.length == 2)
                    {
                        Date startDate = sdf.parse(daysStr[0]);
                        Date endDate = sdf.parse(daysStr[1]);
                        Holiday holiday = new Holiday(startDate, endDate);
                        result.add(holiday);
                    }
                }
                else if (st.contains("#"))
                {
                    String[] daysStr = st.split("#");
                    if (daysStr.length == 2)
                    {
                        Date startDate = sdf.parse(daysStr[0]);
                        Date endDate = sdf.parse(daysStr[1]);
                        Holiday holiday = new Holiday(startDate, endDate);
                        rest.add(holiday);
                    }
                }
            }
            COUNTRY_HOLIDAY = result;
            REST_WORK = rest;
        } catch (Exception e)
        {
            log.error("", e);
        }
    }

    /**
     * 国定假日静态类 Date:2013-4-11
     * <p>
     * comment: 包含假日的开始时间,结束时间,如果国定假日只有1天,则开始时间与结束时间相同。同时适用周末工作日
     * <p>
     *
     * @author Liao, Ku-Cheng Copyright 2011 sh-tobacco & wisdom
     */
    private static class Holiday
    {
        /**
         * 开始时间
         */
        private Date startDate;
        /**
         * 结束时间
         */
        private Date endDate;

        public Holiday(Date start, Date end)
        {
            startDate = start;
            endDate = end;
        }

        /**
         * 是否在假期内
         *
         * @param date
         * @return
         */
        public boolean isContain(Date date)
        {

            return compareTime(startDate, date) && compareTime(date, endDate);
        }

        /**
         * 比较时间
         *
         * @param start
         * @param end
         * @return
         */
        private boolean compareTime(Date start , Date end)
        {
            long startTime = start.getTime();
            long endTime = end.getTime();
            return startTime <= endTime;

        }
    }

    /**
     * 计算两个日期之间的工作日(只排除周末日期)
     *
     * @param start
     * @param end
     * @return
     */
    public static int getWorkDays(Calendar start , Calendar end)
    {
        if (start.getTime().getTime() > end.getTime().getTime())
        {
            return -1;
        }
        int startDays = nextMonday(start);
        int endDays = nextMonday(end);

        int result = startDays - endDays;

        int startYear = start.get(Calendar.YEAR);
        int endYear = end.get(Calendar.YEAR);

        int days = end.get(Calendar.DAY_OF_YEAR)-start.get(Calendar.DAY_OF_YEAR);
        // 计算跨年日期之间的天数
        if (startYear != endYear)
        {
            int yearNum = endYear - startYear;
            for (int i = 0; i < yearNum; i++)
            {
                days += start.getActualMaximum(Calendar.DAY_OF_YEAR);
                start.add(Calendar.YEAR, 1);
            }
        }

        result += days / 7 * 5;
        return result;
    }

    /**
     * 计算当前日期到下一个星期一的时间天数,同时将时间修改为星期一的日期
     *
     * @param date
     * @return
     */
    private static int nextMonday(Calendar date)
    {

        int result = 0;
        //将时间移动到下一个星期一
        switch (date.get(Calendar.DAY_OF_WEEK))
        {
        case Calendar.FRIDAY:
            result = 1;
            break;
        case Calendar.THURSDAY:
            result = 2;
            break;
        case Calendar.WEDNESDAY:
            result = 3;
            break;
        case Calendar.TUESDAY:
            result = 4;
            break;
        }
        date.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        date.add(Calendar.DAY_OF_YEAR, 7);
        return result;
    }

    public static void main(String[] args) throws ParseException
    {
        //
        // System.out.println(DateCalculationUtil.getWorkTimeBefore(6));
        // System.out.println(DateCalculationUtil.getWorkTimeBefore(6));
        Calendar current = Calendar.getInstance();
        Calendar start = Calendar.getInstance();
        String date = "2013-03-12";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date startDate = sdf.parse(date);
        start.setTime(startDate);

        System.out.println(DateCalculationUtil.getWorkDays(start, current));
    }

}

原创粉丝点击