java - restar - calcular tiempo entre dos fechas excel
Cálculo de fechas dadas dos fechas excluyendo el fin de semana (6)
Estoy usando Joda time api en un proyecto de Spring 3.0 para calcular las fechas. Ahora tengo una fecha de inicio y finalización y quiero tener todos los fines de semana de fin de semana o sábado o domingo entre estas dos fechas. Cómo puedo conseguir esto ?
Miré esta publicación Joda time - todos los lunes entre dos fechas . Ofreció alguna orientación, pero todavía es vaga como la forma de excluir dos fechas.
Puede usar el calendario gregoriano para recuperar el día de una fecha determinada. Si la cadena es sábado o domingo, puede descuidarla.
Supongo que tu pregunta es cómo
obtener todos los días excepto el fin de semana o el sábado o el domingo entre dos fechas.
Solución :
public static void main(String[] args) {
final LocalDate start = LocalDate.now();
final LocalDate end = new LocalDate(2012, 1, 14);
LocalDate weekday = start;
if (start.getDayOfWeek() == DateTimeConstants.SATURDAY ||
start.getDayOfWeek() == DateTimeConstants.SUNDAY) {
weekday = weekday.plusWeeks(1).withDayOfWeek(DateTimeConstants.MONDAY);
}
while (weekday.isBefore(end)) {
System.out.println(weekday);
if (weekday.getDayOfWeek() == DateTimeConstants.FRIDAY)
weekday = weekday.plusDays(3);
else
weekday = weekday.plusDays(1);
}
}
Soy nuevo aqui. He estado buscando una solución a este problema y no he usado un bucle pero no he encontrado un algoritmo adecuado. Así que decidí crear esta solución que no utiliza bucle, es muy eficiente y el código ha sido probado.
public int betweenDaysIgnoreWeekends(DateTime startDate, DateTime endDate) {
//Um numero que representa o dia da semana para a data final, exemplo segunda=1, terça=2, quarta=3...
int dayOfWeekEndDateNumber = Integer.valueOf(endDate.dayOfWeek()
.getAsString());
//Um numero que representa o dia da semana para a data inicial, exemplo segunda=1, terça=2, quarta=3...
int dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek()
.getAsString());
//Se a data final for sabado ou domingo, finja ser sexta-feira
if (dayOfWeekEndDateNumber == 6 || dayOfWeekEndDateNumber == 7) {
int DaysToAdd = 8 - dayOfWeekEndDateNumber;
endDate = endDate.plusDays(DaysToAdd);
dayOfWeekEndDateNumber = Integer.valueOf(endDate.dayOfWeek()
.getAsString());
}
//Se a data inicial for sabado ou domingo, finja ser segunda-feira
if (dayOfWeekStartDateNumber == 6 || dayOfWeekStartDateNumber == 7) {
int DaysToAdd = 8 - dayOfWeekStartDateNumber;
startDate = startDate.plusDays(DaysToAdd);
dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek()
.getAsString());
}
//Quantos dias se passaram contando os fins de semana
int days = Days.daysBetween(startDate, endDate).getDays();
//Quantas semanas se passaram exatamente
int weeks = days / 7;
//O excesso de dias que sobrou, exemplo: 1 semana e 3 dias o excess=3 e weeks=1
int excess = days % 7;
//Se a data inicial for igual a data final, passou 0 dia
if (startDate.equals(endDate)) {
return 0;
} else {
//O excesso de dias passou pelo fim de semana, então deve-se retirar 2 dias
//da quantidade final de dias
if (excess + dayOfWeekStartDateNumber >= 6) {
//Quantidade de semanas * 5 dias uteis + o excesso de dias - o final de semana que o excesso atravessou
return weeks * 5 + excess - 2;
}
//Quantidade de semanas * 5 dias uteis + o excesso de dias
return weeks * 5 + excess;
}
}
Esto devolverá la fecha de finalización excluyendo los fines de semana
public static Date addDaysBySkipWeekend(Date startDate, int numDays) {
Calendar dateCal = Calendar.getInstance();
dateCal.setTime(startDate);
for (int i = 0; i < numDays-1; i++) {
dateCal.add(dateCal.DATE, 1);
if(dateCal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY
|| dateCal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY ){
dateCal.add(dateCal.DATE, 1);
i--;
}
}
return dateCal.getTime();
}
Para mejorar lo que @ samir-machado-de-oliveira publicó, aquí hay una función que calculará los días sin fines de semana sin usar un bucle. No comparé esto con la versión en bucle, pero parece que sería más rápido:
/**
* Gets number of days between two dates. Ignoring weekends.
* @param startDate
* @param endDate
* @return
*/
public static int getDaysBetweenIgnoreWeekends(DateTime startDate, DateTime endDate) {
// If the start date is equal to the closing date, spent 0 days
if (startDate.equals(endDate))
return 0;
// A number that represents the day for the start date, Monday = 1 , Tuesday = 2 , Wednesday = 3 ...
int dayOfWeekStartDateNumber = startDate.getDayOfWeek();
// If the starting date is Saturday or Sunday , pretend to be Monday
if (dayOfWeekStartDateNumber == 6 || dayOfWeekStartDateNumber == 7) {
int DaysToAdd = 8 - dayOfWeekStartDateNumber;
startDate = startDate.plusDays(DaysToAdd);
dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek().getAsString());
}
// How many days have passed counting weekends
int days = Days.daysBetween(startDate, endDate).getDays();
// How many weeks have passed
int weeks = days / 7;
// Excess days left. E.g. one week and three days the excess will be 3
int excess = days % 7;
// Excess of days spent for the weekend , then it must be removed two days
// the final number of days
if (excess + dayOfWeekStartDateNumber >= 6) {
// Week count * 5 working days + excess days - the weekend that excess crossed
return weeks * 5 + excess - 2;
}
// Weeks count * 5 working days + excess days
return weeks * 5 + excess;
}
Además, aquí hay una versión que le permitirá ignorar la hora del día, de modo que si la fecha de inicio es a las 11AM en la hora de inicio y la hora de finalización es el día siguiente a las 10AM, se mostrará como 1 día en lugar de 0 dias.
/**
* Gets number of days between two dates. Ignoring weekends. Ignores Hours.
* @param startDate
* @param endDate
* @return
*/
public static int getDaysBetweenIgnoreWeekends(DateTime startDate, DateTime endDate) {
return getDaysBetweenIgnoreWeekends(startDate,endDate,true);
}
/**
* Gets number of days between two dates. Ignoring weekends.
* @param startDate
* @param endDate
* @param ignoreTimeOfDay
* @return
*/
public static int getDaysBetweenIgnoreWeekends(DateTime startDate, DateTime endDate, boolean ignoreTimeOfDay) {
// If the start date is equal to the closing date, spent 0 days
if (startDate.equals(endDate))
return 0;
if (ignoreTimeOfDay && startDate.toLocalDate().equals(endDate.toLocalDate()))
return 0;
// A number that represents the day for the start date, Monday = 1 , Tuesday = 2 , Wednesday = 3 ...
int dayOfWeekStartDateNumber = startDate.getDayOfWeek();
// If the starting date is Saturday or Sunday , pretend to be Monday
if (dayOfWeekStartDateNumber == 6 || dayOfWeekStartDateNumber == 7) {
int DaysToAdd = 8 - dayOfWeekStartDateNumber;
startDate = startDate.plusDays(DaysToAdd);
dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek().getAsString());
}
// How many days have passed counting weekends
int days;
if(ignoreTimeOfDay) {
days = Days.daysBetween(startDate.toLocalDate(), endDate.toLocalDate()).getDays();
} else {
days = Days.daysBetween(startDate, endDate).getDays();
}
// How many weeks have passed
int weeks = days / 7;
// Excess days left. E.g. one week and three days the excess will be 3
int excess = days % 7;
// Excess of days spent for the weekend , then it must be removed two days
// the final number of days
if (excess + dayOfWeekStartDateNumber >= 6) {
// Week count * 5 working days + excess days - the weekend that excess crossed
return weeks * 5 + excess - 2;
}
// Weeks count * 5 working days + excess days
return weeks * 5 + excess;
}
He estado utilizando la lógica de @Josh Maag durante casi un año pero recientemente descubrí que devuelve un valor incorrecto cuando endDate cae un sábado.
Aquí está la versión que me gustaría compartir que considera restar días de endDate cuando es sábado o domingo.
public static int getDaysBetweenIgnoreWeekends(org.joda.time.DateTime startDate, org.joda.time.DateTime endDate, boolean ignoreTimeOfDay) {
// If the start date is equal to the closing date, spent 0 days
if (startDate.equals(endDate))
return 0;
if (ignoreTimeOfDay && startDate.toLocalDate().equals(endDate.toLocalDate()))
return 0;
// A number that represents the day for the start date, Monday = 1 , Tuesday = 2 , Wednesday = 3 ...
int dayOfWeekStartDateNumber = startDate.getDayOfWeek();
int dayOfWeekEndDateNumber = endDate.getDayOfWeek();
// If the starting date is Saturday or Sunday , pretend to be Monday
if (dayOfWeekStartDateNumber == 6 || dayOfWeekStartDateNumber == 7) {
int DaysToAdd = 8 - dayOfWeekStartDateNumber;
startDate = startDate.plusDays(DaysToAdd);
dayOfWeekStartDateNumber = Integer.valueOf(startDate.dayOfWeek().getAsString());
}
org.joda.time.DateTime effectiveEndDate = endDate;
if (dayOfWeekEndDateNumber == 6 || dayOfWeekEndDateNumber == 7) {
effectiveEndDate = endDate.minusDays(Math.abs(5 - dayOfWeekEndDateNumber));
}
// How many days have passed counting weekends
int days;
if(ignoreTimeOfDay) {
days = org.joda.time.Days.daysBetween(startDate.toLocalDate(), effectiveEndDate.toLocalDate()).getDays();
} else {
days = org.joda.time.Days.daysBetween(startDate, effectiveEndDate).getDays();
}
// How many weeks have passed
int weeks = days / 7;
// Excess days left. E.g. one week and three days the excess will be 3
int excess = days % 7;
// Excess of days spent for the weekend , then it must be removed two days
// the final number of days
if (excess + dayOfWeekStartDateNumber >= 6) {
// Week count * 5 working days + excess days - the weekend that excess crossed
return weeks * 5 + excess - 2;
}
// Weeks count * 5 working days + excess days
return weeks * 5 + excess;
}
En la versión anterior, el fragmento siguiente restaba un día adicional. Restando -2 no importa si endDate fue un sábado o domingo.
if (excess + dayOfWeekStartDateNumber >= 6) {
// Week count * 5 working days + excess days - the weekend that excess crossed
return weeks * 5 + excess - 2;
}
¡Espero que ayude!