De segundos a años: calculando el tiempo relativo en C# correctamente

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: ¿Por qué necesitamos el «tiempo relativo»?

\n\n

¿Alguna vez te has preguntado por qué las redes sociales y los sitios de noticias escriben «hace 2 horas» o «ayer», y no «25.04.2025 14:32»? Porque nuestro cerebro procesa el tiempo relativo mucho más rápido. Una fecha absoluta requiere análisis: «Bien, hoy es 25, entonces eso fue…». Una fecha relativa da la respuesta al instante.

\n\n

Si programas en C# — ya sea una aplicación web en ASP.NET, una aplicación de escritorio o un bot de Telegram — tarde o temprano necesitarás mostrar al usuario la hora en formato «justo ahora», «hace 3 minutos» o «hace aproximadamente un año». En Stack Overflow, la pregunta «Calculate relative time in C#» ha acumulado miles de visitas, lo que significa que es un verdadero dolor de cabeza para los desarrolladores.

\n\n

En este artículo, analizaremos la forma más correcta y flexible de calcular el tiempo relativo en C#. Obtendrás código listo para usar que puedes insertar directamente en tu proyecto, entenderás cómo funciona y aprenderás a personalizarlo para cualquier necesidad.

\n\n

El problema: ¿qué tiene de malo la simple resta de fechas?

\n\n

Lo primero que viene a la mente es restar una fecha de otra y obtener un TimeSpan. Sí, funciona. Pero el diablo está en los detalles:

\n\n
    \n
  • Valores umbral. ¿Cuándo termina un «minuto» y comienza una «hora»? ¿Y cuándo una «hora» pasa a ser un «día»?
  • \n
  • Fechas futuras. ¿Qué pasa si la fecha está en el futuro? ¿Mostrar «dentro de 5 minutos» o «dentro de 1 día»?
  • \n
  • Legibilidad del código. Si dispersas la lógica por todo el proyecto, en un mes te confundirás tú mismo.
  • \n
\n\n

Por lo tanto, no necesitamos solo un fragmento de código, sino un método único y reutilizable.

\n\n

Solución: método universal para calcular el tiempo relativo

\n\n

La mejor manera es escribir un único método estático que tome un DateTime (o DateTimeOffset) y devuelva una cadena formateada. Aquí tienes una implementación básica pero ya muy potente, que se puede encontrar en discusiones de Stack Overflow y adaptar a tus necesidades:

\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 en la misma zona horaria!\n        var timeSpan = now - dateTime;\n\n        // Caso 1: fecha futura\n        if (timeSpan.TotalSeconds < 0)\n        {\n            // Calculamos el valor absoluto para el futuro\n            timeSpan = timeSpan.Duration();\n            if (timeSpan.TotalMinutes < 1)\n                return "dentro de unos segundos";\n            if (timeSpan.TotalMinutes < 60)\n                return $"dentro de {timeSpan.Minutes} min.";\n            if (timeSpan.TotalHours < 24)\n                return $"dentro de {timeSpan.Hours} h.";\n            if (timeSpan.TotalDays < 30)\n                return $"dentro de {timeSpan.Days} d.";\n            if (timeSpan.TotalDays < 365)\n                return $"dentro de {timeSpan.Days / 30} meses.";\n            return $"dentro de {timeSpan.Days / 365} años.";\n        }\n\n        // Caso 2: pasado\n        if (timeSpan.TotalMinutes < 1)\n            return "justo ahora";\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} d. atrás";\n\n        // Para fechas de más de una semana, usamos días\n        if (timeSpan.TotalDays < 30)\n            return $"{(int)timeSpan.TotalDays} d. 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} años atrás";                

Blogs

Book Recommendations