Como você converte o tempo da época Unix em tempo real em C #? (Época começando em 1/1/1970)
Como você converte o tempo da época Unix em tempo real em C #? (Época começando em 1/1/1970)
Respostas:
Presumo que você esteja falando da hora do Unix , que é definida como o número de segundos desde a meia-noite (UTC) de 1º de janeiro 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 certo .
A versão mais recente do .Net (v4.6) acabou de adicionar suporte interno para conversões de horário do Unix. Isso inclui o horário de e para o Unix representado por segundos ou milissegundos.
DateTimeOffset
:DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
DateTimeOffset
tempo Unix em segundos:long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
DateTimeOffset
:DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
DateTimeOffset
para o tempo Unix em milissegundos:long unixTimeStampInMilliseconds= dateTimeOffset.ToUnixTimeMilliseconds();
Nota: Esses métodos são convertidos para e de DateTimeOffset
. Para obter uma DateTime
representação, basta usar a DateTimeOffset.DateTime
propriedade:
DateTime dateTime = dateTimeOffset.UtcDateTime;
'DateTimeOffset' does not contain a definition for 'FromUnixTimeSeconds'
Como resolver isso?
Com todo o crédito a LukeH, reuni alguns métodos de extensão para facilitar o uso:
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);
}
Observe o comentário abaixo de CodesInChaos de que o exemplo acima FromUnixTime
retorna a DateTime
com a Kind
de Utc
, o que é bom, mas o acima ToUnixTime
é muito mais suspeito, pois não explica o tipo de DateTime
dado date
. Para permitir date
's Kind
ser tanto Utc
ou Local
, 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
irá converter um Local
(ou Unspecified
) DateTime
para Utc
.
se você não quiser criar a instância DateTime da época ao passar do DateTime para a época, também poderá:
public static long ToUnixTime(this DateTime date)
{
return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
}
ToUnixTime
só funciona corretamente se a data estiver em Utc. Adicione um cheque ou converta-o. (Pessoalmente eu prefiro o cheque)
milliseconds
não segundos !!!
AddMilliseconds
e usar o Double NOT Float. Caso contrário, você terminará com um horário errado.
Você realmente deseja adicionar milissegundos (milissegundos), não segundos. A adição de segundos fornecerá uma exceção fora do intervalo.
AddMillis
e se você está começando a partir de segundos, você obviamente quer AddSeconds
.
Se você quer um melhor desempenho, pode usar esta versão.
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 uma referência rápida (BenchmarkDotNet) sob net471, recebo 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 |
2x mais rápido que a versão de LukeH (se for o desempenho)
É semelhante a como o DateTime funciona internamente.
Use o método DateTimeOffset.ToUnixTimeMilliseconds () Retorna o número de milissegundos decorridos desde 1970-01-01T00: 00: 00.000Z.
Isso é suportado apenas no Framework 4.6 ou superior
var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
Está bem documentado aqui DateTimeOffset.ToUnixTimeMilliseconds
A outra saída é usar o seguinte
long EPOCH = DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1,0,0,0,0).Ticks;
Para obter o EPOCH apenas com segundos, você pode usar
var Epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
e converta o Epoch
para DateTime
com o seguinte método
private DateTime Epoch2UTCNow(int epoch)
{
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(epoch);
}
.Ticks
, você recuperaria uma boa instância TimeSpan da subtração DateTime.
Eu uso os seguintes métodos de extensão para conversão 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 não se preocupar em usar milissegundos ou segundos, basta:
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);
}
Se o tempo da época for em segundos, não haverá como passar o ano de 1972 adicionando milissegundos.
Se você não estiver usando o 4.6, isso pode ajudar. Origem: 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);
Caso você precise converter uma estrutura timeval (segundos, microssegundos) contendo UNIX time
para DateTime
sem perder a precisão, é assim:
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 o .Net 4.6 e superior, use DateTimeOffset.Now.ToUnixTimeSeconds ()
Aqui está a minha solução:
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);
}