工作日处理工具类(包括工作日判断和工作日区间判断)

对于工作日处理相对来说还是比较简单的,不外乎就是周末判断和假期判断。

不过,有些人会把它们写死在类里面,看以下代码:

耦合性较强的代码:

public class WeekdayUtil {

	/**
	 * @title 判断两个日期是否在指定工作日内
	 * @detail (只计算周六和周日)
	 *          例如:前时间2008-12-05,后时间2008-12-11
	 * @author chanson
	 * @param beforeDate 前时间
	 * @param afterDate  后时间
	 * @param deadline 最多相隔时间
	 * @return 是的话,返回true,否则返回false
	 */
	public boolean compareWeekday(String beforeDate, String afterDate, int deadline) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			Date d1 = sdf.parse(beforeDate);
			Date d2 = sdf.parse(afterDate);

			//工作日
			int workDay = 0;
			GregorianCalendar gc = new GregorianCalendar();
			gc.setTime(d1);
			// 两个日期相差的天数
			long time = d2.getTime() - d1.getTime();
			long day = time / 3600000 / 24 + 1;
			if(day < 0){
				//如果前日期大于后日期,将返回false
				return false;
			}
			for (int i = 0; i < day; i++) {
				if(isWeekday(gc)){
					workDay++;
//					System.out.println(gc.getTime());
				}
				//往后加1天
				gc.add(GregorianCalendar.DATE, 1);
			}
			return workDay <= deadline;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
	
	/**
	 * @title 判断是否为工作日
	 * @detail 工作日计算:
	 *           1、正常工作日,并且为非假期
	 *           2、周末被调整成工作日
	 * @author chanson
	 * @param date 日期
	 * @return 是工作日返回true,非工作日返回false
	 */
	public boolean isWeekday(GregorianCalendar calendar){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		if (calendar.get(GregorianCalendar.DAY_OF_WEEK) != GregorianCalendar.SATURDAY
				&& calendar.get(GregorianCalendar.DAY_OF_WEEK) != GregorianCalendar.SUNDAY){
			//平时
			return !getWeekdayIsHolidayList().contains(sdf.format(calendar.getTime()));
		}else{
			//周末
			return getWeekendIsWorkDateList().contains(sdf.format(calendar.getTime()));
		}
	}
	
	/**
	 * @title 获取周六和周日是工作日的情况(手工维护)
	 *    注意,日期必须写全:
	 *       2009-1-4必须写成:2009-01-04
	 * @author chanson
	 * @return 周末是工作日的列表
	 */
	public List getWeekendIsWorkDateList(){
		List list = new ArrayList();
		list.add("2009-01-04");
		list.add("2009-01-24");
		list.add("2009-02-01");
		list.add("2009-05-31");
		list.add("2009-09-27");
		list.add("2009-10-10");
		return list;
	}
	
	/**
	 * @title 获取周一到周五是假期的情况(手工维护)
	 *    注意,日期必须写全:
	 *       2009-1-4必须写成:2009-01-04
	 * @author chanson
	 * @return 平时是假期的列表
	 */
	public List getWeekdayIsHolidayList(){
		List list = new ArrayList();
		list.add("2009-01-29");
		list.add("2009-01-30");
		list.add("2009-04-06");
		list.add("2009-05-01");
		list.add("2009-05-28");
		list.add("2009-05-29");
		list.add("2009-10-01");
		list.add("2009-10-02");
		list.add("2009-10-05");
		list.add("2009-10-06");
		list.add("2009-10-07");
		list.add("2009-10-08");
		return list;
	}

	public static void main(String[] args) {

		WeekdayUtil dateUtils = new WeekdayUtil();
		boolean ok = dateUtils.compareWeekday("2009-10-1", "2009-10-15", 5);
		System.out.println("是否在五个工作日内:" + ok);
	}
}

   这个类相对来说写得就比较死了——太不遵循OCP原则了吧。

   有人说,把工作日配置在数据库中,而且还能根据一定的规律推算出假期来——很厉害,一次生成50年的工作日。但国家

的假期是会变的,比如取消5.1长假就是一个很典型的例子,总不至于每次都得改算法吧。搞不准过2年后,连10.1长假都

没了。

    相对来说,我觉得还是放在XML文件中配置比较灵活。那有人会怀疑说,每次都得访问XML会不会有效率问题。

当然,如果你项目中使用它非常频繁的话,那就把数据放在内存中吧。每次修改该XML文件的时候刷新内存就可以了。

 【改造】

1、引入XML

<?xml version="1.0" encoding="utf-8"?>
<root>
	<validation>
		<list>
			<!-- 非补报报文的交易时间必须在5个工作日内 -->
			<key>EXCH_DATE_CHECK</key>
			<value>5</value>
		</list>
		<list>
			<!-- 回执处理必须在5个工作日内 -->
			<key>REC_DATE_CHECK</key>
			<value>5</value>
		</list>
	</validation>
	<!-- 工作日是假期的情况 -->
	<weekday>
		<holiday_list>
			<date>2009-01-29</date>
			<date>2009-01-30</date>
			<date>2009-04-06</date>
			<date>2009-05-01</date>
			<date>2009-05-28</date>
			<date>2009-05-29</date>
			<date>2009-10-01</date>
			<date>2009-10-02</date>
			<date>2009-10-05</date>
			<date>2009-10-06</date>
			<date>2009-10-07</date>
			<date>2009-10-08</date>
		</holiday_list>
	</weekday>
	<!-- 周末是工作日的情况 -->
	<weekend>
		<weekday_list>
			<date>2009-01-04</date>
			<date>2009-01-24</date>
			<date>2009-02-01</date>
			<date>2009-05-31</date>
			<date>2009-09-27</date>
			<date>2009-10-10</date>
		</weekday_list>
	</weekend>
