Como saber se um mes tem 4 ou 5 semanas?[RESOLVIDO]

[quote=GuiCunha]hum pode cre, isso jah ajudou muito.

Assim, eu preciso saber isso por que tenho uma tela aqui que eh uma agenda, então ao gerar um compromisso mensal, caso o usuário gere esse compromisso na quinta segunda feira de cada mês, tenho que fazer uma verificação, pois nem todos os meses tem 5 semanas, então os que tiverem apenas 4 semanas terão que receber esse compromisso na quarta segunda feira do mês, já os que tiverem 5 semanas receberão o compromisso na quinta segunda-feira.

Não se ficou bem claro, mais é por isso que preciso saber. :D[/quote]

Sua lógica não tem muito sentido (pelo menos para mim).
Se a pessoa agendou uma quinta-feira o algoritmo é : para cada quinta-feira do mês , agende.
Se o mês termina na quarta-feira, paciência. Não ha que marcar a quarta-feira;
Se a tarefa pode ser continuada no mês seguinte, então continua marcando quinta-feira e pronto. Se o evento é semanal não importa o mês em que vc está.

Agora, se a tarefa tem que ser executada N vezes no mês e não existem N quintas-feiras, ai sim, ha que considerar usar a quarta-feira anterior, mas isso não é uma tarefa semanal. Eu poderia simplesmente dividir os dias uteis por N e intercalar um agendamento a cada K dias sem precisar que caia no mesmo dia da semana.

Seja como for, eu usaria o primeiro algoritmo. A cada Q-Feira do mês, agende. Se ha um numero necessários de vezes seria, Enqanto houver vezes para agendar, agende a cada Q-feira, se ela for do mesmo mês. Se não, agende no dia anterior que seja do mesmo mês. Este algoritmo pode levar a agendamento na Quinta-Feira e depois na sexta também (se a sexta é o ultimo dia do mes e ainda faltam eventos para marcar).

Se que vc esplique exactamente a regra de negocio tudo o que vc está falando soa muito estranho e heterodoxo.

sergiotaborda, minha lógica faz sentido, soh tens que entende-la antes…

Assim oh,

Na tela da agenda, o usuário pode cadastrar um compromisso, para tal semana de tal mês.

Então ele vai lah e coloca… “Ahhh eu quero um compromisso toda QUINTA segunda-feira de TODO MÊS.”

Ai vem o problema, pois nem todos os meses tem CINCO SEMANAS, então eu preciso saber apenas quando o mês tem CINCO SEMANAS. Caso o mes seja de QUATRO SEMANAS eu marco o compromisso para a última semana do mês, ou seja, a QUARTA.

Vamos pensar do avesso. Na verdade, se você clicar em uma 5ª-feira, você quer saber se é a última 5ª-feira desse mês, não?

Para saber se é a última 5ª-feira, você deve saber que dia da semana é o último dia do mês.

if ((mes == FEVEREIRO) && (diaDaSemana("1º de fevereiro de " + ano) == DOMINGO) && (! isBissexto(ano))) return 4 else return 5

[quote=GuiCunha]sergiotaborda, minha lógica faz sentido, soh tens que entende-la antes…
[/quote]

Com certeza. E cabe a você explicar-se.

[quote]
Na tela da agenda, o usuário pode cadastrar um compromisso, para tal semana de tal mês.

Então ele vai lah e coloca… “Ahhh eu quero um compromisso toda QUINTA segunda-feira de TODO MÊS.”

Ai vem o problema, pois nem todos os meses tem CINCO SEMANAS, então eu preciso saber apenas quando o mês tem CINCO SEMANAS. Caso o mes seja de QUATRO SEMANAS eu marco o compromisso para a última semana do mês, ou seja, a QUARTA.[/quote]

Eu entendi o que vc quer, mas continua não fazendo sentido porque ninguém pensa assim.
A pessoa pensa na primeira semana, na segunda semana ou na ultima semana. Não importa se é quarta ou a quinta ou a terceira ou a oitava. No máximo a pessoa pensa na terceira semana. ninguem pensa na “quarta semana”, pensa na “ultima semana”.
A ultima quinta-feira é trivial de encontrar e não é relevante se é a quarta ou quinta, e sim é que é a ultima.

Vc está forçando um raciocínio que não é natural. Simplesmente porque é raro que meses tenha 5 dias do mesmo tipo , não faz sentido agendar dessa forma. A pessoa irá agendar pela distancia ao principio ou ao fim, e não em termos absolutos.
De qualquer forma já lhe dei o algoritmo. conte a Q-Feira que quiser procurar e escolha a n-ésima.

Bom sergiotaborda acredito que vc não entendeu o o guicunha quer, afinal caso eu queira marcar um compromisso em uma agenda por exemplo toda quinta quinta-feira do mes 1 ate o mês 10 é necessario saber a ultima semana , fiz algo parecido com o que ele precisa mais em outra linguagem,
bom segue a logica que eu usei
primeiro se vc possui o dia da semana exemplo quinta-feira vc pode fazer um While e percorrer ate o tanto de dias do mês incrementando a data

[code]While diadomes = 31 {

incrementa diadomes

incrementa semana

If (semana = 5) {
if (diasemana = quintafeira) {
incrementa data
}
}
}[/code]
assim vc chegara a data quando for a 5º semana ou a semana desejada…

Agora sim, alguém finalmente entendeu…

Vlw’

Eu entendi mas acho que não é a melhor maneira de resolver o problema. Ter cinco ocorrências de um dia da semana é uma coisa rara (olha lá na tabelinha que colocaram na primeira página), você vai modelar seu sistema pensando em uma situação que dificilmente acontece?

Imagine o seguinte:
O mês acabou na segunda-feira da quinta semana.
Vários clientes tem compromissos para a quinta terça-feira, a quinta quarta-feira, a quinta quinta-feira, a quinta sexta-feira e talvez até o quinto sábado (ficou um pouco confuso esse monte de nomes de dias, leia com calma :slight_smile: )
Pois bem… todos esses clientes vão ficar encavalados nessa última segunda-feira? A empresa terá condição de atendê-los? Os próprios clientes vão querer ser realocados de quinta-feira para segunda-feira?

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