Criando um calendário com JavaScript

Criando um calendário com JavaScript

Neste artigo vamos fazer um exercício em Javascript para trabalhar com funções de data. Vamos criar a lógica para montar o calendário do mês atual. Este calendário será exibido no console do navegador. Com base nesta lógica, vamos melhorar o código para permitir imprimir vários calendários, de acordo com um intervalo de datas inicial e final.

Apesar de existirem várias soluções prontas para criar calendários, este exemplo é voltado para quem deseja criar alguma solução do zero e entender como isto pode ser feito.

O que você vai aprender neste artigo?


- Criar uma data com o objeto Date

- Como obter o último dia do mês.

- Descobrir qual o dia da semana de uma data.

- Adicionar elementos em um array.

- Acrescentando um zero a esquerda em um número.

- Remover caracteres de uma string.

- Imprimir calendários com base num intervalo de datas inicial e final.

 

Descobrir o último dia do mês e os dias da semana da data inicial e final do mês

 

Nosso primeiro trabalho é descobrir qual o dia final do mês atual. Para isso vamos usar o objeto Date. O objeto Date possui um construtor que recebe vários parâmetros, geralmente se trabalha com 3, que seriam o ano, mês e o dia. 

 

var nova_data = new Date(ano, mes, dia)

 

Para criar uma data que seja o último dia do mês atual você pode adicionar +1 no parâmetro mês e informar zero no parâmetro dia.

 

var data_inicio = new Date();

var ultimoDiaDoMes = new Date(data_inicio.getFullYear(), data_inicio.getMonth()+1, 0);

console.log(ultimoDiaDoMes);

 

Uma observação: No parâmetro mês deve ser informado um número entre 0 e 11, ou seja, o primeiro mês começa com zero.

O nosso próximo passo é determinar qual o dia da semana da data inicial e da data final do mês. O objeto Date possui um método chamado getDay() que retorna um número entre 0 a 6. O zero se refere ao domingo, 1 se refere a segunda-feira e assim sucessivamente, sendo que o último dia da semana é representado pelo 6, que seria o sábado.

 

var data_inicio = new Date();

var ultimoDiaDoMes = new Date(data_inicio.getFullYear(), data_inicio.getMonth()+1, 0);

var fim =  ultimoDiaDoMes.getDate();

var ultimoDiaDoMes = new Date(data_inicio.getFullYear(), data_inicio.getMonth()+1, 0);

var dia_semana_inicio = new Date(data_inicio.getFullYear(), data_inicio.getMonth(), 1).getDay();

var dia_semana_fim = ultimoDiaDoMes.getDay();

console.log(fim);

console.log(dia_semana_inicio);

console.log(dia_semana_fim);

 

Veja que no código anterior criamos uma variável chamada "fim", que guarda o dia da data do final do mês. O método getDate() do objeto Date retorna o dia da data informada. 

 

Armazenando os dias do calendário num array

 

Os calendários são impressos numa matriz de 7 colunas e "n" linhas, sendo que cada linha corresponde a uma semana.  A coluna inicial vai ser referente ao domingo. Sabemos que os meses nem sempre vão começar no domingo e terminar no sábado, então precisamos calcular os espaços em branco na primeira semana e na última semana do mês.

Como vamos imprimir os números dos dias com dois dígitos, vamos precisar acrescentar um zero a esquerda nos números que são menores que 10.

Vamos criar duas variáveis para controlar a quantidade de espaços vazios no começo e no final do calendário

 

var acrescimo_inicio = 0;

var acrescimo_fim = 0;

if (dia_semana_inicio > 0){

for (i = dia_semana_inicio; i >= 0; i--) {

acrescimo_inicio++;

}

}

if (dia_semana_fim > 0){

if (dia_semana_fim != 6){

acrescimo_fim = 6 - dia_semana_fim;

}

}

console.log(acrescimo_inicio);

console.log(acrescimo_fim);

 

Para o cálculo da variável "acrescimo_inicio"  utilizamos um laço de repetição For para calcular a quantidade de colunas em branco que devem ser adicionadas na primeira semana do mês. 

No caso da variável "acrescimo_fim", para calcular a quantidade de colunas em branco na última semana do mês fizemos uma substração de 6 menos o dia da semana do fim do mês.

Agora chegou a hora de criar um array para guardar os dados de nosso calendário. Primeiro vamos adicionar as colunas extras na primeira semana, depois os dias do mês e por último as colunas em branco na semana final.

 

var array_calendario = [];

for (i = 0; i < acrescimo_inicio-1; i++) {

array_calendario.push("--");

}

for (i = 1; i <= fim; i++) {

array_calendario.push(("0" + i).slice(-2));

}

for (i = 0; i <= acrescimo_fim; i++) {

array_calendario.push("--");

}

console.log(array_calendario);

 

Para adicionar novos elementos para o nosso array utilizamos o método push. Perceba que para as colunas em branco adicionamos a string "--". Como haviamos comentado antes, os dias do mês devem ter dois dígitos, para isso utilizamos o método slice para adicionar um zero a esquerda + o dia do calendário. Como estamos pegando os dois últimos caracteres a partir da direita, se o dia tiver apenas 1 digito ele acrescenta o zero a esquerda.

 

