2010-05-21 15 views
275

¿Cómo se convierte Unix epoch time en tiempo real en C#? (Época comenzando 1/1/1970)¿Cómo se convierte el tiempo de época en C#?

+1

A menos que me falta algo, la "época" es simplemente el punto de origen de un esquema de tiempo particular. Los ejemplos incluyen 1/1/0001, 1/1/1970 y 1/1/2000. Es más un atributo de un esquema que un esquema (por ejemplo, Julian). –

+5

El tiempo desde la época es el número de segundos desde el 1 de enero de 1970 UTC. –

+12

@Taylor Esa es la época del tiempo de Unix, y probablemente sea la correcta, pero no es la única época válida. Los usuarios del tiempo de Unix no deben confundirse en ese punto. –

Respuesta

441

supongo que quiere decir Unix time, que se define como el número de segundos transcurridos desde la medianoche (GMT) el 1 de enero de 1970.

public static DateTime FromUnixTime(long unixTime) 
{ 
    return epoch.AddSeconds(unixTime); 
} 
private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 
+52

Para que esto funcione correctamente, tuve que cambiar .AddSeconds a .AddMilliseconds. Tendrá que saber si su número proviene de Segundos o Milisegundos para obtener el resultado correcto. Entonces, por ejemplo, la siguiente fecha: 1406310305188 (25 de julio de 2014).http://www.epochconverter.com/ también le permitirá verificar sus resultados de conversión. – jrandomuser

+3

Debe cambiar el tipo de parámetro a double (porque AddSeconds acepta el doble y, por lo tanto, downcast al doble) o agregar un descargo a la descripción del método de que solo se conservarán 53 de 64 bits de precisión en el argumento. – tomosius

+3

@jrandomuser: el tiempo de época de Unix se representa tradicionalmente como * segundos * desde The Epoch. Desde entonces, es común usar * milisegundos * desde The Epoch (por ejemplo, JavaScript), pero la definición clásica es segundos. En resumen, simplemente sepa cuál es su valor de entrada (segundos, milisegundos, tics, lo que sea) y utilice el método correcto de 'AddXYZ'. –

135

Con todo el crédito a LukeH , he reunido algunos métodos de extensión para un uso fácil:

public static DateTime FromUnixTime(this long unixTime) 
{ 
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 
    return epoch.AddSeconds(unixTime); 
} 

public static long ToUnixTime(this DateTime date) 
{ 
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 
    return Convert.ToInt64((date - epoch).TotalSeconds); 
} 

Nota del comentario abajo desde CodesInChaos que lo anterior FromUnixTime devuelve un DateTime con un Kind de Utc, lo cual está bien, pero el ab ove ToUnixTime es mucho más sospechoso en que no cuenta para qué tipo de DateTime es date dado. Para permitir la date 's Kind siendo ya sea Utc o Local, utilice ToUniversalTime:

public static long ToUnixTime(this DateTime date) 
{ 
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 
    return Convert.ToInt64((date.ToUniversalTime() - epoch).TotalSeconds); 
} 

ToUniversalTime convertirá una Local (o Unspecified) DateTime-Utc.

si no desea crear la época ejemplo DateTime cuando se pasa de DateTime de época o también se puede hacer:

public static long ToUnixTime(this DateTime date) 
{ 
    return (date.ToUniversalTime().Ticks - 621355968000000000)/10000000; 
} 
+5

'ToUnixTime' solo funciona correctamente si la fecha está en Utc. Agregue un cheque o conviértalo. (Personalmente prefiero el cheque) – CodesInChaos

+1

Acabo de pasar la última hora averiguando por qué esto no funciona. ¡Tienes que trabajar en 'milisegundos' * no * segundos !!! – KristianB

+7

@KristianB: "Tiempo Unix" es tradicionalmente segundos, no milisegundos, desde La Época, aunque en estos días tengo cuidado de comprobar qué definición está usando alguien. Los segundos solían ser lo suficientemente buenos y nos daban un rango razonable a cada lado de La Época en valores de 32 bits con signo. (Y es por eso que justo después de las 3:14 a. M. El 19 de enero, 2038 GMT podría ser un mal momento para algunos ...) Usar milisegundos es una práctica más moderna gracias a que podemos arrojar rutinariamente valores de 64 bits (ambos integrales) y doble precisión IEEE-754) ... –

6
// convert datetime to unix epoch seconds 
public static long ToUnixTime(DateTime date) 
{ 
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 
    return Convert.ToInt64((date.ToUniversalTime() - epoch).TotalSeconds); 
} 

En caso de utilizar ToUniversalTime() para el objeto DateTime.

17

En realidad quiere agregar milisegundos (milisegundos), no segundos. Agregar segundos le dará una excepción fuera de rango.

+0

¿Por qué es eso? http://www.epochconverter.com/ Dice que agregas el número de segundos desde 1/1/970 no ms. –

+0

Si va desde MS, obviamente quiere 'AddMillis' y si está empezando desde segundos, obviamente quiere' AddSeconds'. – Shoe

+0

