O JavaScript tem um objeto incorporado, Date, que armazena a data e a hora e fornece métodos para as gerir.
Baseava-se na classe java.util.Date do Java, que foi substituída no início da década de 2010, mas, por compatibilidade com versões anteriores, o Date do JavaScript continua a existir.
Devido à dificuldade geral de trabalhar com datas e ao facto de o tratamento de fusos horários ser mau ou inexistente, existem muitas bibliotecas, como moment.js, day.js, date-fns e luxon.
Nenhuma delas está disponível no Exercism.
Nos teus próprios projetos, não uses um pacote obsoleto ou sem manutenção como o moment.js; usa antes alternativas mais modernas, como o luxon, ou o Temporal, que ainda não está amplamente disponível.
Este exercício centra-se no Date, que continuará a ser relevante até ao fim do JavaScript.
Um objeto Date é uma instância da classe Date.
Pode ser criado sem passar quaisquer argumentos à função construtora.
Isto resulta num 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).
Se for passado um número, este será interpretado como um timestamp.
Um timestamp é um número inteiro que representa o número 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)
Podes esperar que new Date(0) gere o objeto de data "mais antigo", mas o JavaScript converte a data para o teu fuso horário local, o que significa que só quem está num fuso horário GMT / UTC+0 é que obtém realmente o valor do Unix epoch.
Podes passar um valor do tipo string que representa uma data à função construtora Date.
O único formato consistente entre implementações é a versão simplificada das chamadas strings de timestamp ISO 8601, reconhecidas e normalizadas internacionalmente.
Um momento no tempo em UTC tem este aspeto:
YYYY-MM-DDTHH:mm:ss.mssZ
YYYYMMDDTHHmmss.mssZ
Em que ocorrem as seguintes substituições:
| Chave | Descrição | Predefiniçã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 num relógio de 24 horas, com 2 dígitos | 00 |
| mm | Os minutos, com 2 dígitos | 00 |
| ss | Os segundos, com 2 dígitos | 00 |
| mss | Os milissegundos, com 3 dígitos | 000 |
| Z | Uma letra Z literal, ou um desvio +/-HH:mm
|
A letra Z literal indica UTC (sem fuso horário, sem horário de verão).
Como existem valores predefinidos para a maioria dos componentes, é válido omitir partes no fim:
YYYY-MM-DD
Por predefinição, assume a hora 00:00:00.000.
Se o timestamp não terminar em Z nem terminar com +HH:mm ou -HH:mm (que indicam um desvio de fuso horário), por razões históricas aplica-se o seguinte:
Quando o desvio de fuso horário está ausente, as formas apenas com data são interpretadas como uma hora UTC e as formas com data e hora são interpretadas como uma hora local. A interpretação como hora UTC deve-se a um erro histórico da especificação, que não era coerente com a ISO 8601, mas que não pôde ser alterado devido à compatibilidade com a web. Vê Broken Parser: um problema de realidade da web.
Outros formatos aceites por Date.parse podem ou não funcionar.
Ao trabalhar com datas em JavaScript, usa sempre um timestamp ISO 8601 ao converter uma string para um Date.
As formas apenas com data são permitidas, mas nem todos os formatos ISO 8601 são suportados. Consulta a página de explicação da versão simplificada na MDN.
Também podes usar um objeto de data já existente como argumento da função construtora.
Isto 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.
Podes criar um objeto de data que representa apenas uma data passando três números. Podes criar um objeto de data que representa uma data e uma hora 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()Podes encontrar menções ou referências a uma função de análise de datas, Date.parse.
Como esta função tem apenas alguns invariantes (verdades) e como o resto da implementação não está especificado (e, por isso, não é padrão), não deves usá-la.
Date
Existem vários métodos nos objetos de data que devolvem 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 destes tem uma variante set correspondente (por exemplo, setFullYear) para atualizar o valor.
Qualquer valor que transborde 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 ignoram o fuso horário local.
Os objetos de data têm um método getTime() que devolve o timestamp UNIX em milissegundos, ou seja, o número de milissegundos desde a meia-noite do início de 1 de janeiro de 1970, UTC.
Além disso, existe o método toISOString(), que converte um objeto de data numa string de timestamp ISO 8601.
Os operadores maior que (>), maior ou igual (>=), menor que (<) e menor ou igual (<=) podem ser usados diretamente entre duas datas, ou entre uma data e um número.
Isto funciona porque o JavaScript tenta converter a data num valor primitivo.
Ao fazer uma comparação entre duas datas, ou entre uma data e um número, o JavaScript chama [Symbol.toPrimitive]("number"), que por sua vez chama date.valueOf().
Esta última é equivalente a chamar date.getTime().
Se não quiseres depender deste comportamento, converte primeiro num número com getTime().
Não é possível comparar datas com os operadores de igualdade (== e ===), mas podes comparar o resultado de .getTime().
Neste exercício vais trabalhar com algumas funções para gerir marcações. O sistema guarda tudo em strings formatadas em ISO 8601, mas não é assim que as pessoas usam o calendário. São necessárias várias funções para converter entre os diferentes formatos.
Cria uma marcação daqui a n dias, à hora atual.
A função recebe n dias e devolve a hora da marcação 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, deve ser usada a hora atual.
Várias ferramentas só funcionam com o formato ISO 8601, normalizado internacionalmente.
Escreve a função getAppointmentTimestamp, que recebe uma data e devolve 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'
Os timestamps são difíceis de ler; uma função para obter os detalhes da marcação deve ajudar nisso.
A função getAppointmentDetails recebe um timestamp no formato ISO 8601 e devolve o ano, o mês, o dia, a hora e os minutos.
getAppointmentDetails('2022-04-24T08:15:00.000');
// => { year: 2022, month: 3, date: 24, hour: 8, minute: 15 }
A função recebe como primeiro argumento a hora da marcação e como segundo argumento um objeto com algumas opções. Tens de atualizar a marcação de acordo com as opções do objeto e devolver a nova data da marcação. 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 }
A função recebe duas marcações (timestamps) como argumentos. Tens de devolver a diferença entre esses dois momentos em segundos.
Como meio segundo é quase irrelevante, arredonda o número antes de o devolver.
timeBetween('2022-12-12T09:20:00.000', '2022-12-18T08:30:00.000');
// => 515400
Por fim, quando a marcação é criada, o sistema precisa de verificar se é válida. Por outras palavras, a marcação tem de estar no futuro e não no passado.
Escreve a função isValid, que recebe dois argumentos, um timestamp de marcação (string) e a hora atual como timestamp (string), e devolve true se a marcação estiver no futuro, dada a hora atual.
isValid('2022-02-11T23:00:00.000', '2022-02-08T23:00:00.000');
// => true
Inscreve-te no Exercism para aprenderes e dominares JavaScript com 37 conceitos159 exercícios, e mentoria humana real, tudo grátis.