Olá… então… consegui resolver o problema… não sei se resolve em todos os casos… mas em todos que eu testei, está ok…
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;
}