Tuve el mismo problema que era seguir saliendo del alcance cuando usaba segundos. El tiempo Unix que estaba intentando convertir estaba en milisegundos. Pensé que era en segundos. Supongo que algún tiempo Unix se mide en milisegundos. – DoodleKana

-3

Aquí está mi solución:

public long GetTime() 
{ 
    DateTime dtCurTime = DateTime.Now.ToUniversalTime(); 

    DateTime dtEpochStartTime = Convert.ToDateTime("1/1/1970 0:00:00 AM"); 

    TimeSpan ts = dtCurTime.Subtract(dtEpochStartTime); 

    double epochtime; 

    epochtime = ((((((ts.Days * 24) + ts.Hours) * 60) + ts.Minutes) * 60) + ts.Seconds); 

    return Convert.ToInt64(epochtime); 
} 
+7

¿esto cuenta para los años bisiestos y los segundos intercalares, etc.? – Jodrell

+1

Para ampliar el comentario anterior, aquí hay un breve video que explica por qué el tiempo es complicado y por qué no debes intentar hacerlo tú mismo: https://www.youtube.com/watch?v=-5wpm-gesOY – vmrob

0

En caso de que necesite para convertir un timeval struct (segundos, microsegundos) que contiene UNIX time a DateTime sin perder precisión, esta es la forma:

DateTime _epochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 
private DateTime UnixTimeToDateTime(Timeval unixTime) 
{ 
    return _epochTime.AddTicks(
     unixTime.Seconds * TimeSpan.TicksPerSecond + 
     unixTime.Microseconds * TimeSpan.TicksPerMillisecond/1000); 
} 
117

El latest version of .Net (v4.6) acaba de agregar compatibilidad integrada para las conversiones de tiempo de Unix. Eso incluye el tiempo hacia y desde Unix representado por segundos o milisegundos.

  • tiempo Unix en cuestión de segundos a DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000); 
  • DateTimeOffset a tiempo Unix en segundos:

long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds(); 
  • tiempo Unix en milisegundos para DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000); 
  • DateTimeOffset a tiempo Unix en milisegundos:

long unixTimeStampInMilliseconds= dateTimeOffset.ToUnixTimeMilliseconds(); 

Nota: Estos métodos se convierten en y desde DateTimeOffset. Para obtener una representación DateTime simplemente use el DateTimeOffset.DateTime propiedad:

DateTime dateTime = dateTimeOffset.UtcDateTime; 
+0

Yo soy obteniendo ''DateTimeOffset' no contiene una definición para 'FromUnixTimeSeconds'' ¿Cómo voy a resolver esto? –

+0

@HappyBird ¿Estás en .NET 4.6 o superior? – i3arnon

0

Si no está utilizando 4.6, esto puede ayudar a Fuente:System.IdentityModel.Tokens

/// <summary> 
    /// DateTime as UTV for UnixEpoch 
    /// </summary> 
    public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 

    /// <summary> 
    /// Per JWT spec: 
    /// Gets the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the desired date/time. 
    /// </summary> 
    /// <param name="datetime">The DateTime to convert to seconds.</param> 
    /// <remarks>if dateTimeUtc less than UnixEpoch, return 0</remarks> 
    /// <returns>the number of seconds since Unix Epoch.</returns> 
    public static long GetIntDate(DateTime datetime) 
    { 
     DateTime dateTimeUtc = datetime; 
     if (datetime.Kind != DateTimeKind.Utc) 
     { 
      dateTimeUtc = datetime.ToUniversalTime(); 
     } 

     if (dateTimeUtc.ToUniversalTime() <= UnixEpoch) 
     { 
      return 0; 
     } 

     return (long)(dateTimeUtc - UnixEpoch).TotalSeconds; 
    }  
4

utilizo siguientes métodos de extensión para la conversión época

public static int GetEpochSeconds(this DateTime date) 
    { 
     TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1); 
     return (int)t.TotalSeconds; 
    } 

public static DateTime FromEpochSeconds(this DateTime date, long EpochSeconds) 
    { 
     var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 
     return epoch.AddSeconds(EpochSeconds); 

    } 
1

Si desea un mejor rendimiento, puede utilizar esta versión.

public const long UnixEpochTicks = 621355968000000000; 
public const long TicksPerMillisecond = 10000; 
public const long TicksPerSecond = TicksPerMillisecond * 1000; 

//[MethodImpl(MethodImplOptions.AggressiveInlining)] 
public static DateTime FromUnixTimestamp(this long unixTime) 
{ 
    return new DateTime(UnixEpochTicks + unixTime * TicksPerSecond); 
} 

De referencia rápida (BenchmarkDotNet) bajo net471 consigo este número:

 Method |  Mean |  Error | StdDev | Scaled | 
-------------- |---------:|----------:|----------:|-------:| 
StackOverflow | 5.897 ns | 0.0897 ns | 0.0795 ns | 1.00 | 
     MyCustom | 3.176 ns | 0.0573 ns | 0.0536 ns | 0.54 | 

2 veces más rápido contra la versión LukeH (si el mater rendimiento)

Esto es similar cómo DateTime trabajo internamente.

Cuestiones relacionadas