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

30 respostas
GuiCunha

Bom dia pessoal,

Alguém sabe se tem algum método pronto pra saber exatamente quantas semans tem em um mês?

Sei que os meses variam entre 4 e 5 semanas, mais preciso saber exatamente quantas semanas cada mes tem, e pra isso teria que usar algo como uma função (método) para me retornar isso.

Utilizo Netbeans 7.3

Se alguém souber posta ai. Desde já agradeço.

atenciosamente,

Guilherme Cruz da Cunha

30 Respostas

Luciano_Lopes

Acho que você quer saber os dias uteis do mês, não? Um mês equivale a 4 semanas, não tem como chegar a 5

GuiCunha

Cara tem meses que tem 5 semanas sim, e eu preciso saber quando o mês tiver essas 5 semanas. Por exemplo se o mês começar na segunda, terça ou quarta é muito provável que chegue a ter 5 semanas, mesmo que não sejam inteiras.

Rodrigo_Sasaki

Primeiro acho que você tem que definir o que considera como semana.

  • Uma semana cheia de 7 dias?
  • A maior parte de uma semana?
  • Um único dia?

Se um mês termina em um domingo da 5ª semana, essa semana é considerada ou descartada?

Tendo isso em mente é só contar os dias, cara :slight_smile:

GuiCunha

Então, eu acho que se uma semana tem no mínimo 3 dias, é considerada uma semana, mais não to conseguindo passar isso pra programação entende, esse é o problema. :frowning:

Rodrigo_Sasaki

Primeiro defina o que é uma semana pra você, depois pense no resto.

Vamos lá, responda as questões acima, pense em outras definições, e tome isso como regra.
Se você não sabe o que será considerado como semana, não tem como desenvolver um algoritmo que calcule isso.

lina

Rodrigo Sasaki:
Primeiro defina o que é uma semana pra você, depois pense no resto.

Vamos lá, responda as questões acima, pense em outras definições, e tome isso como regra.
Se você não sabe o que será considerado como semana, não tem como desenvolver um algoritmo que calcule isso.

Oi,

Depois de definir o que é semana, pode-se utilizar a classe Calendar para fazer o que necessitas.

Dica: Existe um método chamado getFirstDayOfWeek() que retorna o primeiro dia da semana.

Tchauzin!

gmmascarin

Acho que entendi o que você quer. Não seria isso?

Calendar c = Calendar.getInstance();
c.set(Calendar.MONTH, 0);
c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
int val = c.get(Calendar.DAY_OF_WEEK_IN_MONTH);
System.out.println(val);
gmmascarin

Pessoal, não sei o motivo, mas a mensagem duplicou. Não sei como excluir.

sergiotaborda

Não sei onde vc desenterrou essa definição, uma semana tem 7 dias. Uma semana útil tem 5 dias. Feriados não importam.
Portanto sua definição de 3 dias é no mínimo não-padrão. Repare que 7x5 = 35 que é maior que os dias de qualquer mes. Logo, não é possivel ter 5 semanas de 7 dias, como ja foi dito.
É possivel ter 5x5=25 dias uteis, mas por causa dos fins de semana e de 7 e 5 serem numeros primos vc tem que considerar exactamente os dias da semana em que cai o dia do mês. Se o dia 1 é um domingo dia 8 será um domingo e todos os dias 1+nx7 onde N é numero de semanas passadas. Logo se o mes tem 31 dias ele tera (31 - 1 / 7) = 4,1 semanas . que arredondando significa que tem 5 semanas porque pelo menos uma segunda feira será necessária. Isto leva a concluir que sua definição de semana é mais simples do que parece. Se um dia da semana pertence ao mes, então aquele mês tem aquela semana. Mas como semanas podem ser divididas entre dois meses, considera-se que a semana é daquele que tem mais dias ( portanto, no mínimo 4, e não 3 dias). as veja que tudo isto é mera metemática se vc não explicar para quê vc quer usar esse numero de semanas. Se for para calcular dias de trabalho, por exemplo, esse tipo de contas simplesmente não significa nada, pois todas as leis de trabalho se referem a jornadas e horas de trabalho sendo que jornada não é necessariamente um dia (pois o dia tem 24 h e a jornada tem normalmente 8, cabem 3 jornadas num dia).

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. :smiley:

E

Quando você vai desenhar um calendário provavelmente quer saber quantas linhas (correspondentes a semanas) vai precisar desenhar em um calendário, é isso?

Uma maneira é você determinar a semana do ano onde está o primeiro dia do mês e a semana do ano onde está o último dia do mês. Aí você subtrai esses dois números e soma 1.

Entretanto, você precisa tomar um pouco de cuidado com janeiro, porque get (Calendar.WEEK_OF_YEAR) pode retornar um número esquisito para primeiro de janeiro :frowning: - ele pode retornar 53 em vez de 1 dependendo do ano :frowning:

sergiotaborda

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

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.

GuiCunha

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.

E

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.

B

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

sergiotaborda

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

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


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.

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.

B

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

While diadomes = 31 {

incrementa diadomes

incrementa semana

If (semana = 5) {
     if (diasemana = quintafeira) {
           incrementa data    
     }
} 
}
assim vc chegara a data quando for a 5º semana ou a semana desejada...
GuiCunha

Agora sim, alguém finalmente entendeu…

Vlw’

gomesrod

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?

GuiCunha

Caso não haja quinta semana o compromisso é salvo na quarta semana.

g4j

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.

gomesrod

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();
    }
g4j

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;
}
danvsantos

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);
}
WellingtonRamos

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.

staroski

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.

TerraSkilll

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.

staroski

Apareceu como recente pra mim, talvez alguém havia respondido alguma coisa antes de mim e apagou a resposta? Sei lá…

Jamil_Silva

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

Pantrol

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

Criado 12 de março de 2013
Ultima resposta 20 de abr. de 2021
Respostas 30
Participantes 17