¿Cómo se convierte el tiempo de época de Unix en tiempo real en C #? (Época comenzando el 1/1/1970)
¿Cómo se convierte el tiempo de época de Unix en tiempo real en C #? (Época comenzando el 1/1/1970)
Respuestas:
Supongo que te refieres a la hora de Unix , que se define como el número de segundos desde la medianoche (UTC) del 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);
AddXYZ
método correcto .
La última versión de .Net (v4.6) acaba de agregar soporte incorporado para las conversiones de tiempo Unix. Eso incluye el tiempo hacia y desde Unix representado por segundos o milisegundos.
DateTimeOffset
:DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
DateTimeOffset
al tiempo de Unix en segundos:long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
DateTimeOffset
:DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
DateTimeOffset
al tiempo Unix en milisegundos:long unixTimeStampInMilliseconds= dateTimeOffset.ToUnixTimeMilliseconds();
Nota: Estos métodos convierten desde y hacia DateTimeOffset
. Para obtener una DateTime
representación simplemente use la DateTimeOffset.DateTime
propiedad:
DateTime dateTime = dateTimeOffset.UtcDateTime;
'DateTimeOffset' does not contain a definition for 'FromUnixTimeSeconds'
¿Cómo haría para resolver esto?
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);
}
Tenga en cuenta el siguiente comentario de CodesInChaos de que lo anterior FromUnixTime
devuelve un DateTime
con a Kind
de Utc
, lo cual está bien, pero lo anterior ToUnixTime
es mucho más sospechoso porque no explica qué tipo de DateTime
dato date
es. Para permitir date
's Kind
ser cualquiera Utc
o Local
, el uso 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á un Local
(o Unspecified
) DateTime
a Utc
.
si no desea crear la instancia de epoch DateTime al pasar de DateTime a epoch, también puede hacer:
public static long ToUnixTime(this DateTime date)
{
return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
}
ToUnixTime
solo funciona correctamente si la fecha está en Utc. Agregue un cheque o conviértalo. (Personalmente prefiero el cheque)
milliseconds
no segundos!
AddMilliseconds
y debe usar Double NOT Float. De lo contrario, terminarás con un mal momento.
En realidad, desea agregar milisegundos (milisegundos), no segundos. Agregar segundos le dará una excepción fuera de rango.
AddMillis
y si comienza desde segundos, obviamente desea AddSeconds
.
Si desea un mejor rendimiento, puede usar 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 un punto de referencia rápido (BenchmarkDotNet) bajo net471 obtengo este número:
Method | Mean | Error | StdDev | Scaled |
-------------- |---------:|----------:|----------:|-------:|
LukeH | 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 de LukeH (si es el rendimiento mater)
Esto es similar al funcionamiento interno de DateTime.
Use el método DateTimeOffset.ToUnixTimeMilliseconds () Devuelve el número de milisegundos que han transcurrido desde 1970-01-01T00: 00: 00.000Z.
Esto solo es compatible con Framework 4.6 o superior
var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
Está bien documentado aquí DateTimeOffset.ToUnixTimeMilliseconds
La otra salida es usar lo siguiente
long EPOCH = DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1,0,0,0,0).Ticks;
Para obtener el EPOCH con solo segundos, puede usar
var Epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
y convertir el Epoch
a DateTime
con el siguiente método
private DateTime Epoch2UTCNow(int epoch)
{
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(epoch);
}
.Ticks
, uno obtendría una buena instancia de TimeSpan de la resta de DateTime.
// 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);
}
Debería usar ToUniversalTime () para el objeto DateTime.
Yo uso los siguientes métodos de extensión para la conversión de é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);
}
Para no preocuparse por usar milisegundos o segundos, simplemente haga lo siguiente:
public static DateTime _ToDateTime(this long unixEpochTime)
{
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var date = epoch.AddMilliseconds(unixEpochTime);
if (date.Year > 1972)
return date;
return epoch.AddSeconds(unixEpochTime);
}
Si el tiempo de la época es en segundos, no hay forma de que pueda pasar el año 1972 agregando milisegundos.
Si no está utilizando 4.6, esto puede ayudar 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;
}
using Microsoft.IdentityModel.Tokens; ... EpochTime.GetIntDate(dateTime);
En caso de que necesite convertir una estructura timeval (segundos, microsegundos) que contenga UNIX time
a DateTime
sin perder precisión, así es como:
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);
}
Desde .Net 4.6 y superior, use DateTimeOffset.Now.ToUnixTimeSeconds ()
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);
}