Busque em todas as páginas da documentação
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
npm install date-fnsimport { format, parseISO, addDays, differenceInDays } from "date-fns";
// Formatar uma data
format(new Date(), "MMMM d, yyyy"); // "Abril 6, 2026"
// Analisar string ISO
const date = parseISO("2026-04-06T12:00:00Z");
// Adicionar dias
const nextWeek = addDays(new Date(), 7);
// Diferença entre datas
const days = differenceInDays(new Date("2026-12-31"), new Date()); // dias até o fim do anoQuando usar: Você precisa formatar, analisar, comparar ou manipular datas com uma biblioteca leve e com tree-shaking que utiliza objetos Date nativos.
// app/components/ActivityFeed.tsx
"use client";
import {
format,
formatDistanceToNow,
isToday,
isYesterday,
isThisWeek,
parseISO,
} from "date-fns";
interface Activity {
id: string;
action: string;
timestamp: string; // String ISO
user: string;
}
const ACTIVITIES: Activity[] = [
{ id: "1", action: "pushed to main", timestamp: new Date().toISOString(), user: "Alice" },
{ id: "2", action: "opened PR #42", timestamp: new Date(Date.now() - 3600000).toISOString(), user: "Bob" },
{ id: "3", action: "merged PR #41", timestamp: new Date(Date.now() - 86400000).toISOString(), user: "Carol" },
{ id: "4", action: "created issue", timestamp: new Date(Date.now() - 259200000).toISOString(), user: "Dave" },
{ id: "5", action: "deployed v2.1", timestamp: "2026-03-20T10:30:00Z", user: "Eve" },
];
function formatTimestamp(isoString: string): string {
const date = parseISO(isoString);
if (isToday(date)) {
return formatDistanceToNow(date, { addSuffix: true }); // "2 horas atrás"
}
if (isYesterday(date)) {
return `Ontem às ${format(date, "h:mm a")}`; // "Ontem às 15:30"
}
if (isThisWeek(date)) {
return format(date, "EEEE 'às' h:mm a"); // "Segunda-feira às 10:30"
}
return format(date, "MMM d, yyyy"); // "Mar 20, 2026"
}
export default function ActivityFeed() {
return (
<div className="max-w-lg mx-auto p-6">
<h2 className="text-xl font-bold mb-4">Atividade</h2>
<ul className="space-y-3">
{ACTIVITIES.map((activity) => (
<li key={activity.id} className="flex justify-between items-center border-b pb-2">
<div>
<span className="font-medium">{activity.user}</span>{" "}
<span className="text-gray-600">{activity.action}</span>
</div>
<time
dateTime={activity.timestamp}
className="text-sm text-gray-400 whitespace-nowrap"
>
{formatTimestamp(activity.timestamp)}
</time>
</li>
))}
</ul>
</div>
);
}O que isto demonstra:
parseISO para análise segura de strings ISOisToday, isYesterday, isThisWeek para formatação condicionalformatDistanceToNow para saída no estilo "X horas atrás"<time> semântico com atributo dateTimeDate nativos do JavaScript, não em uma classe wrapper personalizadaformat usa tokens do Padrão Técnico Unicode #35: yyyy (ano), MM (mês), dd (dia), HH (24h), hh (12h), mm (minutos), ss (segundos)parseISO é preferível a new Date(string) porque lida com strings ISO 8601 de forma consistente entre navegadoresisBefore, isAfter, isEqual) comparam timestamps, não strings de dataAritmética de datas:
import {
addDays,
addMonths,
addHours,
subWeeks,
startOfMonth,
endOfMonth,
eachDayOfInterval,
} from "date-fns";
const tomorrow = addDays(new Date(), 1);
const nextMonth = addMonths(new Date(), 1);
const twoHoursLater = addHours(new Date(), 2);
const lastWeek = subWeeks(new Date(), 1);
// Obter todos os dias do mês atual (útil para calendários)
const monthStart = startOfMonth(new Date());
const monthEnd = endOfMonth(new Date());
const daysInMonth = eachDayOfInterval({ start: monthStart, end: monthEnd });Suporte a locale:
import { format, formatDistanceToNow } from "date-fns";
import { fr } from "date-fns/locale";
import { ja } from "date-fns/locale";
format(new Date(), "EEEE d MMMM yyyy", { locale: fr });
// "lundi 6 avril 2026"
formatDistanceToNow(new Date(Date.now() - 7200000), {
addSuffix: true,
locale: ja,
});
// "約2時間前"Intervalo e comparação de datas:
import {
isWithinInterval,
isBefore,
isAfter,
differenceInCalendarDays,
differenceInBusinessDays,
areIntervalsOverlapping,
} from "date-fns";
const eventStart = new Date("2026-04-10");
const eventEnd = new Date("2026-04-15");
// Verificar se uma data está dentro do intervalo
isWithinInterval(new Date("2026-04-12"), {
start: eventStart,
end: eventEnd,
}); // true
// Dias úteis entre datas (exclui fins de semana)
differenceInBusinessDays(eventEnd, eventStart); // 3
// Verificar sobreposição de intervalos
areIntervalsOverlapping(
{ start: eventStart, end: eventEnd },
{ start: new Date("2026-04-13"), end: new Date("2026-04-20") }
); // trueAnálise de strings de data personalizadas:
import { parse, isValid } from "date-fns";
const date = parse("04/06/2026", "MM/dd/yyyy", new Date());
console.log(isValid(date)); // true
const invalid = parse("not-a-date", "MM/dd/yyyy", new Date());
console.log(isValid(invalid)); // falseDate ou number (timestamp) como argumentos de dataformat retorna string, addDays retorna Date, differenceInDays retorna numberdate-fns/locale@types adicional é necessário; os tipos estão incluídos em date-fnsimport type { Locale } from "date-fns";
import { fr } from "date-fns/locale";
function formatDate(date: Date | number, locale: Locale = fr): string {
return format(date, "PPP", { locale });
}Confusão de fuso horário - Objetos Date estão sempre no fuso horário local. format produz tempo local, não UTC. Correção: Use date-fns-tz para formatação ciente de fuso horário, ou use formatInTimeZone de date-fns-tz.
Sensibilidade a maiúsculas/minúsculas dos tokens de formato - MM é mês, mm são minutos. DD não é válido (use dd). Correção: Consulte a tabela de tokens de formato. Tokens comuns: yyyy-MM-dd HH:mm:ss.
parseISO vs new Date - new Date("2026-04-06") é analisado como meia-noite UTC, mas exibido no horário local, o que pode alterar a data. Correção: Sempre use parseISO para strings ISO para obter comportamento consistente.
Armadilha de Date mutável - Embora as funções date-fns sejam puras, se você passar a mesma instância de Date para vários locais após mutá-la em outro lugar, obterá resultados inesperados. Correção: Crie novas instâncias de Date ou use os valores de retorno das funções date-fns.
Tamanho do bundle com locales - Importar todos os locales adiciona um tamanho significativo ao bundle. Correção: Importe apenas os locales que você precisa: import { fr } from "date-fns/locale", não import * as locales from "date-fns/locale".
Diferença de data servidor/cliente - Datas renderizadas no servidor usam o fuso horário do servidor, causando dessincronizações de hidratação. Correção: Formate as datas apenas no lado do cliente, ou passe strings pré-formatadas do servidor, ou use suppressHydrationWarning no elemento <time>.
| Biblioteca | Ideal para | Contraponto |
|---|---|---|
| date-fns | API funcional, com tree-shaking | Sem suporte a fuso horário sem date-fns-tz |
| dayjs | Substituição direta do Moment.js (2KB) | Baseado em plugins, API mutável |
| Temporal (proposta) | Futura API nativa de data JS | Ainda não disponível em todos os runtimes |
| Luxon | Suporte completo a fuso horário e i18n | Bundle maior (cerca de 20KB) |
| Moment.js | Apenas projetos legados | Descontinuado, 67KB minificado, mutável |
new Date("2026-04-06") é analisado como meia-noite UTC, mas exibido no horário local, o que pode alterar a data em um diaparseISO lida com strings ISO 8601 de forma consistente em todos os navegadoresimport { formatDistanceToNow } from "date-fns";
formatDistanceToNow(someDate, { addSuffix: true });
// "2 horas atrás" ou "em 3 dias"A opção addSuffix adiciona "em" ou "atrás" automaticamente.
MM = mês (01-12), mm = minutos (00-59)DD não é válido -- use dd para dia do mêsyyyy-MM-dd HH:mm:ssimport { startOfMonth, endOfMonth, eachDayOfInterval } from "date-fns";
const start = startOfMonth(new Date());
const end = endOfMonth(new Date());
const days = eachDayOfInterval({ start, end });import { format } from "date-fns";
import { fr } from "date-fns/locale";
format(new Date(), "EEEE d MMMM yyyy", { locale: fr });
// "lundi 6 avril 2026"Importe apenas os locales que você precisa para manter o tamanho do bundle pequeno.
differenceInDays calcula com base em períodos completos de 24 horasdifferenceInCalendarDays conta as fronteiras de dias de calendário cruzadasdifferenceInDays, mas 1 com differenceInCalendarDaysimport { isWithinInterval } from "date-fns";
isWithinInterval(new Date("2026-04-12"), {
start: new Date("2026-04-10"),
end: new Date("2026-04-15"),
}); // truesuppressHydrationWarning no elemento <time>Date usam o fuso horário localdate-fns-tz para formatação ciente de fuso horárioformatInTimeZone para exibir datas em um fuso horário específicoimport type { Locale } from "date-fns";
import { format } from "date-fns";
function formatDate(
date: Date | number,
pattern: string = "PPP",
locale?: Locale
): string {
return format(date, pattern, { locale });
}Todas as funções date-fns aceitam Date | number como argumentos de data.
import { parse, isValid } from "date-fns";
const date = parse("04/06/2026", "MM/dd/yyyy", new Date());
console.log(isValid(date)); // trueSempre valide com isValid, pois parse retorna uma Date inválida para entradas incorretas.
import { format } from "date-fns" inclui apenas format e suas dependênciasimport * as dateFns from "date-fns", que anula o tree-shakingRevisado por Chris St. John·Última atualização: 19 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