Comment puis-je convertir un DateTime en nombre de secondes depuis 1970?

119

J'essaye de convertir une variable C # DateTime en heure Unix, c'est-à-dire le nombre de secondes depuis le 1er janvier 1970. On dirait qu'un DateTime est en fait implémenté comme le nombre de «ticks» depuis le 1er janvier 0001.

Ma pensée actuelle est de soustraire le 1er janvier 1970 de mon DateTime comme ceci:

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

Y a-t-il un meilleur moyen?

Curseur345
la source

Réponses:

195

C'est fondamentalement ça. Voici les méthodes que j'utilise pour convertir vers et depuis l'époque de l'époque 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);
}

Mise à jour: à partir de .Net Core 2.1 et .Net Standard 2.1, une date / heure égale à l'époque Unix peut être obtenue à partir du fichier statique DateTime.UnixEpoch.

Dave Swersky
la source
1
Il convient de noter que si vous souhaitez convertir en millsecondes pour des horodatages plus précis ou une compatibilité d'objet Javascript Date (), vous devez utiliser long au lieu de int pour le type d'horodatage.
Soviut
3
N'a pas travaillé pour moi. Cette réponse a fait l'affaire: stackoverflow.com/questions/249760/…
Zeezer
@Jonny - ToUniversalTime () convertit en UTC, donc il tient compte de l'UTC.
Dave Swersky
4
Origine DateTime = nouveau DateTime (1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); Intéressant que personne n'ait suggéré cela. Très souvent, vous aurez des millisecondes représentant le temps Utc. Et si vous n'avez pas t specify this explicitly and somewhere later in code youToUniversalTime (), vous vous retrouverez avec une mauvaise heure Utc, car par défaut, DateTime n'est PAS Utc.
steavy
52

Si le reste de votre système fonctionne avec DateTimeOffset au lieu de DateTime, il existe une fonctionnalité très pratique:

long unixSeconds = DateTimeOffset.Now.ToUnixTimeSeconds();
codeMonkey
la source
7
C'est une méthode plus propre, mais elle n'est disponible que dans le framework 4.6 msdn.microsoft.com/en-us/library
Oscar Fraxedas
1
Agréable. Et bien sûr pour passer d'Unix à un DateTimeOffset, vous pouvez utiliser var time = DateTimeOffset.FromUnixTimeSeconds(5000); MS Doc
Jordanie
22

La seule chose que je vois, c'est que c'est censé être depuis minuit le 1er janvier 1970 UTC

TimeSpan span= DateTime.Now.Subtract(new DateTime(1970,1,1,0,0,0, DateTimeKind.Utc));
return span.TotalSeconds;
CaffGeek
la source
7
Doit-il être DateTime.UtcNow?
oferei
14

Vous souhaitez probablement utiliser DateTime.UtcNow pour éviter les problèmes de fuseau horaire

TimeSpan span= DateTime.UtcNow.Subtract(new DateTime(1970,1,1,0,0,0)); 
David
la source
Le seul moyen d'éviter les problèmes de fuseau horaire est de 1) rester parfaitement ignorant et de ne prendre en charge qu'un seul fuseau horaire, ou 2) gérer les fuseaux horaires (au moins) partout où vous vous connectez avec un autre système ou utilisateur final. En particulier, utiliser UTC partout en interne n'est qu'une partie de la bataille. Dans le premier scénario, l'ajout d'heures de données UTC aggrave le problème, jusqu'à ce que vous soyez prêt à tout faire (2), car vous passez de la prise en charge de n'importe quel fuseau horaire à la prise en charge de l'UTC uniquement.
jpaugh
1

Cette approche sera bonne si la date-heure en question est en UTC, ou représente l'heure locale dans une zone qui n'a jamais observé l'heure d'été. Les routines de différence DateTime ne tiennent pas compte de l'heure d'été et par conséquent considéreront minuit le 1er juin comme un multiple de 24 heures après minuit le 1er janvier. locale, donc je ne pense pas qu'il y ait un bon moyen de gérer correctement n'importe quel moment avant le changement de règle le plus récent.

supercat
la source
0

Vous pouvez créer un startTime et un endTime de DateTime, puis faire endTime.Subtract (startTime). Ensuite, affichez votre durée.

Je pense que cela devrait fonctionner.

Alec Sanger
la source
0

J'utilise l'année 2000 au lieu de Epoch Time dans mon calcul. Travailler avec des nombres plus petits est facile à stocker et à transporter et est compatible avec JSON.

L'année 2000 était au deuxième 946684800 de l'époque.

L'année 2000 était au deuxième 63082281600 à partir du 1 janvier 0001.

DateTime.UtcNow Ticks commence à partir du 1 janvier 0001

Secondes à partir de l'an 2000 :

DateTime.UtcNow.Ticks/10000000-63082281600

Secondes à partir de l'heure Unix:

DateTime.UtcNow.Ticks/10000000-946684800

Par exemple, l'année 2020 est:

var year2020 = (new DateTime ()). AddYears (2019) .Ticks; // Parce que DateTime commence déjà à l'année 1

637134336000000000 Tiques depuis le 1 janvier 0001

63713433600 Secondes depuis le 1 janvier 0001

1577836800 Secondes depuis Epoch Time

631152000 Secondes depuis l'an 2000

Références:

Convertisseur de temps d'époque: https://www.epochconverter.com

Convertisseur de l'année 1: https://www.epochconverter.com/seconds-days-since-y0

profimedica
la source