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

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

耦合性较强的代码:

Java代码 复制代码 收藏代码
  1. public class WeekdayUtil {
  2. /**
  3. * @title 判断两个日期是否在指定工作日内
  4. * @detail (只计算周六和周日)
  5. * 例如:前时间2008-12-05,后时间2008-12-11
  6. * @author chanson
  7. * @param beforeDate 前时间
  8. * @param afterDate 后时间
  9. * @param deadline 最多相隔时间
  10. * @return 是的话,返回true,否则返回false
  11. */
  12. public boolean compareWeekday(String beforeDate, String afterDate, int deadline) {
  13. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  14. try {
  15. Date d1 = sdf.parse(beforeDate);
  16. Date d2 = sdf.parse(afterDate);
  17. //工作日
  18. int workDay = 0;
  19. GregorianCalendar gc = new GregorianCalendar();
  20. gc.setTime(d1);
  21. // 两个日期相差的天数
  22. long time = d2.getTime() - d1.getTime();
  23. long day = time / 3600000 / 24 + 1;
  24. if(day < 0){
  25. //如果前日期大于后日期,将返回false
  26. return false;
  27. }
  28. for (int i = 0; i < day; i++) {
  29. if(isWeekday(gc)){
  30. workDay++;
  31. // System.out.println(gc.getTime());
  32. }
  33. //往后加1天
  34. gc.add(GregorianCalendar.DATE, 1);
  35. }
  36. return workDay <= deadline;
  37. } catch (Exception e) {
  38. e.printStackTrace();
  39. return false;
  40. }
  41. }
  42. /**
  43. * @title 判断是否为工作日
  44. * @detail 工作日计算:
  45. * 1、正常工作日,并且为非假期
  46. * 2、周末被调整成工作日
  47. * @author chanson
  48. * @param date 日期
  49. * @return 是工作日返回true,非工作日返回false
  50. */
  51. public boolean isWeekday(GregorianCalendar calendar){
  52. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  53. if (calendar.get(GregorianCalendar.DAY_OF_WEEK) != GregorianCalendar.SATURDAY
  54. && calendar.get(GregorianCalendar.DAY_OF_WEEK) != GregorianCalendar.SUNDAY){
  55. //平时
  56. return !getWeekdayIsHolidayList().contains(sdf.format(calendar.getTime()));
  57. }else{
  58. //周末
  59. return getWeekendIsWorkDateList().contains(sdf.format(calendar.getTime()));
  60. }
  61. }
  62. /**
  63. * @title 获取周六和周日是工作日的情况(手工维护)
  64. * 注意,日期必须写全:
  65. * 2009-1-4必须写成:2009-01-04
  66. * @author chanson
  67. * @return 周末是工作日的列表
  68. */
  69. public List getWeekendIsWorkDateList(){
  70. List list = new ArrayList();
  71. list.add("2009-01-04");
  72. list.add("2009-01-24");
  73. list.add("2009-02-01");
  74. list.add("2009-05-31");
  75. list.add("2009-09-27");
  76. list.add("2009-10-10");
  77. return list;
  78. }
  79. /**
  80. * @title 获取周一到周五是假期的情况(手工维护)
  81. * 注意,日期必须写全:
  82. * 2009-1-4必须写成:2009-01-04
  83. * @author chanson
  84. * @return 平时是假期的列表
  85. */
  86. public List getWeekdayIsHolidayList(){
  87. List list = new ArrayList();
  88. list.add("2009-01-29");
  89. list.add("2009-01-30");
  90. list.add("2009-04-06");
  91. list.add("2009-05-01");
  92. list.add("2009-05-28");
  93. list.add("2009-05-29");
  94. list.add("2009-10-01");
  95. list.add("2009-10-02");
  96. list.add("2009-10-05");
  97. list.add("2009-10-06");
  98. list.add("2009-10-07");
  99. list.add("2009-10-08");
  100. return list;
  101. }
  102. public static void main(String[] args) {
  103. WeekdayUtil dateUtils = new WeekdayUtil();
  104. boolean ok = dateUtils.compareWeekday("2009-10-1", "2009-10-15", 5);
  105. System.out.println("是否在五个工作日内:" + ok);
  106. }
  107. }
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

Java代码 复制代码 收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <root>
  3. <validation>
  4. <list>
  5. <!-- 非补报报文的交易时间必须在5个工作日内 -->
  6. <key>EXCH_DATE_CHECK</key>
  7. <value>5</value>
  8. </list>
  9. <list>
  10. <!-- 回执处理必须在5个工作日内 -->
  11. <key>REC_DATE_CHECK</key>
  12. <value>5</value>
  13. </list>
  14. </validation>
  15. <!-- 工作日是假期的情况 -->
  16. <weekday>
  17. <holiday_list>
  18. <date>2009-01-29</date>
  19. <date>2009-01-30</date>
  20. <date>2009-04-06</date>
  21. <date>2009-05-01</date>
  22. <date>2009-05-28</date>
  23. <date>2009-05-29</date>
  24. <date>2009-10-01</date>
  25. <date>2009-10-02</date>
  26. <date>2009-10-05</date>
  27. <date>2009-10-06</date>
  28. <date>2009-10-07</date>
  29. <date>2009-10-08</date>
  30. </holiday_list>
  31. </weekday>
  32. <!-- 周末是工作日的情况 -->
  33. <weekend>
  34. <weekday_list>
  35. <date>2009-01-04</date>
  36. <date>2009-01-24</date>
  37. <date>2009-02-01</date>
  38. <date>2009-05-31</date>
  39. <date>2009-09-27</date>
  40. <date>2009-10-10</date>
  41. </weekday_list>
  42. </weekend>
  43. </root>
