Trilhas
/
JavaScript
JavaScript
/
Exercícios
/
Horário marcado
Horário marcado

Horário marcado

Exercício de aprendizagem

Introdução

O JavaScript tem um objeto embutido, Date, que armazena data e hora e fornece métodos para gerenciá-las.

Caution

Ele foi baseado na classe java.util.Date do Java, que foi substituída no início da década de 2010, mas, por compatibilidade retroativa, o Date do JavaScript continua por aí.

Como é difícil lidar com datas em geral e como o tratamento de fuso horário é ruim ou simplesmente inexistente, existem muitas bibliotecas, como moment.js, day.js, date-fns e luxon. Nenhuma delas está disponível no Exercism.

Nos seus próprios projetos, não use um pacote obsoleto ou sem manutenção como o moment.js; prefira alternativas mais modernas, como o luxon, ou o Temporal, que ainda não está amplamente disponível. Este exercício foca no Date, que continuará relevante até o fim do JavaScript.

Criação

Um objeto Date é uma instância da classe Date. Ele pode ser criado sem passar nenhum argumento à função construtora. Isso resulta em um objeto Date que representa a data e a hora atuais:

const now = new Date();
// => Thu Apr 14 2022 11:46:08 GMT+0530 (India Standard Time)
// Shows current day, date and time (in your time zone).

Timestamp Unix (número)

Se um número for passado, ele será interpretado como um timestamp. Um timestamp é um número inteiro que representa a quantidade de milissegundos decorridos desde 1º de janeiro de 1970 UTC+0.

const epoch = new Date(0);
// Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time)

const another = new Date(1749508766627);
// Tue Jun 10 2025 00:39:26 GMT+0200 (Central European Summer Time)

É de se esperar que new Date(0) gere o objeto de data "mais antigo", mas o JavaScript converte a data para o seu fuso horário local, o que significa que só quem está em um fuso GMT / UTC+0 é que vai obter de fato o valor da época Unix.

Timestamp ISO 8601 (string)

Você pode passar ao construtor Date um valor de string que representa uma data. O único formato consistente entre implementações é a versão simplificada das chamadas strings de timestamp ISO 8601, reconhecidas e padronizadas internacionalmente.

Um instante no tempo em UTC se parece com isto:

YYYY-MM-DDTHH:mm:ss.mssZ
YYYYMMDDTHHmmss.mssZ

Onde ocorrem as seguintes substituições:

Chave Descrição Padrão
YYYY O ano civil, representado com 4 dígitos
MM O mês civil, representado com 2 dígitos 01
DD O dia civil, representado com 2 dígitos 01
T Uma letra T literal, que separa a data da hora
HH As horas em relógio de 24 horas, 2 dígitos 00
mm Os minutos, 2 dígitos 00
ss Os segundos, 2 dígitos 00
mss Os milissegundos, 3 dígitos 000
Z Uma letra Z literal, ou um deslocamento +/-HH:mm

A letra Z literal indica UTC (sem fuso horário, sem horário de verão).

Como a maioria dos componentes tem valores padrão, é válido omitir partes no final:

YYYY-MM-DD

O padrão é o horário 00:00:00.000

Se o timestamp não terminar em Z e não terminar em +HH:mm ou -HH:mm (que indicam um deslocamento de fuso horário), por razões históricas aplica-se o seguinte:

Quando o deslocamento de fuso horário está ausente, formas apenas com data são interpretadas como horário UTC, e formas com data e hora são interpretadas como horário local. A interpretação como horário UTC se deve a um erro histórico na especificação, que não era compatível com a ISO 8601, mas que não pôde ser corrigido por causa da compatibilidade com a web. Veja Broken Parser – A Web Reality Issue.

Caution

Outros formatos aceitos por Date.parse podem ou não funcionar. Ao trabalhar com datas em JavaScript, use sempre um timestamp ISO 8601 ao converter de string para Date.

Formas apenas com data são permitidas, mas nem todos os formatos ISO 8601 são compatíveis. Consulte a página que explica a versão simplificada no MDN.

Objeto Date

Um objeto de data existente também pode ser usado como argumento do construtor. Isso cria uma cópia do objeto Date existente, com a mesma data e a mesma hora.

const t1 = new Date();
const t2 = new Date(t1);
// Values of t1 and t2 will be the same.

Fornecendo valores individuais de componentes de data e hora

Uma data que representa apenas uma data pode ser criada passando três números. Uma data que representa data e hora pode ser criada passando 6 números.

const date1 = new Date(95, 11, 17);
// Creates Date for Dec 17 1995 00:00 if your local timezone is equivalent to UTC.

const date2 = new Date(2013, 12, 5, 13, 24, 0);
// Creates Date for Jan 5 2014 13:24 if your local timezone is equivalent to UTC.

O segundo valor é o month, que começa em 0 para janeiro e vai até 11 para dezembro.

Date.parse()

Você pode encontrar menções ou referências a uma função de análise de datas, Date.parse. Como essa função tem poucas invariantes (verdades) e o restante da implementação não é especificado (e, portanto, não é padrão), não convém usá-la.

Acessando os componentes de Date

Há vários métodos em objetos de data que retornam os componentes da data:

