I want to add certain number of hours to date, ignoring the weekends
For example,
(Friday 18:00) + 48 = (Tuseday 18:00) (Saturday and Sunday are ignored)
I would strongly recommend using JodaTime
(or DateTime
of Java8) for this, since the old Date/Calendar API is pretty useless.
public DateTime getEndtime(final DateTime startdate, final int hours) {
final DateTime endOfWeek = endOfWeek(startdate);
final Duration restOfWeek = new Duration(startdate, endOfWeek);
final Duration hoursDuration = toDuration(hours);
if (restOfWeek.isLongerThan(hoursDuration)) {
return startdate.plus(hoursDuration);
} else {
final Duration durationForNextWeek = hoursDuration.minus(restOfWeek);
return startOfWeek(startdate).plus(durationForNextWeek);
}
}
//Converts number of hours as int to Duration
private Duration toDuration(final int hours) {
return new Duration(hours * 60 * 60 * 1000);
}
//Returns coming friday, 1 millisecond to midnight
private DateTime endOfWeek(final DateTime dateTime) {
DateTime copy = dateTime;
while (copy.getDayOfWeek() != 6) {
copy = copy.plusDays(1);
}
return copy.toDateMidnight().toDateTime().minusMillis(1);
}
//Returns the following monday at midnight
//If dateTime is on a monday, the next monday will be chosen
private DateTime startOfWeek(final DateTime dateTime) {
DateTime copy = dateTime.plusDays(1);
while (copy.getDayOfWeek() != 1) {
copy = copy.plusDays(1);
}
return copy.toDateMidnight().toDateTime();
}
Explanation of the code:
This code NOT support tasks stretching over multiple weeks, but it's a start that you can modify to support this.. Might be some edge cases that aren't handled as well, I'll leave it to you to test it thoroughly.
Add hours in steps not bigger then 24hours. And check after each step if you end up on a saturday or sunday. In each case add another 24hours. That should do what you want.
public Date getTaskEndTime(Calendar startDate, int hours){
while (hours > 0){
int step = 0;
if(hours > 24) step = 24;
else step = hours;
hours -= step;
startDate.add(Calendar.HOUR_OF_DAY, step);
int dayOfWeek = startDate.get(Calendar.DAY_OF_WEEK);
if(dayOfWeek == Calendar.SATURDAY) hours += 24;
if(dayOfWeek == Calendar.SUNDAY) hours += 24;
}
return startDate.getTime();
}
Below code does solve the purpose.
public static Date addBusinessHours(Calendar startDate, int hours, int workingHourStart, int workingHourEnd){
System.out.println("Entering: Date Time " + startDate.getTime() + " | Remaining Hours: "+ hours + " | Working hours ("+workingHourStart+"-"+workingHourEnd+")");
if(hours == 0){
return startDate.getTime();
}
int hourOfDay = startDate.get(Calendar.HOUR_OF_DAY);
if(startDate.get(Calendar.MINUTE) > 0){
hourOfDay = hourOfDay +1;
}
int dayOfWeek = startDate.get(Calendar.DAY_OF_WEEK);
if(dayOfWeek == Calendar.SATURDAY){
startDate.add(Calendar.DATE, 2);
startDate.set(Calendar.HOUR_OF_DAY, workingHourStart);
startDate.set(Calendar.MINUTE, 0);
startDate.set(Calendar.SECOND, 0);
addBusinessHours(startDate, hours, workingHourStart, workingHourEnd);
}
if(dayOfWeek == Calendar.SUNDAY){
startDate.add(Calendar.DATE, 1);
startDate.set(Calendar.HOUR_OF_DAY, workingHourStart);
startDate.set(Calendar.MINUTE, 0);
startDate.set(Calendar.SECOND, 0);
addBusinessHours(startDate, hours, workingHourStart, workingHourEnd);
}
if(dayOfWeek != Calendar.SATURDAY && dayOfWeek != Calendar.SUNDAY){
if(hourOfDay < workingHourStart){
startDate.set(Calendar.HOUR_OF_DAY, workingHourStart);
startDate.set(Calendar.MINUTE, 0);
startDate.set(Calendar.SECOND, 0);
hourOfDay = startDate.get(Calendar.HOUR_OF_DAY);
dayOfWeek = startDate.get(Calendar.DAY_OF_WEEK);
addBusinessHours(startDate, hours, workingHourStart, workingHourEnd);
}
else if(hourOfDay >= workingHourEnd){
startDate.add(Calendar.DATE, 1);
startDate.set(Calendar.HOUR_OF_DAY, workingHourStart);
startDate.set(Calendar.MINUTE, 0);
startDate.set(Calendar.SECOND, 0);
hourOfDay = startDate.get(Calendar.HOUR_OF_DAY);
dayOfWeek = startDate.get(Calendar.DAY_OF_WEEK);
addBusinessHours(startDate, hours, workingHourStart, workingHourEnd);
}
else if(hourOfDay >= workingHourStart && hourOfDay < workingHourEnd){
if(hours+hourOfDay <= workingHourEnd){
startDate.add(Calendar.HOUR_OF_DAY, hours);
return startDate.getTime();
}else{
//System.out.println("¤¤" + startDate.getTime() );
startDate.add(Calendar.DATE, 1);
//System.out.println("¤¤" + startDate.getTime() );
startDate.set(Calendar.HOUR_OF_DAY, workingHourStart);
startDate.set(Calendar.MINUTE, 0);
startDate.set(Calendar.SECOND, 0);
//System.out.println("¤¤" + startDate.getTime() );
System.out.println("##"+hours+ "##"+ workingHourEnd + "##" + hourOfDay);
int remaining_hours = hours - (workingHourEnd - hourOfDay);
addBusinessHours(startDate, remaining_hours, workingHourStart, workingHourEnd);
}
}
}
return startDate.getTime();
}
you need to handle it in custom way:
public Date getTaskEndTime(Calendar startDate, int hours) {
Calendar endTime = Calendar.getInstance();
endTime.setTime(startDate.getTime());
endTime.add(Calendar.HOUR, hours); // add 2 for saturday and sunday
int dayOfWeek = endTime.get(Calendar.DAY_OF_WEEK);
if (dayOfWeek == Calendar.SATURDAY) {
endTime.add(Calendar.DATE, 2); // add 2 for saturday and sunday
} else if (dayOfWeek == Calendar.SATURDAY) {
endTime.add(Calendar.DATE, 1); // add 1 for sunday
}
return endTime.getTime();
}
Basically what you need to do is to first calculate how many hours that remain of the week (this is the difference between current time and 24:00@Fri). If the number of hours are less than that you just add.
Otherwise you subtract that amount from the hours and then if the remainder is more than 120h (one week) you take the integer quotient and skips that many weeks. Finally you add the remainder to 00:00@Mon that week.
In your example you have between your start and 24:00@Fri 6h, that's less than 48h so you subtract 6h from it and get 42h. Now 42h is less than 120h so you don't skip weeks then you add 42h to 00:00@Mon by which you arrive at 18:00@Tue.
Please refer the below code, see if that helps you.
public static Date getTaskEndTime(Date startDate, int hours) {
// calculate the end time by adding the hours ignoring the weekends
Calendar endCal = Calendar.getInstance();
endCal.setTime(startDate);
for (int i = 0; i < hours; hours = hours - 8) {
if (!(endCal.get(Calendar.DAY_OF_WEEK) == 1 || endCal.get(Calendar.DAY_OF_WEEK) == 7)) {
endCal.add(Calendar.DAY_OF_MONTH, 1);
} else {
endCal.add(Calendar.DAY_OF_MONTH, 1);
hours = hours + 8;
}
}
return endCal.getTime();
}