银行等单位工作日计算的实现

银行等单位工作日计算的实现

 

原先想在JavaEye上发表这篇日志,可是论坛规则小测验让我倍感麻烦,所以暂且让它出现在QZone

  下面就进入正题,这里主要介绍工作日实现的思路及实现。

  年末有段时间需要维护新疆FOA,其中有个需求就是在数据库中查询某个时间段工作日>3天的记录。由于同时存在农历和阳历,造成有些工作日可以休息或者有些周末要正常上班的问题,所以计算工作日还需要考虑到这个问题。

  先介绍下工作日计算的思路:

  1、确定计算公式

    工作日 = 正常工作日 - 工作休息日 + 休息工作日

     说明:正常工作日:按照阳历算出除去周六周日的天数。

        工作休息日:在正常工作日下的休息天数。如国庆、春节7天,工作日可以休息。

        休息工作日:在周末需要正常上班的天数。如国庆、春节后需要在周六或者周日正常上班。

  2、根据公式选择实现方式

    正常工作日实现:遍历某个时间段内每一天,过滤掉周六周日,最终得到正常工作日天数。

    工作休息日实现:将工作休息日的日期写入字典,提供对比,最终计算出工作休息日的天数。

    休息工作日实现:类似工作休息日实现方式。

    说明:由于实现方式简单,以文字方式可以描述清楚问题,这里就不考虑画流程图。

  下面简要介绍Java语言的实现:

  1、类图

    (QZone不支持日志图片上传,转到JavaEye下再上传图片)

  2、实现源代码(代码注释有不周到处请谅解)

/* ==================================================================

 * Created [2010-1-22 下午05:00:29] by Neal Miao

 * ==================================================================  

 * XXX 

 * ================================================================== 

 * XXX  License v1.0  

 * Copyright (c) Gsoft S&T Co.ltd HangZhou, 2009-2010 

 * ================================================================== 

 * 杭州中科天翔科技有限公司拥有该文件的使用、复制、修改和分发的许可权

 * 如果你想得到更多信息,请访问 <http://www.g-soft.com.cn>

 *

 * Gsoft S&T Co.ltd HangZhou owns permission to use, copy, modify and 

 * distribute this documentation.

 * For more information on gs, please 

 * see <http://www.g-soft.com.cn>.  

 * ================================================================== 

 */

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Calendar;

import java.util.Date;

import java.util.LinkedList;

import java.util.List;

 

/**

 * <p>

 * WeekdayCounter.java

 * </p>

 * <p>

 * 可用于工作日计算。<br>

 * 由于中国的部分节假日为农历节日,如春节、清明节等等。

 * 从而使得工作日和周末的混乱,计算工作日要重新考虑。

 * </p>

 * 

 * @author $Author: nealmiao $

 * @version $Revision: 1.1 $

 */

public class WeekdayCountHelper {

      

       /** 控制是否显示console */

       private static boolean needConsoleInfo = false;

 

       /**

        * needConsoleInfo

        *

        * @return  the needConsoleInfo

        * @since   Ver 1.0

        */

       public static boolean isNeedConsoleInfo() {

              return needConsoleInfo;

       }

 

       /**

        * needConsoleInfo

        *

        * @param   needConsoleInfo    the needConsoleInfo to set

        * @since   Ver 1.0

        */

       public static void setNeedConsoleInfo(boolean needConsoleInfo) {

              WeekdayCountHelper.needConsoleInfo = needConsoleInfo;

       }

 

       /**

        * 判断工作日是否大于3,如果是则返回true

        * 

        * @param revDate

        * @param retnDate

        * @return 返回判断工作日是否大于3结果。

        * @since Ver 1.0

        */

       public static boolean isValid(Date revDate, Date retnDate) {

              if (getWeekDays(revDate, retnDate, null, null) > 3) {

                     return true;

              } else {

                     return false;

              }

       }

 