Imprimindo o calendário do mês atual

 

Para imprimir o nosso calendário vamos utilizar um laço de repetição "For". Vamos criar uma string temporaría para armazenar os dias da semana, quando chegarmos no último dia da semana, que seria a sétima coluna, vamos imprimir na tela e limpar a variável temporária para repetir o processo na semana seguinte. 

 

var cabecalho = "DO - SE - TE - QA - QU - SE - SA";

console.log(cabecalho);

var tmp = "";

var z = 1;

for (i = 0; i < array_calendario.length; i++) {

tmp += array_calendario[i] + " - ";

if (z == 7){

tmp = tmp.slice(0, -3);

console.log(tmp);

}

z++;

if (z > 7){

z = 1;

tmp = "";

}

}

 

Perceba que quando adicionamos elementos na variavel temporária "tmp", acrescentamos " - " a cada interação. Quando chegamos na última coluna, utilizamos o método "slice" desta string para remover este espaçador, desta forma não desalinhamos a impressão do calendário no console do navegador.

O código completo pode ver visto a seguir:

 

var data_inicio = new Date();

var ultimoDiaDoMes = new Date(data_inicio.getFullYear(), data_inicio.getMonth()+1, 0);

var acrescimo_inicio = 0;

var acrescimo_fim = 0;

var fim =  ultimoDiaDoMes.getDate();

var dia_semana_inicio = new Date(data_inicio.getFullYear(), data_inicio.getMonth(), 1).getDay();

var dia_semana_fim = ultimoDiaDoMes.getDay();

var array_calendario = [];

if (dia_semana_inicio > 0){

for (i = dia_semana_inicio; i >= 0; i--) {

acrescimo_inicio++;

}

}

if (dia_semana_fim > 0){

if (dia_semana_fim != 6){

acrescimo_fim = 6 - dia_semana_fim;

}

}

//Montar o calendario...

for (i = 0; i < acrescimo_inicio-1; i++) {

array_calendario.push("--");

}

for (i = 1; i <= fim; i++) {

array_calendario.push(("0" + i).slice(-2));

}

for (i = 0; i <= acrescimo_fim; i++) {

array_calendario.push("--");

}

var cabecalho = "DO - SE - TE - QA - QU - SE - SA";

console.log(cabecalho);

var tmp = "";

var z = 1;

for (i = 0; i < array_calendario.length; i++) {

tmp += array_calendario[i] + " - ";

if (z == 7){

tmp = tmp.slice(0, -3);

console.log(tmp);

}

z++;

if (z > 7){

z = 1;

tmp = "";

}

}

 

Imprimindo o calendário de vários meses

 

Vamos fazer agora algo mais sofisticado. Vamos imprimir vários calendários com base numa data inicial e final.

Para isso, vamos criar um array contendo o dia inicial dos meses do intervalo de datas informado. Vamos informar um objeto contendo as datas seguindo este formato:

 

var datas = {

  inicio: new Date(2022, 1, 28, 15, 0, 0, 0), 

  fim: new Date(2022, 8, 1, 15, 0, 0, 0) 

};

 

Perceba que para ínicio e fim criamos um novo objeto Date passando como parâmetros o ano, mês, dia, hora, minuto, segundo e millisegundos. Lembrando mais uma vez que para o parâmetro mês devemos informar um número de 0 a 11 já que o mês de janeiro é representado pelo zero. No horário colocamos 15 horas para evitar problemas com timezones que poderiam impactar negativamente o cálculo com datas.

Nosso código para calcular os dias iniciais de cada mês do intervalo informado ficaria da seguinte forma:

 

function intervalo (datas) {

  var dia = 24 * 60 * 60 * 1000;

  var resultado = [];

  for (var i = datas.inicio.getTime(), fim = datas.fim.getTime(); i <= fim;) {

    var ano = new Date(i).getFullYear();

var mes = new Date(i).getMonth();

    var data_inicio_mes = new Date(ano, mes, 1, 15, 0, 0, 0);

var data_fim_mes = new Date(data_inicio_mes.getFullYear(), data_inicio_mes.getMonth() + 1, 0); 

    resultado.push(data_inicio_mes)

    i = data_fim_mes.getTime() + dia;

  }

  return resultado;

}

var datas = {

  inicio: new Date(2022, 1, 28, 15, 0, 0, 0), 

  fim: new Date(2022, 8, 1, 15, 0, 0, 0) 

};

console.log(intervalo(datas))

 

A função "intervalo" recebe como parâmetro um objeto contendo a data de ínicio e a data final. Utilizando um laço de repetição For fazemos um loop entre a data inicial e a final, perceba que utilizamos o método getTime() do objeto Date para retornar o valor numérico correspondente ao horário da data especificada de acordo com o horário universal.

