java計(jì)算工作時(shí)間除去節(jié)假日以及雙休日
本文實(shí)例為大家分享了java計(jì)算工作時(shí)間的具體代碼,不包括節(jié)假日、雙休日,供大家參考,具體內(nèi)容如下
package common.util;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
public class CalculateHours {
SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); //這里的格式可以自己設(shè)置
//設(shè)置上班時(shí)間:該處時(shí)間可以根據(jù)實(shí)際情況進(jìn)行調(diào)整
int abh = 9;//上午上班時(shí)間,小時(shí)
int abm = 00;//上午上班時(shí)間,分鐘
int aeh = 12;//上午下班時(shí)間,小時(shí)
int aem = 0;//上午下班時(shí)間,分鐘
int pbh = 13;//下午上班時(shí)間,小時(shí)
int pbm = 00;//下午上班時(shí)間,分鐘
int peh = 18;//下午下班時(shí)間,小時(shí)
int pem = 0;//下午下班時(shí)間,分鐘
float h1 = abh+(float)abm/60;
float h2 = aeh+(float)aem/60;
float h3 = pbh+(float)pbm/60;
float h4 = peh+(float)pem/60;
float hoursPerDay = h2-h1+(h4-h3);//每天上班小時(shí)數(shù)
int daysPerWeek = 5;//每周工作天數(shù)
long milsecPerDay = 1000*60*60*24;//每天的毫秒數(shù)
float hoursPerWeek = hoursPerDay*daysPerWeek;//每星期小時(shí)數(shù)
public float calculateHours(String beginTime, String endTime){
//對(duì)輸入的字符串形式的時(shí)間進(jìn)行轉(zhuǎn)換
Date t1 = stringToDate(beginTime);//真實(shí)開(kāi)始時(shí)間
Date t2 = stringToDate(endTime);//真實(shí)結(jié)束時(shí)間
//對(duì)時(shí)間進(jìn)行預(yù)處理
t1 = processBeginTime(t1);
t2 = processEndTime(t2);
//若開(kāi)始時(shí)間晚于結(jié)束時(shí)間,返回0
if(t1.getTime()>t2.getTime()){
return 0;
}
//開(kāi)始時(shí)間到結(jié)束時(shí)間的完整星期數(shù)
int weekCount = (int) ((t2.getTime()-t1.getTime())/(milsecPerDay*7));
float totalHours = 0;
totalHours += weekCount * hoursPerWeek;
//調(diào)整結(jié)束時(shí)間,使開(kāi)始時(shí)間和結(jié)束時(shí)間在一個(gè)星期的周期之內(nèi)
t2.setTime(t2.getTime()-weekCount*7*milsecPerDay);
int dayCounts = 0;//記錄開(kāi)始時(shí)間和結(jié)束時(shí)間之間工作日天數(shù)
//調(diào)整開(kāi)始時(shí)間,使得開(kāi)始時(shí)間和結(jié)束時(shí)間在同一天,或者相鄰的工作日內(nèi)。
while(t1.getTime()<=t2.getTime()){
Date temp = new Date(t1.getTime()+milsecPerDay);
temp = processBeginTime(temp);
temp.setHours(t1.getHours());
temp.setMinutes(t1.getMinutes());
if(temp.getTime()>t2.getTime()){
break;
}else{
t1 = temp;
dayCounts++;
}
}
totalHours += dayCounts * hoursPerDay;
float hh1 = t1.getHours() + (float)t1.getMinutes()/60;
float hh2 = t2.getHours() + (float)t2.getMinutes()/60;
//處理開(kāi)始結(jié)束是同一天的情況
if(t1.getDay()==t2.getDay()){
float tt = 0;
tt = hh2 - hh1;
if(hh1>=h1&&hh1<=h2&&hh2>=h3){
tt = tt - (h3-h2);
}
totalHours += tt;
}else{
//處理開(kāi)始結(jié)束不是同一天的情況
float tt1 = h4 - hh1;
float tt2 = hh2 - h1;
if(hh1<=h2){
tt1 = tt1 - (h3-h2);
}
if(hh2>=h3){
tt2 = tt2 - (h3-h2);
}
totalHours += (tt1 + tt2);
}
return totalHours;
}
/**
* 格式化輸出時(shí)間: yyyy-mm-dd hh:mm:ss 星期x
* @param t
* @return
*/
private String printDate(Date t) {
String str;
String xingqi = null;
switch (t.getDay()) {
case 0:
xingqi = "星期天";
break;
case 1:
xingqi = "星期一";
break;
case 2:
xingqi = "星期二";
break;
case 3:
xingqi = "星期三";
break;
case 4:
xingqi = "星期四";
break;
case 5:
xingqi = "星期五";
break;
case 6:
xingqi = "星期六";
break;
default:
break;
}
str = format.format(t)+" "+xingqi;
return str;
}
/**
* 對(duì)結(jié)束時(shí)間進(jìn)行預(yù)處理,使其處于工作日內(nèi)的工作時(shí)間段內(nèi)
* @param t
* @return
*/
private Date processEndTime(Date t) {
float h = t.getHours() + (float)t.getMinutes()/60;
//若結(jié)束時(shí)間晚于下午下班時(shí)間,將其設(shè)置為下午下班時(shí)間
if(h>=h4){
t.setHours(peh);
t.setMinutes(pem);
}else {
//若結(jié)束時(shí)間介于中午休息時(shí)間,那么設(shè)置為上午下班時(shí)間
if(h>=h2&&h<=h3){
t.setHours(aeh);
t.setMinutes(aem);
}else{
//若結(jié)束時(shí)間早于上午上班時(shí)間,日期向前推一天,并將時(shí)間設(shè)置為下午下班時(shí)間
if(t.getHours()<=h1){
t.setTime(t.getTime()-milsecPerDay);
t.setHours(peh);
t.setMinutes(pem);
}
}
}
//若結(jié)束時(shí)間是周末,那么將結(jié)束時(shí)間向前推移到最近的工作日的下午下班時(shí)間
if(t.getDay()==0){
t.setTime(t.getTime()-milsecPerDay*(t.getDay()==6?1:2));
t.setHours(peh);
t.setMinutes(pem);
}
if(t.getDay()==6){
t.setTime(t.getTime()-milsecPerDay*(t.getDay()==6?1:2));
t.setHours(peh);
t.setMinutes(pem);
}
return t;
}
/**
* 對(duì)開(kāi)始時(shí)間進(jìn)行預(yù)處理
* @param t1
* @return
*/
private Date processBeginTime(Date t) {
float h = t.getHours() + (float)t.getMinutes()/60;
//若開(kāi)始時(shí)間晚于下午下班時(shí)間,將開(kāi)始時(shí)間向后推一天
if(h>=h4){
t.setTime(t.getTime()+milsecPerDay);
t.setHours(abh);
t.setMinutes(abm);
}else {
//若開(kāi)始時(shí)間介于中午休息時(shí)間,那么設(shè)置為下午上班時(shí)間
if(h>=h2&&h<=h3){
t.setHours(pbh);
t.setMinutes(pbm);
}else{
//若開(kāi)始時(shí)間早于上午上班時(shí)間,將hour設(shè)置為上午上班時(shí)間
if(t.getHours()<=h1){
t.setHours(abh);
t.setMinutes(abm);
}
}
}
//若開(kāi)始時(shí)間是周末,那么將開(kāi)始時(shí)間向后推移到最近的工作日的上午上班時(shí)間
if(t.getDay()==0){
t.setTime(t.getTime()+milsecPerDay*(t.getDay()==6?2:1));
t.setHours(abh);
t.setMinutes(abm);
}if(t.getDay()==6){
t.setTime(t.getTime()+milsecPerDay*(t.getDay()==6?2:1));
t.setHours(abh);
t.setMinutes(abm);
}
return t;
}
/**
* 將字符串形式的時(shí)間轉(zhuǎn)換成Date形式的時(shí)間
* @param time
* @return
*/
private Date stringToDate(String time){
try {
return format.parse(time);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
/**
* 去除周末節(jié)假日工作小時(shí)
* @param beginTime
* @param endTime
* @return
* @throws ParseException
*/
public static float CalculateHour(String beginTime,String endTime) throws ParseException{
CalculateHours ch = new CalculateHours();
float a=ch.calculateHours(beginTime, endTime);
Calendar startDay = Calendar.getInstance();
Calendar endDay = Calendar.getInstance();
startDay.setTime(FORMATTER.parse(beginTime));
endDay.setTime(FORMATTER.parse(endTime));
String[] workday=printDay(startDay, endDay);
String[] holiday = new String[]{"01-01","01-02","01-03","05-01","05-02","05-03","10-01","10-02",
"10-03","10-04","10-05","10-06","02-08","02-09","02-10"};
Calendar now = Calendar.getInstance();
int year=now.get(Calendar.YEAR); //獲取當(dāng)前年份
List<String> list = new ArrayList<String>();
for (String string : holiday) {
string=year+"-"+string;
list.add(string);
}
String[] arr = list.toArray(new String[0]);
int holidays = arrContrast(workday, arr);
int holidayHous=holidays*8;
float b = (float)(Math.round(a*10))/10;
float workHours=b-holidayHous;
return workHours;
}
public static void main(String[] args) throws ParseException {
String beginTime = "2018-6-1 9:00:00";
String endTime = "2018-6-4 10:10:00";
CalculateHours ch = new CalculateHours();
float b=ch.calculateHours(beginTime, endTime);
System.out.println(b);
float a=CalculateHours.CalculateHour(beginTime, endTime);
System.out.println(a);
}
/**
* 去除數(shù)組中相同日期
* @param arr1
* @param arr2
* @return
*/
private static int arrContrast(String[] arr1, String[] arr2){
int count=0;
List<String> list = new LinkedList<String>();
for (String str : arr1) { //處理第一個(gè)數(shù)組,list里面的值為1,2,3,4
if (!list.contains(str)) {
list.add(str);
}
}
for (String str : arr2) { //如果第二個(gè)數(shù)組存在和第一個(gè)數(shù)組相同的值,就刪除
if(list.contains(str)){
list.remove(str);
++count;
}
}
return count;
}
private static final DateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd");
private static String[] printDay(Calendar startDay, Calendar endDay) {
List<String> list = new ArrayList<String>();
// 給出的日期開(kāi)始日比終了日大則不執(zhí)行打印
if (startDay.compareTo(endDay) >= 0) {
return new String[]{};
}
// 現(xiàn)在打印中的日期
Calendar currentPrintDay = startDay;
while (true) {
// 日期加一
currentPrintDay.add(Calendar.DATE, 1);
// 日期加一后判斷是否達(dá)到終了日,達(dá)到則終止打印
if (currentPrintDay.compareTo(endDay) == 0) {
break;
}
list.add(FORMATTER.format(currentPrintDay.getTime()));
}
String[] arr = list.toArray(new String[0]);
return arr;
}
}
main方法中的執(zhí)行結(jié)果為:

代碼中都有注釋?zhuān)勺孕懈鶕?jù)需要進(jìn)行調(diào)節(jié)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java數(shù)據(jù)結(jié)構(gòu)之二叉排序樹(shù)的實(shí)現(xiàn)
二叉排序樹(shù)(Binary Sort Tree),又稱(chēng)二叉查找樹(shù)(Binary Search Tree),亦稱(chēng)二叉搜索樹(shù)。本文詳細(xì)介紹了二叉排序樹(shù)的原理,并且提供了Java代碼的完全實(shí)現(xiàn)。需要的可以參考一下2022-01-01
解決spring @ControllerAdvice處理異常無(wú)法正確匹配自定義異常
這篇文章主要介紹了解決spring @ControllerAdvice處理異常無(wú)法正確匹配自定義異常的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Java線(xiàn)程并發(fā)訪(fǎng)問(wèn)代碼分析
這篇文章主要介紹了Java線(xiàn)程并發(fā)訪(fǎng)問(wèn)代碼分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
淺析Java IO相關(guān)知識(shí)點(diǎn)
本篇文章給大家分享了關(guān)于java io的一些相關(guān)知識(shí)點(diǎn)以及相關(guān)內(nèi)容,對(duì)此有需要的朋友可以學(xué)習(xí)參考下。2018-05-05
java中的export方法實(shí)現(xiàn)導(dǎo)出excel文件
這篇文章主要介紹了java中的export方法實(shí)現(xiàn)導(dǎo)出excel文件,文章圍繞java導(dǎo)出excel文件的相關(guān)資料展開(kāi)詳細(xì)內(nèi)容,需要的小伙伴可以參考一下2022-03-03
SpringBoot Jpa分頁(yè)查詢(xún)配置方式解析
這篇文章主要介紹了SpringBoot Jpa分頁(yè)查詢(xún)配置方式解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
java實(shí)現(xiàn)多人聊天工具(socket+多線(xiàn)程)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)多人聊天工具,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
Java并發(fā)編程之顯示鎖ReentrantLock和ReadWriteLock讀寫(xiě)鎖
這篇文章主要介紹了Java并發(fā)編程之顯示鎖ReentrantLock和ReadWriteLock讀寫(xiě)鎖,本文講解了ReentrantLock概況、Lock接口、Lock使用、輪詢(xún)鎖的和定時(shí)鎖、公平性、可中斷獲鎖獲取操作等內(nèi)容,需要的朋友可以參考下2015-04-04