       /**

        * 判断工作日是否大于3

        * 

        * @param revDate

        * @param retnDate

        * @param specialHolidayList

        * @param specialNonHolidayList

        * @return 返回判断工作日是否大于3结果。

        * @since Ver 1.0

        */

       public static boolean isValid(Date revDate, Date retnDate,

                     List<Date> specialHolidayList, List<Date> specialNonHolidayList) {

              if (getWeekDays(revDate, retnDate, specialHolidayList,

                            specialNonHolidayList) > 3) {

                     return true;

              } else {

                     return false;

              }

       }

 

       /**

        * 判断工作日是否大于3

        *

        * @param startDate

        * @param endDate

        * @param specialHolidayList

        * @param specialNonHolidayList

        * @throws ParseException

        * @return boolean

        * @since Ver 1.0

        */

       public static boolean isValid(String startDate, String endDate,

                     List<Date> specialHolidayList, List<Date> specialNonHolidayList)

                     throws ParseException {

              if (isNeedConsoleInfo()) {

                     System.out.println("/nFrom " + startDate + " to " + endDate);

              }

              SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

              return isValid(format.parse(startDate), format.parse(endDate),

                            specialHolidayList, specialNonHolidayList);

       }

 

       /**

        * 根据日期判断是否为周末,只考虑周六和周日。

        * 

        * @param date

        * @return 返回是否为周末。

        * @since Ver 1.0

        */

       public static boolean isWeekend(Date date) {

              Calendar calendar = Calendar.getInstance();

              calendar.setTime(date);

              int week = calendar.get(Calendar.DAY_OF_WEEK);

              if (Calendar.SUNDAY == week || Calendar.SATURDAY == week) {

                     return true;

              } else {

                     return false;

              }

       }

 

       /**

        * 周末要上班的天数

        * 

        * @param startDate

        * @param endDate

        * @param specialHolidayList

        * @return int

        * @exception

        * @since Ver 1.0

        */

       public static int getSpecialNonHolidays(Date startDate, Date endDate,

                     List<Date> specialNonHolidayList) {

              Calendar start = Calendar.getInstance();

              start.setTime(startDate);

              Calendar end = Calendar.getInstance();

              end.setTime(endDate);

              Calendar compareDate = Calendar.getInstance();

              int days = 0;

              while (start.compareTo(end) <= 0) {

                     for (Date date : specialNonHolidayList) {

                            compareDate.setTime(date);

                            int day = compareDate.get(Calendar.DAY_OF_WEEK);

                            if (day == Calendar.SUNDAY || day == Calendar.SATURDAY) {

                                   if (start.compareTo(compareDate) == 0) {

                                          days++;

                                          continue;

                                   }

                            } else {

                                   // do nothing, 过滤掉输入的周末日期

                            }

                     }

                     start.set(Calendar.DATE, start.get(Calendar.DATE) + 1);

              }

              if (isNeedConsoleInfo()) {

                     System.out.print("周末上班的工作日:" + days + "/t");

              }

              return days;

       }

 

       /**

        * 特殊工作日,主要由农历节日引起。

        * 

        * @param startDate

        * @param endDate

        * @param specialHolidayList

        * @return int

        * @exception

        * @since Ver 1.0

        */

       public static int getSpecialHolidays(Date startDate, Date endDate,

                     List<Date> specialHolidayList) {

              Calendar start = Calendar.getInstance();

              start.setTime(startDate);

              Calendar end = Calendar.getInstance();

              end.setTime(endDate);

              Calendar compareDate = Calendar.getInstance();

              int days = 0;

              while (start.compareTo(end) <= 0) {

                     for (Date date : specialHolidayList) {

                            compareDate.setTime(date);

                            int day = compareDate.get(Calendar.DAY_OF_WEEK);

                            if (day == Calendar.SUNDAY || day == Calendar.SATURDAY) {

                                   // do nothing, 过滤掉输入的非周末日期

                            } else {

                                   if (start.compareTo(compareDate) == 0) {

                                          days++;

                                          continue;

                                   }

                            }

                     }

                     start.set(Calendar.DATE, start.get(Calendar.DATE) + 1);

              }

              if (isNeedConsoleInfo()) {

                     System.out.print("正常工作日的休息日:" + days + "/t");

              }

              return days;

       }

 

