Come posso convertire un DateTime nel numero di secondi dal 1970?


119

Sto provando a convertire una variabile DateTime C # in tempo Unix, cioè il numero di secondi dal 1 gennaio 1970. Sembra che un DateTime sia effettivamente implementato come numero di "tick" dal 1 gennaio 0001.

Il mio pensiero attuale è quello di sottrarre il 1 ° gennaio 1970 dal mio DateTime in questo modo:

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

C'è un modo migliore?


Risposte:


195

Fondamentalmente è così. Questi sono i metodi che utilizzo per convertire da e verso Unix Epoch Time:

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);
}

Aggiornamento: A partire da .Net Core 2.1 e .Net Standard 2.1 un DateTime uguale a Unix Epoch può essere ottenuto dallo statico DateTime.UnixEpoch.


1
Vale la pena notare che se si desidera convertire in millsecondi per timestamp più accurati o per la compatibilità con gli oggetti Javascript Date (), è necessario utilizzare long invece di int per il tipo di timestamp.
Soviut

3
Non ha funzionato per me. Questa risposta ha fatto il trucco: stackoverflow.com/questions/249760/...
Zeezer

@ Jonny - ToUniversalTime () converte in UTC, quindi tiene conto dell'UTC.
Dave Swersky

4
DateTime origin = new DateTime (1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); È interessante che nessuno lo abbia suggerito. Molto spesso avrai millisecondi che rappresentano il tempo Utc. E se non t specify this explicitly and somewhere later in code youavrai ToUniversalTime () allora finirai con un cattivo tempo Utc, perché per impostazione predefinita DateTime NON è Utc.
pesante

52

Se il resto del tuo sistema va bene con DateTimeOffset invece di DateTime, c'è una funzione davvero conveniente:

long unixSeconds = DateTimeOffset.Now.ToUnixTimeSeconds();

7
Questo è un modo più pulito, ma è disponibile solo nel framework 4.6 msdn.microsoft.com/en-us/library/…
Oscar Fraxedas

1
Bello. E, naturalmente, per passare da unix a DateTimeOffset, puoi utilizzare var time = DateTimeOffset.FromUnixTimeSeconds(5000); MS Doc
Jordan

22

L'unica cosa che vedo è che dovrebbe essere dalla mezzanotte del 1 gennaio 1970 UTC

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

7
Dovrebbe essere DateTime.UtcNow?
oferei il

14

Probabilmente vorrai usare DateTime.UtcNow per evitare problemi di fuso orario

TimeSpan span= DateTime.UtcNow.Subtract(new DateTime(1970,1,1,0,0,0)); 

L'unico modo per evitare problemi di fuso orario è 1) rimanere beatamente ignoranti e supportare solo un fuso orario o 2) gestire i fusi orari (almeno) ovunque ci si interfaccia con un altro sistema o utente finale. In particolare, utilizzare UTC ovunque internamente è solo una parte della battaglia. Nel primo scenario, l'aggiunta di data e ora UTC in realtà peggiora il problema, finché non si è pronti a fare tutto (2), perché si passa dal supporto di un fuso orario al supporto solo dell'UTC.
jpaugh

1

Questo approccio sarà valido se la data e l'ora in questione è in UTC o rappresenta l'ora locale in un'area che non ha mai osservato l'ora legale. Le routine di differenza DateTime non tengono conto dell'ora legale e di conseguenza considereranno la mezzanotte del 1 giugno come un multiplo di 24 ore dopo la mezzanotte del 1 gennaio. Non sono a conoscenza di qualsiasi cosa in Windows che segnali le regole storiche dell'ora legale per locale, quindi non penso che ci sia un buon modo per gestire correttamente qualsiasi momento prima della più recente modifica delle regole per l'ora legale.


0

Puoi creare un startTime e endTime di DateTime, quindi eseguire endTime.Subtract (startTime). Quindi visualizza il tuo intervallo di secondi.

Penso che dovrebbe funzionare.


0

Uso l'anno 2000 invece di Epoch Time nel mio calcolo. Lavorare con numeri più piccoli è facile da memorizzare e trasportare ed è compatibile con JSON.

L'anno 2000 era al secondo 946684800 dell'epoca.

L'anno 2000 era al secondo 63082281600 dal 1 ° gennaio 0001.

DateTime.UtcNow Ticks inizia dal 1 ° gennaio 0001

Secondi dall'anno 2000 :

DateTime.UtcNow.Ticks/10000000-63082281600

Secondi dall'ora di Unix:

DateTime.UtcNow.Ticks/10000000-946684800

Ad esempio l'anno 2020 è:

var year2020 = (new DateTime ()). AddYears (2019) .Ticks; // Perché DateTime inizia già nell'anno 1

637134336000000000 Zecche dal 1 ° gennaio 0001

63713433600 Secondi dal 1 ° gennaio 0001

1577836800 Secondi da Epoch Time

631152000 Secondi dall'anno 2000

Riferimenti:

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

Convertitore anno 1: https://www.epochconverter.com/seconds-days-since-y0

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.