getFullYear(); // Get the year (4 digits)
getMonth(); // Get the month, from 0 to 11.
getDate(); // Get the day of month, from 1 to 31.
getHours(); // Get the hour in a 24 clock, from 0 to 23
getMinutes(); // Get the minutes, from 0 to 59
getSeconds(); // Get the seconds, from 0 to 59
getMilliseconds(); // Get the milliseconds, from 0 and 999
getDay(); // Get the day of week, from 0 (Sunday) to 6 (Saturday).

Cada um deles tem uma variante set correspondente (por exemplo, setFullYear) para atualizar o valor. Qualquer valor que ultrapasse o limite passa para o componente seguinte:

const date = new Date('2025-02-28T12:42:00Z');
// => Fri Feb 28 2025 13:42:00 GMT+0100 (Central European Standard Time)

date.setDate(29);
// there was no February 29th in 2025.

date.getDate();
// => 1

date.toString();
// => Sat Mar 01 2025 13:42:00 GMT+0100 (Central European Standard Time)

Existem variantes UTC de todos os métodos, que desconsideram o fuso horário local.

Convertendo a partir de uma data

Objetos de data têm um método getTime() que retorna o timestamp UNIX em milissegundos, ou seja, a quantidade de milissegundos desde a meia-noite do início de 1º de janeiro de 1970, UTC. Além disso, o método toISOString() está disponível para converter um objeto de data em uma string de timestamp ISO 8601.

Comparando datas

Os operadores maior que (>) e maior ou igual (>=), assim como menor que (<) e menor ou igual (<=), podem ser usados diretamente entre duas datas ou entre uma data e um número. Isso funciona porque o JavaScript tenta converter a data em um primitivo.

Advanced

Ao fazer uma comparação entre duas datas, ou entre uma data e um número, o JavaScript chama [Symbol.toPrimitive]("number"), que internamente chama date.valueOf(). Esta última é a mesma coisa que chamar date.getTime().

Se você não quiser depender desse comportamento, converta para número usando getTime() primeiro.

Datas não podem ser comparadas com igualdade (== e ===), mas o resultado de .getTime() pode.

Instruções

Neste exercício, você vai trabalhar com algumas funções para gerenciar compromissos. O sistema guarda tudo em strings formatadas conforme a ISO 8601, mas não é assim que as pessoas usam o calendário. Várias funções são necessárias para converter entre os diversos formatos.

1. Crie um compromisso

Crie um compromisso daqui a n dias, no horário atual. A função recebe n dias e retorna o horário do compromisso daqui a n dias.

createAppointment(4, now);
// Given now is Sun Oct 05 2022 23:28:43 GMT+0600 (Bangladesh Standard Time)
// => Sun Oct 09 2022 23:28:43 GMT+0600 (Bangladesh Standard Time)

Se o segundo parâmetro now não for usado, o horário atual deve ser usado em vez dele.

2. Converta uma data em um timestamp

Várias ferramentas só funcionam com o formato ISO 8601, padronizado internacionalmente. Escreva a função getAppointmentTimestamp para receber uma data e retornar uma string nesse formato.

const appointment = new Date(Date.UTC(2010, 6, 16, 12, 42, 0, 0));

getAppointmentTimestamp(appointment);
// => '2010-07-16T12:42:00.000Z'

3. Obtenha os detalhes de um compromisso

Timestamps são difíceis de ler; uma função para obter os detalhes do compromisso deve ajudar com isso. A função getAppointmentDetails recebe um timestamp no formato ISO 8601 e retorna o ano, o mês, o dia, a hora e o minuto.

getAppointmentDetails('2022-04-24T08:15:00.000');
// => { year: 2022, month: 3, date: 24, hour: 8, minute: 15 }

4. Atualize um compromisso com as opções fornecidas

A função receberá como primeiro argumento o horário do compromisso e como segundo argumento um objeto com algumas opções. Você deve atualizar o compromisso de acordo com as opções no objeto e retornar a nova data do compromisso. O objeto de opções pode ter várias opções.

updateAppointment('2022-02-09T09:20:00.000', { month: 6 });
// => { year: 2022, month: 6, date: 9, hour: 10, minute: 20 }

5. Obtenha o tempo disponível entre dois compromissos

A função receberá dois compromissos (timestamps) como argumentos. Você deve retornar a diferença entre esses dois horários em segundos.

Como meio segundo é quase insignificante, arredonde o número antes de retorná-lo.

timeBetween('2022-12-12T09:20:00.000', '2022-12-18T08:30:00.000');
// => 515400

6. Verifique se um compromisso é válido ou não

Por fim, quando o compromisso é marcado, o sistema precisa verificar se ele é válido. Em outras palavras, o compromisso deve estar no futuro, e não no passado.

Escreva a função isValid, que recebe dois argumentos, um timestamp de compromisso (string) e o horário atual como timestamp (string), e retorna true se o compromisso estiver no futuro, dado o horário atual.

isValid('2022-02-11T23:00:00.000', '2022-02-08T23:00:00.000');
// => true
Editar via GitHub O link abre em uma nova janela ou aba
JavaScript Exercism

Tudo pronto para começar Horário marcado?

Crie sua conta no Exercism para aprender e dominar JavaScript com 37 conceitos159 exercícios e mentoria humana de verdade, tudo de graça.