.NET DateTime to UnixTime (y viceversa)

En algunas ocasiones tenemos que interactuar con sistemas que tiene este tipo de fecha: 1183875671, hombre que no siempre las fechas van a estar como nosotros queremos :D. Cuando lo vi inicialmente, sólo por el título imagine que era una fecha, pero no tenía la certeza de que unidad de medida era o en que formato estaba. Pero gracias a mi amigo Necudeco, un poco exagerado en algunos post pero con mucho conocimiento, que me comentó que era una fecha en formato Unixstamp, o Unixtime, o en algunos casos lo conocen como Timestamp, que no es lo mismo que timeSpan.

El Unixtimestamp, no es otra cosa que el número de segundos transcurridos desde la 0 horas del 1 de enero de 1970.

Ahora un tipo DateTime de .NET, tiene una propiedad llamada DateTime.Ticks, que es lo más parecido al UnixTime, pero la propiedad DateTime.Ticks tiene otra unidad de medida: representa el número de intervalos de 100 nanosegundos transcurridos desde las 0 horas del 1 de enero de 0001.

Entonces tenemos que:

  • 1 Tick = 100 nseg;
  • 1 seg = 10^9 nseg;

Entonces si queremos convertir un DateTime a UnixTime, recordamos nuestra clase de unidades de medida y conversiones, que si mal no recuerdo, un sólo profesor me explico bien ese tema, y aquella vez entendí porque al multiplicar velocidad(m/s) por tiempo (s) te da la distancia recorrida (m) o lo entendí solo, bueno en este momento lo importante es que lo sé :D,y como decía, aprendí que no tenía que hacer fichas que recordar las formulas para los exámenes, bastaba con saber las unidades de medida que te daban y el resto estaba hecho, aunque si trabajabas con velocidad instantánea, las derivadas eran otro tema. Otro tip, es que al usar unidades en cualquier operación puedes descubrir errores en el copiado de una fórmula, que si multiplicas pisco peruano por jarabe de goma no te va dar pisco a al cuadrado, pero si te da un verdadero Pisco Sour piñas por papayas no te va dar piñas al cuadrado, a lo mucho te puede dar un buen jugo :).

Volviendo al tema, utilizando la misma regla de conversiones que usaba en la universidad, tenemos que: si queremos ir de DateTime, usaremos la medida en Ticks (Y ticks), a UnixTime (X seg) en segundos, o viceversa:

Pero ahora llevémoslo a funciones, en C# :d:

Conversión de DateTime to UnixTime

En un programa del tipo consola podemos hacer esto, o si tienes el .NET Framework instalado, y le echas mano al notepad++, también puedes hacerlo:

Variables comunes:

   1: static Int64 SecInNasec = Convert.ToInt64(Math.Pow(10, 9));
   2: static Int64 OneTick = 100;
   3: static Int32 AnioBase = 1970 - 1;

Y aunque es que difícil que los datos de este formato cambien, así lo veo más ordenado. Ahora vayamos con la función para convertir un DateTime a Unixtime:

   1: public static Int64 ToUnixTime(DateTime dateTime) 
   2: {
   3:    DateTime time = dateTime.AddYears(-AnioBase);
   4:  
   5:    Int64 unixTime = (time.Ticks*OneTick)/SecInNasec;
   6:  
   7:    return unixTime;
   8: }

Le resto los años de diferencia, ya que recuerden que Ticks es desde el año 1 en cambio UnixTime desde el año 1970. Después multiplico los ticks de la fecha, por 100 nseg/ticks, y por último lo dívido entre 10^9 nseg/seg, quedando el resultado en segundos :D.

Ahora para la función para convertir un Unixtime a DateTime quedaría así:

   1: public static DateTime FromUnixTime(Int64 unixTime)
   2: {                  
   3:    DateTime time = new DateTime((unixTime*SecInNasec)/OneTick);
   4:  
   5:    time = time.AddYears(AnioBase);
   6:  
   7:    return time;
   8:  
   9: }

Multiplicamos los segundos del unixTime por 10^9 nseg/seg, y eso lo dividimos entre 100 nseg/ticks, quedando el resultado en ticks :D, que es lo que necesita el constructor del DateTime para crear una fecha, pero recuerden que los segundos era del año 1, por eso hay que agregar los años de diferencia :).

Y por último para probar nuestra funciones en el main:

   1: static void Main(string[] args)
   2: {
   3:  
   4:    Int64 unixOriginal = 1183875671;
   5:    DateTime commonFormat = FromUnixTime(unixOriginal);
   6:    Int64 unixNow = ToUnixTime(commonFormat);
   7:  
   8:    Console.WriteLine("nombre original: {0}", 
   9:             unixOriginal);
  10:    Console.WriteLine("en fecha normal: {0}, y la hora: {1}",
  11:             commonFormat.ToLongDateString(),
  12:             commonFormat.ToLongTimeString());
  13:    Console.WriteLine("unixStamp original: {0}", 
  14:             unixNow);
  15:  
  16:    Console.ReadLine();
  17:  
  18: }

Otros post relacionados:

P.D.: Por cierto en UnixTimeStamp.com, calcula el Unixtime pero en -5 GMT, y antes de que empiecen a pifiar si notan que el algoritmo de esta entrada no coincide con ese resultado :D, prueben poniendo 1 en esa web para que se den cuenta.

Saludos,

Post cruzado

2 comentarios en “.NET DateTime to UnixTime (y viceversa)”

  1. Esta parecía una solución elegante pero está errada. Ha pasado mucho tiempo de este post pero por si alguien vuelve a entrar aquí le advierto que hay un bug.

    La idea detrás del método ToUnixTime(DateTime dateTime) es restar la base para así tener como una fecha el tiempo total transcurrido. Hagan un Debug con la fecha dd/MM/yy 29/02/2000. El DateTime va a tomar el valor “28/02/0031”. Ya se pueden dar cuenta del error.

    Les recomiendo algo más simple :

    DateTime d = new DateTime(2009, 02, 13, 20, 31, 30);
    d = d.ToUniversalTime();
    double unixtime =(d – new DateTime(1970, 1, 1)).TotalSeconds;

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *