Caso não haja quinta semana o compromisso é salvo na quarta semana.
O que você quer é achar o ultimo dia da semana do mês! É mais simples você pegar o ultimo dia do mês, depois o decrementar os dias até achar o dia da semana. Não tem que se preocupar com quantas semanas o mês tem.
Nesse caso acho que está tudo bem desde que a empresa esteja preparada para possivelmente trabalhar dobrado em alguns dias da quarta semana, para atender aos clientes da própria quarta semana e também aos da quinta!!
De qualquer maneira segue uma implementação básica do que você precisa: Trazer a n-ésima ocorrência do dia da semana dentro do mês, com o tratamento especial de buscar a última ocorrência existente (4a semana) sempre que o dia desejado cair fora do mês (5a semana).
O código mostra que é possível fazer isso sem loops. Ele está bastante extenso porque está detalhado, mas dá para diminuir bem resumindo os cálculos (dá para juntar até em uma única fórmula se quiser); isso fica de lição de casa, junto com outras coisas como: validação de parâmetros, uso de enums para representar os dias e semanas.
public static void main(String[] args) {
// Teste: retorna a quinta terça-feira de março de 2013
Date dt = enesimoDiaDaSemana(Calendar.MARCH, 2013, Calendar.TUESDAY, 5);
System.out.println(dt);
}
/**
* Retorna a data correspondente à n-ésima ocorrência de um dia da semana dentro do mês.
* Ao solicitar quinta semana, se o dia não existir será retornada a data correspondente
* na quarta semana.
*
* @param mes
* @param ano
* @param diaSemana O dia da semana desejado (1=Domingo .... 7=Sábado)
* @param semanaDoMes De 1 (primeira semana) a 5 (quinta semana)
* @return
*/
private static Date enesimoDiaDaSemana(int mes, int ano, int diaSemana, int semanaDoMes) {
Calendar cal = Calendar.getInstance();
// Ajusta no primeiro dia no mes selecionado.
cal.set(Calendar.MONTH, mes);
cal.set(Calendar.YEAR, ano);
cal.set(Calendar.DAY_OF_MONTH, 1);
// Vai até a primeira ocorrência do dia da semana, dentro daquele mês
int primeiroDiaDoMes = cal.get(Calendar.DAY_OF_WEEK);
int ajustePrimeiraOcorrencia;
if (primeiroDiaDoMes <= diaSemana) {
ajustePrimeiraOcorrencia = diaSemana - primeiroDiaDoMes;
} else {
ajustePrimeiraOcorrencia = 7 + diaSemana - primeiroDiaDoMes;
}
cal.add(Calendar.DAY_OF_MONTH, ajustePrimeiraOcorrencia);
// Quantos dias restam no mes após a primeira ocorrencia?
// (vamos precisar dessa informação para saber se as consultas na quinta semana
// não vão ultrapassar o fim do mês)
int diasRestantes = cal.getActualMaximum(Calendar.DAY_OF_MONTH) - cal.get(Calendar.DAY_OF_MONTH);
// Quantos dias será necessário adiantar até chegar na n-ésima ocorrência do dia da semana.
// Lembrando que o Calendar já está na primeira ocorrência.
int ajusteSemanaDoMes = 7 * (semanaDoMes - 1);
// Se for cair fora do mês, diminui uma semana.
if (ajusteSemanaDoMes > diasRestantes) {
ajusteSemanaDoMes -= 7;
}
// Finalmente faz o ajuste
cal.add(Calendar.DAY_OF_MONTH, ajusteSemanaDoMes);
return cal.getTime();
}
Mais um exemplo:
//Uso:
Date date = obj.getLastWeekday(2013, Calendar.MARCH, Calendar.THURSDAY);
public Date getLastWeekday(int year, int month, int dayOfWeek) {
Calendar c = Calendar.getInstance();
c.set(Calendar.MONTH, month);
c.set(Calendar.YEAR, year);
//decrescenta o mês e testa o dia da semana.
for (int i = c.getActualMaximum(Calendar.DAY_OF_MONTH); i >= 1; i--) {
c.set(Calendar.DAY_OF_MONTH, i);
if (c.get(Calendar.DAY_OF_WEEK) == dayOfWeek) {
return c.getTime();
}
}
return null;
}
Você pode usar esse método. Ex: Junho/2015 resultará em 5 semanas.
private int obterQuantidadeDeSemanasMesAtual() {
Calendar dataBase = Calendar.getInstance();
int ultimoDiaDoMes = dataBase.getActualMaximum(Calendar.DAY_OF_MONTH);
dataBase.set(Calendar.DAY_OF_MONTH, ultimoDiaDoMes);
return dataBase.get(Calendar.WEEK_OF_MONTH);
}
Uma simulação na melhor situação: Mês com 31 dias.
Olhando esta tabela, talvez fique mais fácil identificar possíveis meses com 5 semanas.
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 32
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
Você pode criar um mapa considerando informações do tipo: mês com 28 (não é necessário para este caso), 29, 30 ou 31 dias, quando começa e quando termina na semana. E, baseado nisso fazer seu cálculo.
Talvez seja mais eficiente que usar a API de datas do Java.
Primeiro obtenha a semana do ano para a data correspondente ao primeiro dia do mês.
Depois obtenha a semana do ano para a data correspondente ao último dia do mês.
Subtraia a primeira da segunda e você terá a quantidade de semanas daquele mês.
Curiosidade: por que responder num tópico de 5 anos atrás?
Nada contra a resposta, mas tenho visto uma galera levantar tópicos de anos atrás, sem um motivo aparente. É porque aparece no feed e as pessoas acabam respondendo sem conferir a data?
Abraço.
Apareceu como recente pra mim, talvez alguém havia respondido alguma coisa antes de mim e apagou a resposta? Sei lá…
O número médio de semanas de um mes no calendário gregoriano é de extamente 4,348125, ou seja
1 mês tem em média 4,348125 semanas
Isso pq o ciclo do calendário gregooriano tem 20871 semanas ou 4800 meses. Portanto 20871/4800 = 4,348125
que complicaçao kkk eu ate entendo o brother o metodo e que nao sei fazer por q sou iniciante mas com certeza ele vai terq pegar a data do sistema, ja e nao tem como agente saber qual vai ser o valores do calenderio ano poz ano, s e fizer pelo calendário atual seria como usar uma fariavel que nao muda e isso pderia dar algum erro, o melhor seria pegar a data do sistema oBs nao falo bem português