Introdução
\nTrabalhar com datas e horas é uma das tarefas mais comuns, mas também das mais traiçoeiras no desenvolvimento web. O objeto padrão Date em JavaScript, apesar de sua versatilidade, tem uma série de limitações: falta de suporte embutido para fusos horários (exceto UTC e hora local), métodos inconvenientes para formatação e dificuldades no cálculo da diferença entre datas. Neste artigo, vamos abordar técnicas avançadas de trabalho com datas no ambiente Node.js que o ajudarão a escrever código confiável e claro.
1. Intl.DateTimeFormat: Formatação poderosa sem bibliotecas de terceiros
\nO JavaScript moderno fornece a API embutida Intl.DateTimeFormat, que permite formatar datas e horas de forma flexível, considerando a localidade. Esta é a ferramenta ideal se você não precisa de todo o poder das bibliotecas de terceiros.
Uso básico
\nCrie uma instância do formatador, passando a localidade e um objeto com opções:
\nconst date = new Date('2024-12-25T10:30:00Z');\n\n// Formatação para localidade russa\nconst ruFormatter = new Intl.DateTimeFormat('ru-RU', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n weekday: 'long',\n hour: '2-digit',\n minute: '2-digit',\n timeZone: 'Europe/Moscow'\n});\n\nconsole.log(ruFormatter.format(date));\n// Saída: "среда, 25 декабря 2024 г. в 13:30"\n\nTrabalhando com fusos horários
\nA principal vantagem do Intl.DateTimeFormat é o suporte a fusos horários através da opção timeZone. Você pode exibir a mesma data em diferentes fusos:
const date = new Date();\n\nconst formatters = {\n 'Nova York': new Intl.DateTimeFormat('en-US', { timeZone: 'America/New_York', dateStyle: 'full', timeStyle: 'long' }),\n 'Tóquio': new Intl.DateTimeFormat('ja-JP', { timeZone: 'Asia/Tokyo', dateStyle: 'full', timeStyle: 'long' }),\n 'Londres': new Intl.DateTimeFormat('en-GB', { timeZone: 'Europe/London', dateStyle: 'full', timeStyle: 'long' })\n};\n\nfor (const [city, fmt] of Object.entries(formatters)) {\n console.log(`${city}: ${fmt.format(date)}`);\n}\n\nFormatação de intervalos de datas
\nA API também consegue formatar intervalos usando o método formatRange:
const start = new Date('2024-01-01');\nconst end = new Date('2024-01-05');\n\nconst rangeFormatter = new Intl.DateTimeFormat('ru-RU', {\n month: 'long',\n day: 'numeric'\n});\n\nconsole.log(rangeFormatter.formatRange(start, end));\n// Saída: "1–5 января"\n\n2. Manipulações com datas: adição, subtração e diferença
\nO Date padrão não é adequado para aritmética. Vamos considerar duas abordagens: JavaScript puro e bibliotecas populares.
JavaScript puro: trabalhando com milissegundos
\nA maneira mais simples é converter a data para Unix timestamp (milissegundos desde 1º de janeiro de 1970) e realizar as operações:
\nfunction addDays(date, days) {\n const result = new Date(date);\n result.setTime(result.getTime() + days * 24 * 60 * 60 * 1000);\n return result;\n}\n\nfunction diffDays(date1, date2) {\n const msDiff = Math.abs(date2.getTime() - date1.getTime());\n return Math.floor(msDiff / (1000 * 60 * 60 * 24));\n}\n\nconst today = new Date('2024-10-01');\nconst future = addDays(today, 30);\nconsole.log(future); // 2024-10-31\nconsole.log(diffDays(today, future)); // 30\nDesvantagem: não considera o horário de verão, segundos bissextos e a duração variável dos meses.
\n\nBiblioteca date-fns: abordagem funcional e leve
\ndate-fns é uma biblioteca modular, onde cada função é um módulo separado. Isso evita inflar o bundle:
// Instalação: npm install date-fns\nconst { addDays, subMonths, differenceInDays, format } = require('date-fns');\nconst { ru } = require('date-fns/locale');\n\nconst startDate = new Date(2024, 0, 15); // 15 de janeiro de 2024\n\nconst plusWeek = addDays(startDa