De segundos a anos: calculando tempo relativo em C# corretamente

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que precisamos de "tempo relativo"?

\n\n

Você já se perguntou por que as redes sociais e sites de notícias escrevem "2 horas atrás" ou "ontem", em vez de "25.04.2025 14:32"? Porque nosso cérebro processa o tempo relativo muito mais rápido. Uma data absoluta exige análise: "Ok, hoje é dia 25, então isso foi...". Uma data relativa dá a resposta instantaneamente.

\n\n

Se você programa em C# — seja uma aplicação web em ASP.NET, um aplicativo desktop ou um bot do Telegram — mais cedo ou mais tarde precisará mostrar ao usuário o tempo no formato "agora mesmo", "3 minutos atrás" ou "cerca de um ano atrás". No Stack Overflow, a pergunta "Calculate relative time in C#" acumulou milhares de visualizações, o que significa que é uma verdadeira dor de cabeça para os desenvolvedores.

\n\n

Neste artigo, vamos analisar a maneira mais correta e flexível de calcular o tempo relativo em C#. Você receberá um código pronto que pode ser inserido diretamente no seu projeto, entenderá como ele funciona e aprenderá a personalizá-lo para qualquer necessidade.

\n\n

O problema: o que há de errado com a simples subtração de datas?

\n\n

A primeira coisa que vem à mente é subtrair uma data da outra e obter um TimeSpan. Sim, isso funciona. Mas o diabo está nos detalhes:

\n\n
    \n
  • Valores limite. Quando termina o "minuto" e começa a "hora"? E quando a "hora" se transforma em "dia"?
  • \n
  • Datas futuras. E se a data estiver no futuro? Mostrar "em 5 minutos" ou "em 1 dia"?
  • \n
  • Legibilidade do código. Se você espalhar a lógica por todo o projeto, em um mês você mesmo ficará confuso.
  • \n
\n\n

Portanto, não precisamos apenas de um trecho de código, mas de um método único e reutilizável.

\n\n

Solução: método universal para cálculo de tempo relativo

\n\n

A melhor maneira é escrever um único método estático que receba um DateTime (ou DateTimeOffset) e retorne uma string bonita. Aqui está uma implementação básica, mas já muito poderosa, que pode ser encontrada em discussões no Stack Overflow e adaptada às suas necessidades:

\n\n
using System;\n\npublic static class TimeHelper\n{\n    public static string GetRelativeTime(DateTime dateTime)\n    {\n        var now = DateTime.Now;\n        var utcNow = DateTime.UtcNow;\n\n        // Importante: comparar no mesmo fuso horário!\n        var timeSpan = now - dateTime;\n\n        // Caso 1: data no futuro\n        if (timeSpan.TotalSeconds < 0)\n        {\n            // Calcula o valor absoluto para o futuro\n            timeSpan = timeSpan.Duration();\n            if (timeSpan.TotalMinutes < 1)\n                return "em alguns segundos";\n            if (timeSpan.TotalMinutes < 60)\n                return $"em {timeSpan.Minutes} min.";\n            if (timeSpan.TotalHours < 24)\n                return $"em {timeSpan.Hours} h.";\n            if (timeSpan.TotalDays < 30)\n                return $"em {timeSpan.Days} dias";\n            if (timeSpan.TotalDays < 365)\n                return $"em {timeSpan.Days / 30} meses";\n            return $"em {timeSpan.Days / 365} anos";\n        }\n\n        // Caso 2: passado\n        if (timeSpan.TotalMinutes < 1)\n            return "agora mesmo";\n        if (timeSpan.TotalMinutes < 60)\n            return $"{timeSpan.Minutes} min. atrás";\n        if (timeSpan.TotalHours < 24)\n            return $"{timeSpan.Hours} h. atrás";\n        if (timeSpan.TotalDays < 7)\n            return $"{timeSpan.Days} dias atrás";\n\n        // Para datas com mais de uma semana, usamos dias\n        if (timeSpan.TotalDays < 30)\n            return $"{(int)timeSpan.TotalDays} dias atrás";\n        if (timeSpan.TotalDays < 365)\n        {\n            int months = (int)(timeSpan.TotalDays / 30);\n            return $"{months} meses atrás";\n        }\n\n        int years = (int)(timeSpan.TotalDays / 365);\n        return $"{years} anos atrás";                

Blogs

Book Recommendations