       /**

        * 循环遍历日期,获取工作日天数。

        * 

        * @param startDate 起始日期

        * @param endDate 结束日期

        * @return 返回工作日天数。

        * @since Ver 1.0

        */

       public static int getNormalWeekdays(Date startDate, Date endDate) {

              Calendar start = Calendar.getInstance();

              start.setTime(startDate);

              Calendar end = Calendar.getInstance();

              end.setTime(endDate);

              int days = 0;

              while (start.compareTo(end) <= 0) {

                     int day = start.get(Calendar.DAY_OF_WEEK);

                     start.set(Calendar.DATE, start.get(Calendar.DATE) + 1);

                     if (day == Calendar.SUNDAY || day == Calendar.SATURDAY) {

                            continue;

                     } else {

                            days++;

                     }

              }

              if (isNeedConsoleInfo()) {

                     System.out.print("正常工作日:" + days + "/t");

              }

              return days;

       }

 

       /**

        * 计算获得实际工作天数。<br>

        * 工作天数 = 计算公式正常的工作天数-特殊的(农历)节假日+特殊的工作日

        * 

        * @param startDate

        * @param endDate

        * @param specialHolidayList

        * @param specialNonHolidayList

        * @return 返回实际工作日天数。

        */

       public static int getWeekDays(Date startDate, Date endDate,

                     List<Date> specialHolidayList, List<Date> specialNonHolidayList) {

              int days = getNormalWeekdays(startDate, endDate)

                            - getSpecialHolidays(startDate, endDate, specialHolidayList)

                            + getSpecialNonHolidays(startDate, endDate, specialNonHolidayList);

              if (isNeedConsoleInfo()) {

                     System.out.print("/n实际工作日:" + days + "/t");

              }

              return days;

       }

 

       public static void main(String[] args) throws ParseException {

              SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

              List<Date> holidayList = new LinkedList<Date>();

              holidayList.add(format.parse("2010-2-10"));

              holidayList.add(format.parse("2010-2-9"));

              holidayList.add(format.parse("1990-2-9"));

              List<Date> nonHolidayList = new LinkedList<Date>();

              nonHolidayList.add(format.parse("2010-2-13"));

              setNeedConsoleInfo(true);

              isValid("2010-2-8", "2010-2-13", holidayList,      nonHolidayList);

              isValid("1992-2-8", "2010-2-13", holidayList,      nonHolidayList);

              isValid("1990-2-8", "2010-2-13", holidayList,      nonHolidayList);

              isValid("1990-2-8", "1990-2-13", holidayList,      nonHolidayList);

       }

}

  测试结果:

From 2010-2-8 to 2010-2-13

正常工作日:5     工作休息日:2     休息工作日:1    

实际工作日:4    

From 1992-2-8 to 2010-2-13

正常工作日:4700     工作休息日:2     休息工作日:1    

实际工作日:4699    

From 1990-2-8 to 2010-2-13

正常工作日:5222     工作休息日:1     休息工作日:0    

实际工作日:5221    

From 1990-2-8 to 1990-2-13

正常工作日:4     工作休息日:1     休息工作日:0    

实际工作日:3    

  对比1992-2-8 to 2010-2-131990-2-8 to 2010-2-13的结果,发现后者的结果有问题。后者的正确结果应该是5220。时间跨度达到某一个值程序会出现位置错误。一般情况下,工作日的时间跨度不会大于4000多天,所以这个程序还是具有一定实用性和通用性。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C1618

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值