1. 程式人生 > >工作日處理工具類(包括工作日判斷和工作日區間判斷)

工作日處理工具類(包括工作日判斷和工作日區間判斷)

 

對於工作日處理相對來說還是比較簡單的,不外乎就是週末判斷和假期判斷。

 

不過,有些人會把它們寫死在類裡面,看以下程式碼:

 

耦合性較強的程式碼:

 

 

 

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。否則將匹配不上。