Como calcular períodos de tempo em projetos reais
O cálculo de períodos de tempo parece simples até você precisar lidar com fusos horários, dias que não existem em alguns meses, ou queries que levam minutos para rodar em datasets grandes. Eu já vi gente perder meia manhã resolvendo algo que deveria levar cinco minutos.
Definição prática de período de tempo
Um período de tempo é basicamente uma diferença entre dois pontos temporais. Pode ser dias, horas, minutos, ou segundos. A complicação vem quando você precisa fazer isso de forma consistente em diferentes contextos — planilhas, bancos de dados, scripts — e cada ferramenta se comporta de um jeito diferente. No Python com pandas, por exemplo, você trabalha com o tipo timedelta. Na prática, subtrair duas colunas de data já te dá o período em dias. Multiplicar por 24, 1440 ou 86400 te coloca em horas, minutos ou segundos. Simples, até você tentar calcular períodos que atravessam o horário de verão. Foi exatamente isso que aconteceu num projeto meu: o fuso horário de Brasília mudou em 2018 e uma query que calculava horas trabalhadas ficou 1 hora errada em 15 dias por ano. A solução foi converter tudo para UTC antes de qualquer cálculo.
Em SQL, a função varia conforme o banco. O PostgreSQL tem o operador de subtração direto entre timestamps, enquanto o MySQL usa DATEDIFF que só dá dias. O SQL Server devolve intervalos com DATEADD e DATEDIFF combinados. O problema comum aqui é que muitos devs não percebem que DATEDIFF(date, start, end) no MySQL conta quantas fronteiras de unidade foram cruzadas, não o valor real da diferença. Se você subtrai 23:00 de 01:00 do dia seguinte com DATEDIFF(hour, ...), o resultado é 1, mas a diferença real é 2 horas.
Métodos pelos principais cenários
Vou abordar os três que aparecem com mais frequência no dia a dia de quem trabalha com dados.
Período de tempo em Python com pandas
O formato mais direto é usar pd.to_datetime() para garantir que suas colunas sejam objetos datetime, depois subtrair. O resultado é um objeto timedelta64 que você converte para a unidade que precisa.
import pandas as pd
df = pd.DataFrame({
'inicio': ['2024-01-15 08:30:00', '2024-03-20 14:00:00'],
'fim': ['2024-01-15 17:45:00', '2024-03-20 19:30:00']
})
df['inicio'] = pd.to_datetime(df['inicio'])
df['fim'] = pd.to_datetime(df['fim'])
df['periodo_dias'] = (df['fim'] - df['inicio']).dt.days
df['periodo_horas'] = (df['fim'] - df['inicio']).dt.total_seconds() / 3600
df['periodo_minutos'] = (df['fim'] - df['inicio']).dt.total_seconds() / 60
A função total_seconds() é o segredo aqui. Ela retorna o total como um float, então você divide pela unidade desejada. Se usar apenas .seconds, ela retorna apenas a porção de segundos dentro do dia (0-86399), o que quebra cálculos de períodos maiores que 24 horas. Outro ponto que muita gente erra: se seus dados vêm de arquivos CSV com datas em formatos diferentes misturados, o pandas pode inferir tipos errados. Sempre passe format='mixed' ou defina o formato explicitamente no argumento parser_dates.
Período de tempo em SQL
Dependendo do SGBD, a abordagem muda. No PostgreSQL, o cálculo mais limpo é subtrair dois timestamp e extrair o campo que precisa:
SELECT
inicio,
fim,
EXTRACT(EPOCH FROM (fim - inicio)) / 3600 AS horas
FROM eventos;
O EXTRACT(EPOCH FROM ...) converte o intervalo para segundos, e a divisão por 3600 dá horas. Funciona para minutos (÷60), dias (÷86400), etc. No MySQL 8+, a função TIMESTAMPDIFF() é a mais prática:
👉 Clique no botão abaixo para saber mais sobre o assunto!
SELECT
TIMESTAMPDIFF(HOUR, inicio, fim) AS horas,
TIMESTAMPDIFF(MINUTE, inicio, fim) AS minutos,
TIMESTAMPDIFF(DAY, inicio, fim) AS dias
FROM eventos;
E no SQL Server, o DATEDIFF() funciona mas com a ressalva que citei acima sobre fronteira de unidade. Para valores exatos, prefira DATEDIFF(second, inicio, fim) e faça a conversão depois:
SELECT
DATEDIFF(second, inicio, fim) / 3600.0 AS horas,
DATEDIFF(minute, inicio, fim) % 60 AS minutos_resto
FROM eventos;
Usar / 3600.0 (com ponto decimal) força divisão de ponto flutuante, senão o SQL Server truncateia o resultado.
Período de tempo em Excel e Google Sheets
Aqui a coisa é mais simples mas armadilhosa. Dates em planilhas são armazenados como números inteiros (dias desde 1900 no Excel, desde 1899 no Sheets). Horas são frações. Então subtrair duas células de data já te dá o período em dias. Para horas: = (B2 - A2) * 24. Para minutos: = (B2 - A2) * 1440. O formato da célula de resultado precisa ser ajustado manualmente para mostrar décimos de hora corretamente, senão o Excel arredonda.
Uma armadilha clássica: se você usa DIFDIA() no Excel, ele considera apenas dias completos e ignora horas. Para precisão horária, sempre calcule pela subtração direta multiplicada pelo fator.
Edge cases que todo mundo esquece
Dias que não existem. 29 de fevereiro em anos não bissextos. Quando você subtrai 1º de março de 1º de fevereiro em um ano não bissexto, o resultado são 28 dias. Em um bissexto, são 29. Isso parece óbvio mas causa bugs silenciosos em relatórios mensais que assumem 30 dias fixos. Fusos horários. Se seus dados vêm de múltiplas fontes com fusos diferentes e você não normaliza para UTC antes de calcular, o período pode ficar errando de 1 a 12 horas dependendo da origem. Eu vi um relatório de uptime que mostrava 99,97% quando na verdade era 99,23% porque dois servidores estavam em fusos distintos e a subtração não considerou o offset.
Intervalos de tempo com milliseconds. O pandas lida bem com isso nativamente. O SQL padrão nem sempre. Se você precisa de precisão sub-horária em banco de dados, use timestamps com fração de segundo e extrai o epoch em microssegundos.
Quando calcular período de tempo não funciona bem
Em datasets muito grandes no SQL, calcular períodos em cada linha pode ser custoso. Se você tem milhões de registros e precisa de períodos relativos, é mais eficiente criar uma tabela intermediária com as datas base e fazer join, em vez de calcular tudo no SELECT. A diferença costuma ser de segundos para minutos em queries com mais de 100k linhas. Também não adianta confiar cegamente em funções de alto nível. O DATE_DIFF() do BigQuery, por exemplo, tem comportamento diferente do DATEDIFF do SQL Server quando envolve DST. Sempre valide com um subset conhecido antes de aplicar ao dataset todo.
Se o seu cenário envolve períodos recorrentes complexos — como "últimoFridaydoMês" ou "30 dias corridos a partir de uma data variável" — ferramentas como o módulo dateutil do Python ou o temporal do DuckDB são mais adequadas que cálculos manuais com delta.
Resumo rápido de período de tempo
A regra prática é: normalize fusos primeiro, depois subtraia, depois converta para a unidade desejada usando o fator correto. Use total_seconds() no Python em vez de seconds. Cuidado com fronteira de unidade no SQL Server. E nunca assuma 30 dias por mês sem verificar se o seu caso específico exige dias corridos ou dias comerciais. Isso resolve a maioria dos problemas. O resto é caso por caso.