前言
工作日的计算是一个大的问题, 要考虑假期, 而且每年的假期也不一样。假期完还有工作日调休等。
所以必须要将假期存储在硬盘上的数据(数据库或xml)。
然后计算时间差。
比如, 2018年5月11日星期五, 需要过3个工作日, 那么就是2018年5月16日星期三。
假期的获取
假期每年都是不一样的, 所以
- 通过人工查看政策文件手动写入硬盘, 如节假日安排
- 通过
Api
定时任务Quartz
进行获取, 如聚合数据Api
以xml形式存储
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| <xml> <holidays> <day value="2018-01-01" desc="元旦"/> <day value="2018-02-15" desc="春节"/> <day value="2018-02-16" desc="春节"/> <day value="2018-02-17" desc="春节"/> <day value="2018-02-18" desc="春节"/> <day value="2018-02-19" desc="春节"/> <day value="2018-02-20" desc="春节"/> <day value="2018-02-21" desc="春节"/> <day value="2018-04-05" desc="清明节"/> <day value="2018-04-06" desc="清明节"/> <day value="2018-04-07" desc="清明节"/> <day value="2018-04-29" desc="劳动节"/> <day value="2018-04-30" desc="劳动节"/> <day value="2018-05-01" desc="劳动节"/> <day value="2018-06-16" desc="端午节"/> <day value="2018-06-17" desc="端午节"/> <day value="2018-06-18" desc="端午节"/> <day value="2018-09-22" desc="中秋节"/> <day value="2018-09-23" desc="中秋节"/> <day value="2018-09-24" desc="中秋节"/> <day value="2018-10-01" desc="国庆节"/> <day value="2018-10-02" desc="国庆节"/> <day value="2018-10-03" desc="国庆节"/> <day value="2018-10-04" desc="国庆节"/> <day value="2018-10-05" desc="国庆节"/> <day value="2018-10-06" desc="国庆节"/> <day value="2018-10-07" desc="国庆节"/> </holidays> <workingdays> <day value="2018-02-11" desc="调休成为工作日"/> <day value="2018-02-24" desc="调休成为工作日"/> <day value="2018-04-08" desc="调休成为工作日"/> <day value="2018-04-28" desc="调休成为工作日"/> <day value="2018-09-29" desc="调休成为工作日"/> <day value="2018-09-30" desc="调休成为工作日"/> </workingdays> </xml>
|
以数据库形式存储
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| id day desc 1 2018-01-01 元旦 2 2018-02-15 春节 3 2018-02-16 春节 4 2018-02-17 春节 5 2018-02-18 春节 6 2018-02-19 春节 7 2018-02-20 春节 8 2018-02-21 春节 9 2018-04-05 清明节 10 2018-04-06 清明节 11 2018-04-07 清明节 12 2018-04-29 劳动节 13 2018-04-30 劳动节 14 2018-05-01 劳动节 15 2018-06-16 端午节 16 2018-06-17 端午节 17 2018-06-18 端午节 18 2018-09-22 中秋节 19 2018-09-23 中秋节 20 2018-09-24 中秋节 21 2018-10-01 国庆节 22 2018-10-02 国庆节 23 2018-10-03 国庆节 24 2018-10-04 国庆节 25 2018-10-05 国庆节 26 2018-10-06 国庆节 27 2018-10-07 国庆节 28 2018-02-11 调休成为工作日 29 2018-02-24 调休成为工作日 30 2018-04-08 调休成为工作日 31 2018-04-28 调休成为工作日 32 2018-09-29 调休成为工作日 33 2018-09-30 调休成为工作日
|
计算工作日的时间差
代码逻辑都写在注释中了。
其中, holidaysMap<年月日, 节假日名称>
和workingdaysMap<年月日, 调休>
两个Map
集合读取的数据, 来源于上述的数据集合。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| import org.apache.commons.lang3.time.DurationFormatUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory;
public class WorkDateHelper { private static final Logger logger = LoggerFactory.getLogger(WorkDateHelper.class); private static final int DAY_TIME = 24 * 60 * 60 * 1000; private static final SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyy-MM-dd");
public static long workTimeDiff(Date preDate, Date nextDate){ Calendar calendar = Calendar.getInstance();
long preTime = preDate.getTime(), nextTime = nextDate.getTime(); if(preTime > nextTime){ logger.error("前一个日期"+yyyyMMdd.format(preDate)+"不能大于后一个日期"+yyyyMMdd.format(nextDate)); return -1; }
long timeDiff = 0; calendar.setTimeInMillis(preTime); calendar.add(Calendar.DATE, 1); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0);
if(isWorkDate(preTime)) { timeDiff += calendar.getTimeInMillis() - preTime; } preTime = calendar.getTimeInMillis();
calendar.setTimeInMillis(nextTime); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0);
if(isWorkDate(nextTime)) { timeDiff += nextTime - calendar.getTimeInMillis(); } nextTime = calendar.getTimeInMillis();
while(preTime < nextTime) { if(isWorkDate(preTime)) { timeDiff += DAY_TIME; } preTime += DAY_TIME;
}
return timeDiff; }
public static boolean isWorkDate(long time){ String day = yyyyMMdd.format(new Date(time));
if(holidaysMap.containsKey(day)){ return false; }
if(workingdaysMap.containsKey(day)){ return true; }
Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(time); int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); if(dayOfWeek == Calendar.SUNDAY || dayOfWeek == Calendar.SATURDAY){ return false; }
return true; } }
|