packagecom.utouu.uphone.commons;importjava.text.ParseException;importjava.text.SimpleDateFormat;importjava.util.ArrayList;importjava.util.Calendar;importjava.util.Date;importjava.util.Iterator;importjava.util.List;importorg.springframework.stereotype.Component;/*** 获取工作日
*
创建日期:2016年7月21日
* Copyright 2016 UTOUU All Rights Reserved
*@authorzhushuangshuang
*@since1.0
*@version1.0*/@Componentpublic classGetWorkDay {/*** 获取两个时间之内的工作日时间(只去掉两个日期之间的周末时间,法定节假日未去掉)
*
*@paramstart
* -起始时间,共有3个重载方法,可以传入long型,Long型,与Date型
*@paramend
* -结束时间,共有3个重载方法,可以传入long型,Long型,与Date型
*@returnLong型时间差对象*/
/*public static void main(String[] args) {
GetWorkDay g=new GetWorkDay();
List initHoliday;
try {
initHoliday = g.initHoliday();
double days = g.getWorkdayTimeInMillisExcWeekendHolidays("2016-06-30 17-12-53","2016-08-30 11-27-50","yyyy-MM-dd HH-mm-ss",initHoliday);
double formateToDay = g.formateToDay(days);
String formatDuring = g.formatDuring(days);
System.out.println(formateToDay);
System.out.println(formatDuring);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
private double getWorkdayTimeInMillis(long start, longend,
ListlistHolidays) {//如果起始时间大于结束时间,将二者交换
if (start >end) {long temp =start;
start=end;
end=temp;
}//根据参数获取起始时间与结束时间的日历类型对象
Calendar sdate =Calendar.getInstance();
Calendar edate=Calendar.getInstance();
sdate.setTimeInMillis(start);
edate.setTimeInMillis(end);//计算指定时间段内法定节假日天数的毫秒数
long holidays = 0;if (listHolidays != null) {
holidays=getHolidaysInMillis(start, end, listHolidays);
listHolidays.clear();
}//如果两个时间在同一周并且都不是周末日期,则直接返回时间差,增加执行效率
if ((sdate.get(Calendar.YEAR) ==edate.get(Calendar.YEAR))&& (sdate.get(Calendar.WEEK_OF_YEAR) ==edate
.get(Calendar.WEEK_OF_YEAR))&& (sdate.get(Calendar.DAY_OF_WEEK) != 1 &&sdate
.get(Calendar.DAY_OF_WEEK)!= 7)&& (edate.get(Calendar.DAY_OF_WEEK) != 1 &&edate
.get(Calendar.DAY_OF_WEEK)!= 7)) {return new Long(end - start -holidays);
}//如果两个时间在同一周并且都是周末日期,则直接返回0
if ((sdate.get(Calendar.YEAR) ==edate.get(Calendar.YEAR))&& (sdate.get(Calendar.WEEK_OF_YEAR) ==edate
.get(Calendar.WEEK_OF_YEAR)-1)&& (sdate.get(Calendar.DAY_OF_WEEK) == 1
|| sdate.get(Calendar.DAY_OF_WEEK) == 7)&&(edate.get(Calendar.DAY_OF_WEEK)== 1
|| edate.get(Calendar.DAY_OF_WEEK) == 7)) {
start=validateStartTime(sdate);
end=validateEndTime(edate);long result=end - start -holidays;return new Long(result>0?result:0);
}
start=validateStartTime(sdate);
end=validateEndTime(edate);//首先取得起始日期与结束日期的下个周一的日期
Calendar snextM =getNextMonday(sdate);
Calendar enextM=getNextMonday(edate);//获取这两个周一之间的实际天数
int days =getDaysBetween(snextM, enextM);//获取这两个周一之间的工作日数(两个周一之间的天数肯定能被7整除,并且工作日数量占其中的5/7)
int workdays = days / 7 * 5;//计算最终结果,具体为:workdays加上开始时间的时间偏移量,减去结束时间的时间偏移量
double a=(double)workdays*24*3600000;double result = (a + calcWorkdayTimeInMillis(sdate, edate, start, end) -holidays);return result > 0 ? result : 0;
}/***
* 验证开始日期是否合法,如果不合法,并返回修复后的正确日期毫秒数
*@paramsdate
*@return
*/
private longvalidateStartTime(Calendar sdate){if(sdate.get(Calendar.DAY_OF_WEEK) == 1)//开始日期从周日开始,如果开始时间为周末,自动修复为下周的9:00开始
{
sdate.add(Calendar.DATE,1);
sdate.setTimeInMillis(sdate.getTime().getTime()- //从9点开始
(((sdate.get(Calendar.HOUR_OF_DAY)-9) * 3600000)+ (sdate.get(Calendar.MINUTE) * 60000)+ (sdate.get(Calendar.SECOND) * 1000)));
}else if(sdate.get(Calendar.DAY_OF_WEEK) == 7){//开始日期从周六开始
sdate.add(Calendar.DATE,2);
sdate.setTimeInMillis(
sdate.getTime().getTime()- //从9点开始,如果开始时间为周末,自动修复为下周的9:00开始
(((sdate.get(Calendar.HOUR_OF_DAY)-9) * 3600000)+ (sdate.get(Calendar.MINUTE) * 60000)+ (sdate.get(Calendar.SECOND) * 1000)));
}returnsdate.getTimeInMillis();
}/***
* 验证结束日期是否合法,如果不合法,并返回修复后的正确日期毫秒数
*@paramsdate
*@return
*/
private longvalidateEndTime(Calendar edate)
{if(edate.get(Calendar.DAY_OF_WEEK) == 1)//结束日期是周日,如果结束日期是周六、周末自动修复为这周五18:00
{
edate.add(Calendar.DATE,-2);
edate.setTimeInMillis(
edate.getTime().getTime()+(18*3600000-((edate.get(Calendar.HOUR_OF_DAY) * 3600000)+ (edate.get(Calendar.MINUTE) * 60000)+ (edate.get(Calendar.SECOND) * 1000))));
}else if(edate.get(Calendar.DAY_OF_WEEK) == 7){//结束日期是周六,如果结束日期是周六、周末自动修复为这周五18:00
edate.add(Calendar.DATE,-1);
edate.setTimeInMillis(
edate.getTime().getTime()+(18*3600000-((edate.get(Calendar.HOUR_OF_DAY) * 3600000)+ (edate.get(Calendar.MINUTE) * 60000)+ (edate.get(Calendar.SECOND) * 1000))));}returnedate.getTimeInMillis();
}/***
* 计算两个日期间的工作日天数,除周六日
*
*@paramsdate
*@paramedate
*@return
*/
private long calcWorkdayTimeInMillis(Calendar sdate, Calendar edate,long start, longend) {//获取开始时间的偏移量
long scharge = 0;if (sdate.get(Calendar.DAY_OF_WEEK) != 1
&& sdate.get(Calendar.DAY_OF_WEEK) != 7) {//只有在开始时间为非周末的时候才计算偏移量
scharge += (sdate.get(Calendar.HOUR_OF_DAY) * 3600000);
scharge+= (sdate.get(Calendar.MINUTE) * 60000);
scharge+= (sdate.get(Calendar.SECOND) * 1000);
scharge= ((24 * 3600000) -scharge);
scharge+= ((sdate.getTime().getTime() - start) - (3 * 24 * 3600000));
}//(24*3600000=86400000)-((9*3600000+1800000)=34200000)+(3*24*3600000=259200000)-(2*24*3600000)=//86400000-34200000=52200000//获取结束时间的偏移量
long echarge = 0;if (edate.get(Calendar.DAY_OF_WEEK) != 1
&& edate.get(Calendar.DAY_OF_WEEK) != (7)) {//只有在结束时间为非周末的时候才计算偏移量
echarge += (edate.get(Calendar.HOUR_OF_DAY) * 3600000);
echarge+= (edate.get(Calendar.MINUTE) * 60000);
echarge+= (edate.get(Calendar.SECOND) * 1000);
echarge= ((24 * 3600000) -echarge);
echarge+= (edate.getTime().getTime() - end) - (24 * 3600000);
echarge-= (2 * 24 * 3600000);
}//(24*3600000=86400000)-(18*3600000=64800000)+(24*3=259200000)
if (scharge < 0 || echarge < 0)
scharge= echarge = 0;return scharge -echarge;
}/*** 获取两个时间之内的工作日时间(只去掉两个日期之间的周末时间,法定节假日未去掉)
*
*@paramstart
* -起始时间,共有3个重载方法,可以传入long型,Long型,与Date型
*@paramend
* -结束时间,共有3个重载方法,可以传入long型,Long型,与Date型
*@returnLong型时间差对象*/
public double getWorkdayTimeInMillisExcWeekend(long start, longend) {returngetWorkdayTimeInMillis(start, end);
}/***
* 获取两个时间之内的工作日时间(去掉两个日期之间的周末时间,法定节假日时间)
*
*@paramstart
*@paramend
*@return
*/
public double getWorkdayTimeInMillisExcWeekendHolidays(String start,String end, String format, ListlistHolidays) {
SimpleDateFormat sdf= newSimpleDateFormat(format);
Date sdate;
Date edate;try{
sdate=sdf.parse(start);
edate=sdf.parse(end);returngetWorkdayTimeInMillis(sdate.getTime(), edate.getTime(),
listHolidays);
}catch(ParseException e) {
e.printStackTrace();return new Long(0);
}
}public doublegetWorkdayTimeInMillis(Long start, Long end) {return getWorkdayTimeInMillis(start.longValue(), end.longValue(), null);
}public doublegetWorkdayTimeInMillis(Date start, Date end) {return getWorkdayTimeInMillis(start.getTime(), end.getTime(), null);
}public doublegetWorkdayTimeInMillis(String start, String end, String format) {
SimpleDateFormat sdf= newSimpleDateFormat(format);
Date sdate;
Date edate;try{
sdate=sdf.parse(start);
edate=sdf.parse(end);returngetWorkdayTimeInMillis(sdate, edate);
}catch(ParseException e) {
e.printStackTrace();return new Long(0);
}
}private long getHolidaysInMillis(long start, longend,
ListlistHolidays) {
Calendar scalendar=Calendar.getInstance();
Calendar ecalendar=Calendar.getInstance();int daysofH = 0;try{
scalendar.setTimeInMillis(start);
ecalendar.setTimeInMillis(end);if (listHolidays == null)return new Long(0);
Iterator iterator =listHolidays.iterator();while(iterator.hasNext()) {
Calendar ca=Calendar.getInstance();
Date hdate=iterator.next();
ca.setTime(hdate);if (ca.after(scalendar) &&ca.before(ecalendar)) {
daysofH= daysofH + 1;
}else if (ca.getTimeInMillis() ==scalendar.getTimeInMillis()) {
daysofH= daysofH + 1;
}else if (ca.getTimeInMillis() ==ecalendar.getTimeInMillis()) {
daysofH= daysofH + 1;
}
}
}catch(Exception e) {
e.printStackTrace();return new Long(0);
}return daysofH * 24 * 3600000;
}privateCalendar getNextMonday(Calendar cal) {int addnum = 9 -cal.get(Calendar.DAY_OF_WEEK);if (addnum == 8)
addnum= 1;//周日的情况
cal.add(Calendar.DATE, addnum);returncal;
}/***
*@parammss
*@param要转换的毫秒数
*@return该毫秒数转换为 * days * hours * minutes * seconds 后的格式*/
public String formatDuring(doublemss) {long days = (long) (mss / (1000 * 60 * 60 * 24));long hours = (long) ((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));long minutes = (long) ((mss % (1000 * 60 * 60)) / (1000 * 60));long seconds = (long) ((mss % (1000 * 60)) / 1000);return days + " days " + hours + " hours " + minutes + " minutes "
+ seconds + " seconds ";
}/*** 获取两个日期之间的实际天数,支持跨年
*@paramstart
*@paramend
**/
/*** 获得两个日期之间的工作日
*@since1.0
*@parammss
*@return* 作者:@authorzhushunagshuang
*
创建时间:2016年7月21日 下午3:12:23*/
public double formateToDay(doublemss){double days = mss / (1000 * 60 * 60 * 24);returndays;
}public intgetDaysBetween(Calendar start, Calendar end) {if(start.after(end)) {
Calendar swap=start;
start=end;
end=swap;
}int days = end.get(Calendar.DAY_OF_YEAR)-start.get(Calendar.DAY_OF_YEAR);int y2 =end.get(Calendar.YEAR);if (start.get(Calendar.YEAR) !=y2) {
start=(Calendar) start.clone();do{
days+=start.getActualMaximum(Calendar.DAY_OF_YEAR);
start.add(Calendar.YEAR,1);
}while (start.get(Calendar.YEAR) !=y2);
}returndays;
}/*** 手动维护2016年的节假日
*@since1.0
*@return*@throwsParseException
* 作者:@authorzhushunagshuang
*
创建时间:2016年7月21日 下午5:12:08*/
public List initHoliday() throwsParseException{
List holidays = new ArrayList();
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd");//元旦
holidays.add(sdf.parse("2016-01-01"));
holidays.add(sdf.parse("2016-01-02"));
holidays.add(sdf.parse("2016-01-03"));//春节
holidays.add(sdf.parse("2016-02-07"));
holidays.add(sdf.parse("2016-02-08"));
holidays.add(sdf.parse("2016-02-09"));
holidays.add(sdf.parse("2016-02-10"));
holidays.add(sdf.parse("2016-02-11"));
holidays.add(sdf.parse("2016-02-12"));
holidays.add(sdf.parse("2016-02-13"));//清明节
holidays.add(sdf.parse("2016-04-02"));
holidays.add(sdf.parse("2016-04-03"));
holidays.add(sdf.parse("2016-04-04"));//劳动节
holidays.add(sdf.parse("2016-04-30"));
holidays.add(sdf.parse("2016-05-01"));
holidays.add(sdf.parse("2016-05-02"));//端午节
holidays.add(sdf.parse("2016-06-09"));
holidays.add(sdf.parse("2016-06-10"));
holidays.add(sdf.parse("2016-06-11"));//中秋节
holidays.add(sdf.parse("2016-09-15"));
holidays.add(sdf.parse("2016-09-16"));
holidays.add(sdf.parse("2016-09-17"));//国庆节
holidays.add(sdf.parse("2016-10-01"));
holidays.add(sdf.parse("2016-10-02"));
holidays.add(sdf.parse("2016-10-03"));
holidays.add(sdf.parse("2016-10-04"));
holidays.add(sdf.parse("2016-10-05"));
holidays.add(sdf.parse("2016-10-06"));
holidays.add(sdf.parse("2016-10-07"));returnholidays;
}
}