Como posso converter um DateTime para o número de segundos desde 1970?

119

Estou tentando converter uma variável C # DateTime para o tempo Unix, ou seja, o número de segundos desde 1º de janeiro de 1970. Parece que um DateTime está realmente implementado como o número de 'tiques' desde 1º de janeiro de 0001.

Meu pensamento atual é subtrair 1º de janeiro de 1970 do meu DateTime assim:

TimeSpan span= DateTime.Now.Subtract(new DateTime(1970,1,1,0,0,0));
return span.TotalSeconds;

Existe uma maneira melhor?

Slider345
fonte
1
Possível duplicata de Como você converte o tempo de época em C #?
jpaugh

Respostas:

195

É basicamente isso. Estes são os métodos que uso para converter de e para o tempo de época do Unix:

public static DateTime ConvertFromUnixTimestamp(double timestamp)
{
    DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
    return origin.AddSeconds(timestamp);
}

public static double ConvertToUnixTimestamp(DateTime date)
{
    DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
    TimeSpan diff = date.ToUniversalTime() - origin;
    return Math.Floor(diff.TotalSeconds);
}

Atualização: A partir do .Net Core 2.1 e do .Net Standard 2.1, um DateTime igual ao Unix Epoch pode ser obtido no estático DateTime.UnixEpoch.

Dave Swersky
fonte
1
Deve ser importante notar que se você deseja converter em milsegundos para carimbos de data / hora mais precisos ou compatibilidade do objeto Javascript Date (), você precisa usar long em vez de int para o tipo de carimbo de data / hora.
Soviut
3
não funcionou para mim. Essa resposta funcionou: stackoverflow.com/questions/249760/…
Zeezer
@Jonny - ToUniversalTime () converte para UTC, portanto, conta para UTC.
Dave Swersky
4
Origem DateTime = novo DateTime (1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); Interessante que ninguém sugeriu isso. Freqüentemente, você terá milissegundos representando o tempo Utc. E se você não t specify this explicitly and somewhere later in code youtiver o ToUniversalTime (), terá um tempo Utc ruim, porque por padrão o DateTime NÃO é Utc.
steavy
52

Se o resto do seu sistema estiver OK com DateTimeOffset em vez de DateTime, há um recurso realmente conveniente:

long unixSeconds = DateTimeOffset.Now.ToUnixTimeSeconds();
codeMonkey
fonte
7
Esta é uma maneira mais limpa, mas está disponível apenas no framework 4.6 msdn.microsoft.com/en-us/library/…
Oscar Fraxedas
1
Agradável. E, claro, para ir de unix para DateTimeOffset, você pode usar o var time = DateTimeOffset.FromUnixTimeSeconds(5000); MS Doc
Jordan
22

A única coisa que vejo é que deveria ser desde a meia-noite de 1º de janeiro de 1970 UTC

TimeSpan span= DateTime.Now.Subtract(new DateTime(1970,1,1,0,0,0, DateTimeKind.Utc));
return span.TotalSeconds;
CaffGeek
fonte
7
Deve ser DateTime.UtcNow?
oferei
14

Você provavelmente deseja usar DateTime.UtcNow para evitar problemas de fuso horário

TimeSpan span= DateTime.UtcNow.Subtract(new DateTime(1970,1,1,0,0,0)); 
David
fonte
A única maneira de evitar problemas de fuso horário é 1) permanecer completamente ignorante e suportar apenas um fuso horário, ou 2) lidar com fusos horários (pelo menos) em todos os lugares em que você fizer interface com outro sistema ou usuário final. Em particular, usar UTC em todos os lugares internamente é apenas parte da batalha. No primeiro cenário, adicionar data e hora UTC na verdade piora o problema, até que você esteja pronto para fazer tudo de (2), porque você deixa de suportar qualquer fuso horário para suportar apenas UTC.
jpaugh
1

Essa abordagem será boa se a data / hora em questão estiver em UTC ou representar a hora local em uma área que nunca observou o horário de verão. As rotinas de diferença DateTime não levam em consideração o horário de verão e, consequentemente, considerarão a meia-noite de 1º de junho como um múltiplo de 24 horas após a meia-noite de 1º de janeiro. Não tenho conhecimento de nada no Windows que relata regras históricas de horário de verão para locale, portanto, não acho que haja uma boa maneira de lidar corretamente com qualquer horário anterior à alteração mais recente da regra de horário de verão.

supergato
fonte
0

Você pode criar um startTime e endTime de DateTime e, em seguida, endTime.Subtract (startTime). Em seguida, imprima seu span.Seconds.

Acho que deve funcionar.

Alec Sanger
fonte
0

Eu uso o ano 2000 em vez do Epoch Time no meu cálculo. Trabalhar com números menores é fácil de armazenar e transportar e é compatível com JSON.

O ano de 2000 foi o segundo 946684800 do tempo da época.

O ano de 2000 ocorreu no segundo 63082281600 de 1º de janeiro de 0001.

DateTime.UtcNow Ticks começa a partir de 1 de janeiro de 0001

Segundos do ano 2000 :

DateTime.UtcNow.Ticks/10000000-63082281600

Segundos do horário Unix:

DateTime.UtcNow.Ticks/10000000-946684800

Por exemplo, o ano de 2020 é:

var year2020 = (new DateTime ()). AddYears (2019) .Ticks; // Porque DateTime começa já no ano 1

637134336000000000 Carrapatos desde 1º de janeiro de 0001

63713433600 segundos desde 1º de janeiro de 0001

1577836800 segundos desde a hora da época

631152000 segundos desde o ano 2000

Referências:

Conversor Epoch Time: https://www.epochconverter.com

Conversor do ano 1: https://www.epochconverter.com/seconds-days-since-y0

profimedica
fonte