Como a variável "i" possui o valor da data inicial, extraimos o ano e mês e criamos uma nova data utilizando este mês e ano e informando 1 como dia. Esse resultado é guardado num array chamado resultado, ele vai ser o retorno de nossa função.

Foi necessário calcular o dia final do mês da variável "i", e somar o número de millisegundos de um dia para atualizar esta variável. Desta forma, na interação seguinte, esta variável vai estar atualizada com o valor do dia inicial do mês seguinte.

Voltando ao código que utilizamos para imprimir o nosso calendário, você vai perceber que o ponto de partida foi a variável "data_inicio", que armazena o dia atual. Vamos fazer a seguinte alteração, com base nesse array gerado pela função "intervalo", vamos fazer um loop nestes resultados e usar cada uma de suas datas como o valor inicial.

 

Encerramento

 

O código utilizado para imprimir apenas um mês vai ter pequenos ajustes para poder imprimir qualquer quantidade de meses. O código completo de nosso calendário imprimindo os meses de acordo com um intervalo de data inicial e final fica da seguinte forma:

 

function intervalo (datas) {

  var dia = 24 * 60 * 60 * 1000;

  var resultado = [];

  for (var i = datas.inicio.getTime(), fim = datas.fim.getTime(); i <= fim;) {

    var ano = new Date(i).getFullYear();

var mes = new Date(i).getMonth();

    var data_inicio_mes = new Date(ano, mes, 1, 15, 0, 0, 0);

var data_fim_mes = new Date(data_inicio_mes.getFullYear(), data_inicio_mes.getMonth() + 1, 0); 

    resultado.push(data_inicio_mes)

    i = data_fim_mes.getTime() + dia;

  }

  return resultado;

}

var datas = {

  inicio: new Date(2022, 1, 28, 15, 0, 0, 0), 

  fim: new Date(2022, 8, 1, 15, 0, 0, 0) 

};

var calendario = intervalo(datas)

var nomes= ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro","Dezembro"];

for (var x = 0; x < calendario.length; x++) {

var data_inicio = calendario[x];

var ultimoDiaDoMes = new Date(data_inicio.getFullYear(), data_inicio.getMonth()+1, 0);

var ano = data_inicio.getFullYear();

var mes = data_inicio.getMonth();

var acrescimo_inicio = 0;

var acrescimo_fim = 0;

var fim =  ultimoDiaDoMes.getDate();

var dia_semana_inicio = new Date(data_inicio.getFullYear(), data_inicio.getMonth(), 1).getDay();

var dia_semana_fim = ultimoDiaDoMes.getDay();

var array_calendario = [];

if (dia_semana_inicio > 0){

for (i = dia_semana_inicio; i >= 0; i--) {

acrescimo_inicio++;

}

}

if (dia_semana_fim > 0){

if (dia_semana_fim != 6){

acrescimo_fim = 6 - dia_semana_fim;

}

}

for (i = 0; i < acrescimo_inicio-1; i++) {

array_calendario.push("--");

}

for (i = 1; i <= fim; i++) {

array_calendario.push(("0" + i).slice(-2));

}

for (i = 0; i <= acrescimo_fim; i++) {

array_calendario.push("--");

}

var cabecalho = "DO - SE - TE - QA - QU - SE - SA";

console.log(nomes[mes] + " - " + ano);

console.log(cabecalho);

var tmp = "";

var z = 1;

for (i = 0; i < array_calendario.length; i++) {

tmp += array_calendario[i] + " - ";

if (z == 7){

tmp = tmp.slice(0, -3);

console.log(tmp);

}

z++;

if (z > 7){

z = 1;

tmp = "";

}

}

}

 

 

Para saber mais

 

Se você achou este artigo interessante eu tenho certeza que vai gostar de ver mais conteúdos sobre como trabalhar com datas no JavaScript. Eu recomendo os seguintes links para você:

 

Calculando a diferença de dias úteis entre duas datas utilizando JavaScript

 

Números e datas por extenso em JavaScript

 

Calcular a diferença entre horas utilizando JavaScript

 

Calculando a idade com JavaScript

 

E se você está começando os seus estudos e precisa de um roteiro de estudos, você não pode deixar de conferir o link a seguir:

 

Roadmap JavaScript

 

Está começando e deseja saber o que precisa estudar de HTML e JavaScript? Não deixe de conferir os roteiros de estudo de HTML e JavaScript!. São dezenas de conteúdos para você melhorar suas habilidades.

Roteiro de estudos - HTML e CSS

Roteiro de estudos - Javascript

 

Outros conteudos que podem ser de seu interesse

Validando placas de veiculos com JavaScript
03/11/2019JAVASCRIPT

Validando placas de veiculos com JavaScript

Validando placas de carros ou motos nos formatos atual ou novo com JS

Saiba mais...
Métodos para trabalhar com arrays no JavaScript
29/05/2022JAVASCRIPT

Métodos para trabalhar com arrays no JavaScript

Veja como resolver os problemas mais comuns ao utilizar arrays no JavaScript

Saiba mais...

Conteúdo sobre banco de dados sem complicação!