对于工作日处理相对来说还是比较简单的,不外乎就是周末判断和假期判断。
不过,有些人会把它们写死在类里面,看以下代码:
耦合性较强的代码:
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。否则将匹配不上。