支持节假日及调休的工作日历实现
支持节假日及调休的工作日历实现
最近产品及项目中要用到工作日历, 找了一下发现jBPM的工作日历BusinessCalendar可用, 但缺少对节假日调休的支持, 通过简单改造实现了节假日调休和中文配置
主要修改如下:
1\ 在假日维护中增加一个加班或调休的定义维护
public class Holiday{public static List parseOvertimes(Properties calendarProperties,BusinessCalendar businessCalendar) {List overtimes = new ArrayList();DateFormat dateFormat = new SimpleDateFormat(calendarProperties.getProperty("day.format"));Iterator iter = calendarProperties.keySet().iterator();while (iter.hasNext()) {String key = (String) iter.next();if (key.startsWith("overtime")) {Holiday holiday = new Holiday(calendarProperties.getProperty(key), dateFormat,businessCalendar);overtimes.add(holiday);}}return overtimes;}}public class BusinessCalendar{ public Day findDay(Date date) {Calendar calendar = getCalendar();calendar.setTime(date);Day day = weekDays[calendar.get(Calendar.DAY_OF_WEEK)];//当某天无工作时间时检查是否有加班或调休if(day==null || day.dayParts==null || day.dayParts.length==0){if(isOvertime(date)){day = weekDayCommon;}}return day;}}public class BusinessCalendar{ /** * 工作日历计算 * @param date 初始时间 * @param field 时间单位,同Calendar * @param amount 时间数量 * @return 按工作日历计算后时间 */public Date add(Date date, int field, int amount){return add(date, field, amount, true);}public Date add(Date date, int field, int amount, boolean isBusinessTime){Date end = null;if (isBusinessTime) {DayPart dayPart = findDayPart(date);boolean isInbusinessHours = (dayPart != null);if (!isInbusinessHours) {Object[] result = new Object[2];findDay(date).findNextDayPartStart(0, date, result);date = (Date) result[0];dayPart = (DayPart) result[1];}end = dayPart.add(date, field, amount);} else {Calendar calendar = getCalendar();calendar.setTime(date);calendar.add(field, amount);end = calendar.getTime();}return end;}}public class DayPart{ public Duration(String duration) {if (duration == null)throw new NullPointerException("duration is null");int separatorIndex = -1;String quantityText = null;String unitText = null;//检查空格 for english formateseparatorIndex = duration.indexOf(' ');if (separatorIndex>1){quantityText = duration.substring(0, separatorIndex).trim().toLowerCase();unitText = duration.substring(separatorIndex + 1).trim().toLowerCase();if (unitText.startsWith("business")) {isBusinessTime = true;}}//检查中文"工作"if(separatorIndex<=0){separatorIndex = duration.indexOf("工作");if(separatorIndex>0){isBusinessTime = true;quantityText = duration.substring(0, separatorIndex).trim().toLowerCase();unitText = duration.substring(separatorIndex + 2).trim().toLowerCase();}}//逐字符检查if(separatorIndex<=0){for(int i=0; i<duration.length(); i++){char ch = duration.charAt(i);if((48<=ch && ch<=57) || ch==46){continue;}//第一个非数字和.quantityText = duration.substring(0, i).trim().toLowerCase();unitText = duration.substring(i).trim().toLowerCase();}if(quantityText==null){quantityText = duration;}if(unitText==null || "".equals(unitText)){unitText = "H";}}double amount = Double.parseDouble(quantityText);Long unit = (Long) units.get(unitText);this.milliseconds = (long) (amount * unit.longValue());} static {units = new HashMap();units.put("second", new Long(SECOND));units.put("seconds", new Long(SECOND));units.put("秒", new Long(SECOND));units.put("S", new Long(SECOND));units.put("s", new Long(SECOND));units.put("business second", new Long(SECOND));units.put("business seconds", new Long(SECOND));units.put("minute", new Long(MINUTE));units.put("minutes", new Long(MINUTE));units.put("分钟", new Long(MINUTE));units.put("Min", new Long(MINUTE));units.put("min", new Long(MINUTE));units.put("business minute", new Long(MINUTE));units.put("business minutes", new Long(MINUTE));units.put("hour", new Long(HOUR));units.put("hours", new Long(HOUR));units.put("小时", new Long(HOUR));units.put("时", new Long(HOUR));units.put("H", new Long(HOUR));units.put("h", new Long(HOUR));units.put("business hour", new Long(HOUR));units.put("business hours", new Long(HOUR));units.put("day", new Long(DAY));units.put("days", new Long(DAY));units.put("天", new Long(DAY));units.put("日", new Long(DAY));units.put("D", new Long(DAY));units.put("d", new Long(DAY));units.put("business day", new Long(BUSINESS_DAY));units.put("business days", new Long(BUSINESS_DAY));units.put("week", new Long(WEEK));units.put("weeks", new Long(WEEK));units.put("星期", new Long(WEEK));units.put("周", new Long(WEEK));units.put("W", new Long(WEEK));units.put("w", new Long(WEEK));units.put("business week", new Long(BUSINESS_WEEK));units.put("business weeks", new Long(BUSINESS_WEEK));units.put("month", new Long(MONTH));units.put("months", new Long(MONTH));units.put("月", new Long(MONTH));units.put("M", new Long(MONTH));units.put("m", new Long(MONTH));units.put("business month", new Long(BUSINESS_MONTH));units.put("business months", new Long(BUSINESS_MONTH));units.put("year", new Long(YEAR));units.put("years", new Long(YEAR));units.put("年", new Long(YEAR));units.put("Y", new Long(YEAR));units.put("y", new Long(YEAR));units.put("business year", new Long(BUSINESS_YEAR));units.put("business years", new Long(BUSINESS_YEAR));}}## 工作日及工作时间定义hour.format=HH:mm #weekday ::= [<daypart> [& <daypart>]*] #daypart ::= <start-hour>-<to-hour> #start-hour and to-hour must be in the hour.format #dayparts have to be ordered weekday.common=9:00-12:00 & 12:30-17:00 #通用工作时间, 周末调休会用到weekday.monday=9:00-12:00 & 12:30-17:00 weekday.thuesday=9:00-12:00 & 12:30-17:00weekday.wednesday=9:00-12:00 & 12:30-17:00weekday.thursday=9:00-12:00 & 12:30-17:00weekday.friday=9:00-12:00 & 12:30-17:00weekday.saturday=weekday.sunday=## 节假日及加班调休定义day.format=yyyy/MM/dd# holiday syntax: <holiday> # holiday period syntax: <start-day>-<end-day> # below are the belgian official holidays #元旦 holiday.1=2012/01/01-2012/01/03#春节 holiday.2=2012/01/22-2012/01/28overtime.2=2012/01/21overtime.2a=2012/01/29#清明holiday.3=2012/04/02-2012/04/04overtime.3=2012/03/31-2012/04/01#五一holiday.4=2012/04/29-2012/05/01overtime.4=2012/04/28#端午 holiday.5=2012/06/22-2012/06/24 #中秋 holiday.6=2012/09/30#国庆holiday.7=2012/10/01-2012/10/07overtime.7=2012/09/29## 其他参数定义 business.day.expressed.in.hours=8business.week.expressed.in.hours=40business.month.expressed.in.business.days=21business.year.expressed.in.business.days=220