¿Cómo puedo convertir un DateTime al número de segundos desde 1970?

119

Estoy tratando de convertir una variable DateTime de C # a tiempo de Unix, es decir, el número de segundos desde el 1 de enero de 1970. Parece que un DateTime está realmente implementado como el número de 'ticks' desde el 1 de enero de 0001.

Mi pensamiento actual es restar el 1 de enero de 1970 de mi DateTime de esta manera:

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

¿Existe una forma mejor?

Control deslizante345
fuente

Respuestas:

195

Eso es básicamente todo. Estos son los métodos que utilizo para convertir hacia y desde la época de 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);
}

Actualización: A partir de .Net Core 2.1 y .Net Standard 2.1, se puede obtener un DateTime igual a Unix Epoch de la estática DateTime.UnixEpoch.

Dave Swersky
fuente
1
Vale la pena señalar que si desea convertir a milsegundos para obtener marcas de tiempo más precisas o compatibilidad con objetos Javascript Date (), debe usar long en lugar de int para el tipo de marca de tiempo.
Soviut
3
No funcionó para mí. Esta respuesta funcionó: stackoverflow.com/questions/249760/…
Zeezer
@Jonny - ToUniversalTime () se convierte a UTC, por lo que tiene en cuenta UTC.
Dave Swersky
4
Origen de DateTime = nuevo DateTime (1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); Interesante que nadie sugirió esto. Muy a menudo tendrá milisegundos que representan el tiempo Utc. Y si no t specify this explicitly and somewhere later in code youtiene ToUniversalTime (), terminará con un mal tiempo Utc, porque por defecto DateTime NO es Utc.
steavy
52

Si el resto de su sistema está bien con DateTimeOffset en lugar de DateTime, hay una característica realmente conveniente:

long unixSeconds = DateTimeOffset.Now.ToUnixTimeSeconds();
codeMonkey
fuente
7
Esta es una forma más limpia, pero solo está disponible en el marco 4.6 msdn.microsoft.com/en-us/library/…
Oscar Fraxedas
1
Agradable. Y, por supuesto, para pasar de unix a un DateTimeOffset, puede usar var time = DateTimeOffset.FromUnixTimeSeconds(5000); MS Doc
Jordan
22

Lo único que veo es que se supone que es desde la medianoche del 1 de enero de 1970 UTC

TimeSpan span= DateTime.Now.Subtract(new DateTime(1970,1,1,0,0,0, DateTimeKind.Utc));
return span.TotalSeconds;
CaffGeek
fuente
7
¿Debería ser DateTime.UtcNow?
oferei
14

Probablemente desee utilizar DateTime.UtcNow para evitar problemas de zona horaria

TimeSpan span= DateTime.UtcNow.Subtract(new DateTime(1970,1,1,0,0,0)); 
David
fuente
La única forma de evitar problemas con la zona horaria es 1) permanecer felizmente ignorante y admitir solo una zona horaria, o 2) manejar las zonas horarias (al menos) en todas partes donde interactúe con otro sistema o usuario final. En particular, usar UTC en todas partes internamente es solo una parte de la batalla. En el primer escenario, agregar fechas UTC en realidad empeora el problema, hasta que esté listo para hacer todo (2), porque pasa de admitir cualquier zona horaria a admitir solo UTC.
jpaugh
1

Ese enfoque será bueno si la fecha y hora en cuestión está en UTC, o representa la hora local en un área que nunca ha observado el horario de verano. Las rutinas de diferencia de fecha y hora no tienen en cuenta el horario de verano y, en consecuencia, considerarán la medianoche del 1 de junio como un múltiplo de 24 horas después de la medianoche del 1 de enero. No tengo conocimiento de nada en Windows que informe las reglas históricas de ahorro de luz del día para la locale, por lo que no creo que haya una buena manera de manejar correctamente cualquier momento antes del cambio de regla de horario de verano más reciente.

Super gato
fuente
0

Puede crear un startTime y endTime de DateTime, luego hacer endTime.Subtract (startTime). Luego genere su intervalo.Segundos.

Creo que debería funcionar.

Alec Sanger
fuente
0

Utilizo el año 2000 en lugar de Epoch Time en mi cálculo. Trabajar con números más pequeños es fácil de almacenar y transportar y es compatible con JSON.

El año 2000 fue el segundo 946684800 de la época.

El año 2000 fue en el segundo 63082281600 desde el 1 de enero de 0001.

DateTime.UtcNow Ticks comienza el 1 de enero de 0001

Segundos desde el año 2000 :

DateTime.UtcNow.Ticks/10000000-63082281600

Segundos de Unix Time:

DateTime.UtcNow.Ticks/10000000-946684800

Por ejemplo, el año 2020 es:

var year2020 = (nuevo DateTime ()). AddYears (2019) .Ticks; // Porque DateTime ya comienza en el año 1

637134336000000000 Garrapatas desde el 1 de enero de 0001

63713433600 Segundos desde el 1 de enero de 0001

1577836800 Segundos desde Epoch Time

631152000 Segundos desde el año 2000

Referencias:

Convertidor de época: https://www.epochconverter.com

Convertidor del año 1: https://www.epochconverter.com/seconds-days-since-y0

profimedica
fuente