<?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的方法

Java代码 复制代码 收藏代码
  1. public class Dom4JUtil {
  2. private final static String BASE_PATH = "/config/";
  3. public String getConfFile(String file) {
  4. URL confURL = getClass().getClassLoader().getResource(file);
  5. if (confURL == null)
  6. confURL = getClass().getClassLoader().getResource(
  7. "META-INF/" + file);
  8. if (confURL == null)
  9. confURL = Thread.currentThread().getContextClassLoader()
  10. .getResource(file);
  11. if (confURL == null) {
  12. System.err.println(" cann't find config file:-->" + file);
  13. } else {
  14. String filePath = confURL.getFile();
  15. filePath = filePath.replaceAll("%20", " ");
  16. File file1 = new File(filePath);
  17. if (file1.isFile())
  18. return filePath;
  19. }
  20. return null;
  21. }
  22. /**
  23. * @title 获取工作日相关配置
  24. * @author chanson
  25. * @return
  26. */
  27. public WeekdayVO getWeekdayConfig(){
  28. Map validateMap = new HashMap();
  29. List weekendIsWeekdayList = new ArrayList();
  30. List weekdayIsHolidayList = new ArrayList();
  31. //1、放到web工程
  32. File f = new File(getConfFile(BASE_PATH + "weekday.xml"));
  33. //2、application测试
  34. //String file = "D:/workspace/test/src/config/weekday.xml";
  35. //File f = new File(file);
  36. SAXReader reader = new SAXReader();
  37. try{
  38. Document doc = reader.read(f);
  39. Element root = doc.getRootElement();
  40. //===================================
  41. //工作日校验相关属性
  42. //===================================
  43. Element validationElement = root.element("validation");
  44. Element listElement;
  45. for(Iterator i = validationElement.elementIterator("list");i.hasNext();){
  46. listElement = (Element)i.next();
  47. validateMap.put((String) listElement.elementText("key"),
  48. (String)listElement.elementText("value"));
  49. }
  50. //===================================
  51. //工作日是假期的列表
  52. //===================================
  53. Element weekdayElement = root.element("weekday");
  54. Element holidayListElement = weekdayElement.element("holiday_list");
  55. Element holidayValueElement = null;
  56. for(Iterator i = holidayListElement.elementIterator("date");i.hasNext();){
  57. holidayValueElement = (Element)i.next();
  58. weekdayIsHolidayList.add((String)holidayValueElement.getText());
  59. }
  60. //===================================
  61. //周末是工作日的列表
  62. //===================================
  63. Element weekendElement = root.element("weekend");
  64. Element weekdayListElement = weekendElement.element("weekday_list");
  65. Element weekdayValueElement = null;
  66. for(Iterator i = weekdayListElement.elementIterator("date");i.hasNext();){
  67. weekdayValueElement = (Element)i.next();
  68. weekendIsWeekdayList.add((String)weekdayValueElement.getText());
  69. }
  70. WeekdayVO vo = new WeekdayVO();
  71. vo.setValidateMap(validateMap);
  72. vo.setWeekdayIsHolidayList(weekdayIsHolidayList);
  73. vo.setWeekendIsWeekdayList(weekendIsWeekdayList);
  74. return vo;
  75. }catch(Exception e){
  76. e.printStackTrace();
  77. return null;
  78. }
  79. }
  80. public static void main(String[] args) {
  81. Dom4JUtil dom4JUtil = new Dom4JUtil();
  82. WeekdayVO vo = dom4JUtil.getWeekdayConfig();
  83. System.out.println(vo.getWeekdayIsHolidayList());
  84. System.out.println(vo.getWeekendIsWeekdayList());
  85. }
  86. }
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类:

Java代码 复制代码 收藏代码
  1. public class WeekdayVO {
  2. private Map validateMap;//工作日校验
  3. private List weekendIsWeekdayList;//周末是工作日的列表
  4. private List weekdayIsHolidayList;//工作日是假期的列表
  5. //setter/getter(省略)
  6. }
public class WeekdayVO {

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

       //setter/getter(省略)
}

3、修改WeekUtil类中的方法

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

Java代码 复制代码 收藏代码
  1. public boolean isWeekday(GregorianCalendar calendar){
  2. Dom4JUtil dom4JUtil = new Dom4JUtil();
  3. WeekdayVO vo = dom4JUtil.getWeekdayConfig();
  4. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  5. if (calendar.get(GregorianCalendar.DAY_OF_WEEK) != GregorianCalendar.SATURDAY
  6. && calendar.get(GregorianCalendar.DAY_OF_WEEK) != GregorianCalendar.SUNDAY){
  7. //平时
  8. return !vo.getWeekdayIsHolidayList().contains(sdf.format(calendar.getTime()));
  9. }else{
  10. //周末
  11. return vo.getWeekendIsWeekdayList().contains(sdf.format(calendar.getTime()));
  12. }
  13. }
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)、修改调用方式:

Java代码 复制代码 收藏代码
  1. public static void main(String[] args) {
  2. Dom4JUtil dom4JUtil = new Dom4JUtil();
  3. Map validateMap = dom4JUtil.getWeekdayConfig().getValidateMap();
  4. String EXCH_DATE_CHECK = (String)validateMap.get("EXCH_DATE_CHECK");
  5. WeekdayUtil dateUtils = new WeekdayUtil();
  6. boolean ok = dateUtils.compareWeekday("2009-10-1", "2009-10-15", Integer.parseInt(EXCH_DATE_CHECK));
  7. System.out.println("是否在五个工作日内:" + ok);
  8. }
	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。否则将匹配不上。