Próxima data

1 resposta
J

Olá,

Tenho que fazer um algoritmo que faça o seguinte:
Ele recebe de entrada:
ano
mes
dia
hora
minuto
dia da semana
Qualquer um desses parâmetros podem ser nulos.

Bom, o que o algoritmo deve fazer é o seguinte, procurar a primeira data (próxima data) que satisfaça todos esses critérios. Eu fiz um algoritmo, mas ele está muito complexo e cheio de falhas.

Um exemplo:
Agora são 6/7/2006 14:12 Quinta

Se eu passar pro algoritmo dia 29 de fevereiro, num domingo ele deve me retornar:
29/2/2032 00:00 Domingo

Se eu passar pro algoritmo 10 minutos:
6/7/2006 15:10 Quinta

Será que conseguir me expressar???

Idéias de como fazer isso sem ser força bruta???

Abraços

1 Resposta

J

Olá… então… consegui resolver o problema… não sei se resolve em todos os casos… mas em todos que eu testei, está ok…

Código C#:

public static DateTime CalcularDataProximaExecucao(object ano, object mes, object dia, object hora, object minuto, object diaDaSemana) {
	DateTime data = DateTime.Now;
	data = new DateTime(data.Year, data.Month, data.Day, data.Hour, data.Minute, 0);
	int anoI, mesI, diaI, horaI, minutoI;

	DayOfWeek diaDaSemanaI = data.DayOfWeek;
	// Se informou o dia da semana, descobre
	if (diaDaSemana != null) {
		switch (((int) diaDaSemana)) {
			case 0:
				diaDaSemanaI = DayOfWeek.Sunday;
				break;
			case 1:
				diaDaSemanaI = DayOfWeek.Monday;
				break;
			case 2:
				diaDaSemanaI = DayOfWeek.Tuesday;
				break;
			case 3:
				diaDaSemanaI = DayOfWeek.Wednesday;
				break;
			case 4:
				diaDaSemanaI = DayOfWeek.Thursday;
				break;
			case 5:
				diaDaSemanaI = DayOfWeek.Friday;
				break;
			case 6:
				diaDaSemanaI = DayOfWeek.Saturday;
				break;
		}
	}

	// Se não informou o ano, usa o atual, caso contrário utiliza o informado
	if (ano == null) {
		anoI = data.Year;
	} else {
		anoI = (int) ano;

		// Se o ano informado menor que o ano atual, erro
		if (anoI < data.Year) {
			return DateTime.MaxValue;
		}
	}

	// Se não informou o mês
	if (mes == null) {
		// E se o ano informado for o atual
		if (anoI == data.Year) {
			// Usa o mês atual
			mesI = data.Month;
		} else {
			// Caso informou um ano diferente do atual, usa o primeiro mês
			mesI = 1;
		}
	} else {
		// Se informou, utiliza o informado
		mesI = (int) mes;

		// Se um ano foi informado, e o mês informado for menor que o atual, erro
		if (ano != null && anoI == data.Year && mesI < data.Month) {
			return DateTime.MaxValue;
		}
	}

	// Se não informou o dia
	if (dia == null) {
		// E se o ano informado for o atual e o mês atual for o atual
		if (anoI == data.Year && mesI == data.Month) {
			// Usa o dia atual
			diaI = data.Day;
		} else {
			// Caso informou um ano diferente do atual ou um mês diferente do atual, usa o primeiro dia
			diaI = 1;
		}
	} else {
		// Se informou, utiliza o informado
		diaI = (int) dia;

		// Se um ano e um mês foram informados, e o dia informado for menor que o atual, erro
		if (ano != null && anoI == data.Year && mes != null && mesI == data.Month && diaI < data.Day) {
			return DateTime.MaxValue;
		}
	}

	// Se não informou a hora
	if (hora == null) {
		// E se o ano informado for o atual e o mês informado for o atual e o dia informado for o atual
		if (anoI == data.Year && mesI == data.Month && diaI == data.Day && diaDaSemanaI == data.DayOfWeek) {
			horaI = data.Hour;
		} else {
			// Caso informou um ano diferente do atual ou um mês diferente do atual ou um dia diferente do atual, usa a primeiro hora
			horaI = 0;
		}
	} else {
		// Se informou, utiliza o informado
		horaI = (int) hora;

		// Se um ano, um mês e um dia foram informados, e a hora informada for menor que o atual, erro
		if (ano != null && anoI == data.Year && mes != null && mesI == data.Month && dia != null && diaI == data.Day && horaI < data.Hour) {
			return DateTime.MaxValue;
		}
	}

	// Se não informou os minutos
	if (minuto == null) {
		// E se o ano informado for o atual e o mês informado for o atual e o dia informado for o atual e a hora informada for a atual
		// E se a hora informada for a atual
		if (anoI == data.Year && mesI == data.Month && diaI == data.Day && diaDaSemanaI == data.DayOfWeek && horaI == data.Hour) {
			// Usa os minutos atuais
			minutoI = data.Minute;
		} else {
			// Caso informou um ano diferente do atual ou um mês diferente do atual ou um dia diferente do atual ou horas diferente da atual, usa a primeiro hora
			minutoI = 0;
		}
	} else {
		// Se informou, utiliza o informado
		minutoI = (int) minuto;

		// Se um ano, um mês, um dia e uma hora foram informados, e os minutos informados forem menores que o atual, erro
		if (ano != null && anoI == data.Year && mes != null && mesI == data.Month && dia != null && diaI == data.Day && hora != null && horaI == data.Hour && minutoI < data.Minute) {
			return DateTime.MaxValue;
		}
	}

	// Verifica se o mês é valido
	if (mes != null && (mesI < 1 || mesI > 12)) {
		return DateTime.MaxValue;
	}

	// Verifica se o dia é válido
	if (dia != null && (diaI < 1 || diaI > 31)) {
		return DateTime.MaxValue;
	}

	// Verifica se a hora é válida
	if (hora != null && (horaI < 0 || horaI > 23)) {
		return DateTime.MaxValue;
	}

	// Verifica se os minutos são válidos
	if (minuto != null && (minutoI < 0 || minutoI > 59)) {
		return DateTime.MaxValue;
	}

	// Se foi informado uma data e um dia da semana, e essa data não é esse dia da semana, erro
	if (ano != null && mes != null && dia != null && diaDaSemana != null) {
		if (new DateTime(anoI, mesI, diaI).DayOfWeek != diaDaSemanaI) {
			return DateTime.MaxValue;
		}
	}

	// Se foi informado um mês e um dia, verifica se o intervalo de dias é válido
	if (mes != null && dia != null) {
		// Fevereiro
		if (mesI == 2 && diaI > 29) {
			return DateTime.MaxValue;
		}

		// Meses com até 30 dias
		if (mesI <= 7 && mesI % 2 == 0 && diaI > 30) {
			return DateTime.MaxValue;
		}
	}

	DateTime dataRetorno = DateTime.MinValue;;
	bool somarMes, somarAno, somarHora;


	// Se for o dia de hoje, procura a hora correta
	if (anoI == data.Year && mesI == data.Month && diaI == data.Day && diaDaSemanaI == data.DayOfWeek) {
		do {
			try {
				dataRetorno = new DateTime(anoI, mesI, diaI, horaI, minutoI, 0);
			} catch {
				dataRetorno = DateTime.MinValue;
			}

			somarHora = false;

			if (minuto == null) {
				minutoI++;

				if (minutoI >= 60) {
					minutoI = 0;
					somarHora = true;
				}
			} else {
				somarHora = true;
			}

			if (hora == null && somarHora) {
				horaI++;

				if (horaI >= 24) {
					dataRetorno = DateTime.MaxValue;
				}
			} else if (somarHora) {
				dataRetorno = DateTime.MaxValue;
			}
		} while (dataRetorno.CompareTo(data) <= 0);

		if (dataRetorno != DateTime.MaxValue) {
			return dataRetorno;
		}
	}

	if (dataRetorno == DateTime.MaxValue) {
		dataRetorno = new DateTime(anoI, mesI, diaI).AddDays(1);

		anoI = dataRetorno.Year;
		mesI = dataRetorno.Month;
		diaI = dataRetorno.Day;
	}


	if (hora == null) {
		horaI = 0;
	}
	if (minuto == null) {
		minutoI = 0;
	}

	do {
		somarMes = somarAno = false;

		try {
			dataRetorno = new DateTime(anoI, mesI, diaI, horaI, minutoI, 0);
		} catch {
			dataRetorno = DateTime.MinValue;
		}

		if (dia == null) {
			diaI++;

			if (diaI >= 32) {
				diaI = 1;
				somarMes = true;
			}
		} else {
			somarMes = true;
		}

		if (mes == null && somarMes) {
			mesI++;

			if (mesI >= 13) {
				mesI = 1;
				somarAno = true;
			}
		} else {
			somarAno = true;
		}

		// Se neste passo é para somar ano e mês
		if (somarAno && somarMes) {
			// Se não foi informado o ano
			if (ano == null) {
				// Soma
				anoI++;
			}

			if (ano != null && mes != null && dia != null && dataRetorno == DateTime.MinValue) {
				return DateTime.MaxValue;
			}
		}
	} while (dataRetorno.CompareTo(data) <= 0 || (diaDaSemana != null && dataRetorno.DayOfWeek != diaDaSemanaI));

	return dataRetorno;
}

Abraços…

Criado 6 de julho de 2006
Ultima resposta 6 de jul. de 2006
Respostas 1
Participantes 1