</root>

注:该XML文件放在src/config下。

2、增加解析XML的方法

public class Dom4JUtil {
	
	private final static String BASE_PATH = "/config/";
	
	public String getConfFile(String file) {
		URL confURL = getClass().getClassLoader().getResource(file);
		if (confURL == null)
			confURL = getClass().getClassLoader().getResource(
					"META-INF/" + file);
		if (confURL == null)
			confURL = Thread.currentThread().getContextClassLoader()
					.getResource(file);
		if (confURL == null) {
			System.err.println(" cann't find config file:-->" + file);
		} else {
			String filePath = confURL.getFile();
			filePath = filePath.replaceAll("%20", " ");
			File file1 = new File(filePath);
			if (file1.isFile())
				return filePath;
		}
		return null;
	}
	
	/**
	 * @title 获取工作日相关配置
	 * @author chanson
	 * @return
	 */
	public WeekdayVO getWeekdayConfig(){
		
		Map validateMap = new HashMap();
		List weekendIsWeekdayList = new ArrayList();
		List weekdayIsHolidayList = new ArrayList();
		
		//1、放到web工程
		File f = new File(getConfFile(BASE_PATH + "weekday.xml"));
		//2、application测试
		//String file  = "D:/workspace/test/src/config/weekday.xml";
		//File f = new File(file);
		SAXReader reader = new SAXReader();
		try{
			Document doc = reader.read(f);
			Element root = doc.getRootElement();
			
			//===================================
			//工作日校验相关属性
			//===================================
			Element validationElement = root.element("validation");
			Element listElement;
			for(Iterator i = validationElement.elementIterator("list");i.hasNext();){
				listElement = (Element)i.next();
				validateMap.put((String) listElement.elementText("key"), 
						(String)listElement.elementText("value"));
			}
			
			//===================================
			//工作日是假期的列表
			//===================================
			Element weekdayElement = root.element("weekday");
			Element holidayListElement = weekdayElement.element("holiday_list");
			Element holidayValueElement = null;
			for(Iterator i = holidayListElement.elementIterator("date");i.hasNext();){
				holidayValueElement = (Element)i.next();
				weekdayIsHolidayList.add((String)holidayValueElement.getText());
			}
			
			//===================================
			//周末是工作日的列表
			//===================================
			Element weekendElement = root.element("weekend");
			Element weekdayListElement = weekendElement.element("weekday_list");
			Element weekdayValueElement = null;
			for(Iterator i = weekdayListElement.elementIterator("date");i.hasNext();){
				weekdayValueElement = (Element)i.next();
				weekendIsWeekdayList.add((String)weekdayValueElement.getText());
			}
			
			WeekdayVO vo = new WeekdayVO();
			vo.setValidateMap(validateMap);
			vo.setWeekdayIsHolidayList(weekdayIsHolidayList);
			vo.setWeekendIsWeekdayList(weekendIsWeekdayList);
			return vo;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}
	
	public static void main(String[] args) {
		Dom4JUtil dom4JUtil = new Dom4JUtil();
		WeekdayVO vo = dom4JUtil.getWeekdayConfig();
		System.out.println(vo.getWeekdayIsHolidayList());
		System.out.println(vo.getWeekendIsWeekdayList());
	}
}

使用了一个POJO类:

public class WeekdayVO {

	private Map validateMap;//工作日校验
	private List weekendIsWeekdayList;//周末是工作日的列表
	private List weekdayIsHolidayList;//工作日是假期的列表

       //setter/getter(省略)
}

3、修改WeekUtil类中的方法

   1)、修改工作日判断方法:

public boolean isWeekday(GregorianCalendar calendar){
		Dom4JUtil dom4JUtil = new Dom4JUtil();
		WeekdayVO vo = dom4JUtil.getWeekdayConfig();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		if (calendar.get(GregorianCalendar.DAY_OF_WEEK) != GregorianCalendar.SATURDAY
				&& calendar.get(GregorianCalendar.DAY_OF_WEEK) != GregorianCalendar.SUNDAY){
			//平时
			return !vo.getWeekdayIsHolidayList().contains(sdf.format(calendar.getTime()));
		}else{
			//周末
			return vo.getWeekendIsWeekdayList().contains(sdf.format(calendar.getTime()));
		}
	}

 2)、修改调用方式:

	public static void main(String[] args) {
		
		Dom4JUtil dom4JUtil = new Dom4JUtil();
		Map validateMap = dom4JUtil.getWeekdayConfig().getValidateMap();
		String EXCH_DATE_CHECK = (String)validateMap.get("EXCH_DATE_CHECK");

		WeekdayUtil dateUtils = new WeekdayUtil();
		boolean ok = dateUtils.compareWeekday("2009-10-1", "2009-10-15", Integer.parseInt(EXCH_DATE_CHECK));
		System.out.println("是否在五个工作日内:" + ok);
	}

   改造完毕。

   更高级的改造

    对于我现在的项目来说,算是完成了。当然还可以改得更好一些:

1、扩展XML,区分每年的工作日。(对于某些统计分析的项目,可能会用得着)

2、添加可视化页面配置,避免了人工修改配置文件。

3、目前的XML文件中的日期格式有要求:

必须补全10位。例如:2008-1-1 必须配置成 2008-01-01。否则将匹配不上。

猜你喜欢

转载自blog.csdn.net/cysunc/article/details/83325346