Obtenir l'heure en millisecondes en utilisant C #

132

Je crée un programme dans lequel j'ai besoin d'obtenir l'heure en millisecondes. Par temps, je veux dire un nombre qui n'est jamais égal à lui-même, et qui est toujours 1000 nombres plus grand qu'il y a une seconde. J'ai essayé de convertir DateTime.Nowen a TimeSpanet d'en tirer le résultat TotalMilliseconds... mais j'ai entendu dire que ce n'était pas parfaitement précis.

Existe-t-il un moyen plus simple de le faire?

Entité
la source
Vous attendez-vous à ce que deux appels conduisent toujours à des valeurs croissantes? En général, les appels plus proches que l'intervalle minimum autorisé par la résolution du minuteur donneront la même valeur. Vous devrez ajouter votre propre bris d'égalité sous la forme d'un sérialiseur de fausse précision.
Steven Sudit
16
"Un nombre qui n'est jamais égal à lui-même". Cela semble ... compliqué. ;)
Mizipzor
1
NaN répondrait en fait à cette exigence. Bien qu'il ne soit "pas un nombre", c'est un type de nombre, et il n'est pas égal à lui-même.
Yay295

Réponses:

78

Utilisez la Stopwatchclasse.

Fournit un ensemble de méthodes et de propriétés que vous pouvez utiliser pour mesurer avec précision le temps écoulé.

Il y a de bonnes informations sur sa mise en œuvre ici:

Tests de performance: mesures précises du temps d'exécution avec System.Diagnostics.Stopwatch

RedFilter
la source
8
le chronomètre fait partie des diagnostics. Doit-il être utilisé dans du code réel?
Andrey
Ceci n'est normalement précis qu'à 15 ms environ.
Steven Sudit
11
combien coûte-t-il cependant? peut-être devrions-nous chronométrer un chronomètre :)
jb.
3
@Steven, cela dépend du système d'exploitation et du matériel sous-jacent. S'il est disponible, un minuteur haute résolution est utilisé, ce qui est le cas pour toutes les versions Windows x86 actuelles de bureau et de serveur dont j'ai connaissance. Vérifiez les propriétés Frequency et IsHighResolution pour plus de détails. Au niveau du système d'exploitation, QueryPerformanceCounter et QueryPerformanceFrequency sont les API de bas niveau qui soutiennent cette fonctionnalité.
Chris Taylor
321
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

C'est en fait ainsi que les différentes méthodes de conversion Unix sont implémentées dans la DateTimeOffsetclasse (.NET Framework 4.6+, .NET Standard 1.3+):

long milliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
Evan Mulawski
la source
65
Le titre est "obtenir le temps en millisecondes". Cette réponse est utile.
Aerospace
33
Oui, pour ceux d'entre nous qui recherchent une réponse à la question posée, cela a été très utile, merci.
user430788
1
Si vous voulez des décimales (même si ce DateTime.Nown'est pas "mis à jour" très souvent), utilisez bien sûr à la decimal milliseconds = DateTime.Now.Ticks / (decimal)TimeSpan.TicksPerMillisecond;place.
Jeppe Stig Nielsen
1
C'est beaucoup plus utile que la réponse sélectionnée pour les résultats de recherche et même pour ce que je retiens de la question originale.
bwoogie
1
Cette réponse m'a sauvé la vie. Vous avez un code similaire mais ne fonctionne pas. Impossible de comprendre pourquoi. Puis j'ai vu le longtype de données devant les millisecondes. L'utilisation intva certainement déborder.
FisNaN
13

La DateTime.Tickspropriété obtient le nombre de graduations qui représentent la date et l'heure.

10 000 tiques correspondent à une milliseconde (10 000 000 tiques par seconde).

Itay Karo
la source
4
Mais la résolution de Ticks est très inférieure à 1 / 10000s, peut-être 1 /
62s
2
@codymanix - de MSDN:A single tick represents one hundred nanoseconds or one ten-millionth of a second. There are 10,000 ticks in a millisecond.
Itay Karo
5
Bien sûr, mais le système d'exploitation n'a pas la résolution pour être aussi exacte.
codymanix
6
@codymanix est correct. Par analogie, un Angström est une unité de longueur; dix milliards d'Angströms font un mètre. Vous pouvez écrire une fonction qui rapporte votre taille sous la forme d'un entier de 64 bits en angströms, mais si tout ce que vous avez est un métre-aiguille précis au centimètre, alors le fait que la fonction représente une précision inférieure au nanomètre est complètement hors de propos. Les chiffres les moins significatifs seront des déchets.
Eric Lippert
4
@RedFilter: Si vous connaissiez réellement votre âge à la milliseconde près, vous pourriez peut-être dire quelque chose comme: "Quand je cligne des yeux à nouveau, mon âge sera de x millisecondes." Le problème le plus profond n'est pas la communication mais la mesure: il est peu probable que votre naissance soit connue à la seconde près.
Steven Sudit
11

J'utilise la classe suivante. Je l'ai trouvé sur Internet une fois, supposé être le meilleur MAINTENANT () .

/// <summary>Class to get current timestamp with enough precision</summary>
static class CurrentMillis
{
    private static readonly DateTime Jan1St1970 = new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    /// <summary>Get extra long current timestamp</summary>
    public static long Millis { get { return (long)((DateTime.UtcNow - Jan1St1970).TotalMilliseconds); } }
}

Source inconnue.

schmijos
la source
5
FWIW, le but de cet extrait de code couramment utilisé, est de créer un horodatage compatible avec le standard d'horodatage Unix. Pour cela, c'est vital. Si l'on veut juste faire du timing, cela coûte inutilement.
ToolmakerSteve
8

Vous pouvez essayer la QueryPerformanceCounterméthode native. Voir http://www.pinvoke.net/default.aspx/kernel32/QueryPerformanceCounter.html pour plus d'informations. C'est ce que la Stopwatchclasse utilise.

Consultez Comment obtenir l'horodatage de la précision des graduations dans .NET / C #? pour plus d'informations.

Stopwatch.GetTimestamp() donne accès à cette méthode:

public static long GetTimestamp() {
     if(IsHighResolution) {
         long timestamp = 0;
         SafeNativeMethods.QueryPerformanceCounter(out timestamp);
         return timestamp;
     }
     else {
         return DateTime.UtcNow.Ticks;
     }
 }
Pieter van Ginkel
la source
1
AFAIK StopWatch utilise QueryPerformanceCounter en interne si disponible
codymanix
Oui, l'implémentation interne de Stopwatch.GetTimestamp()fournit en fait l'accès à cette méthode.
Pieter van Ginkel
5

J'ai utilisé DateTime.Now.TimeOfDay.TotalMilliseconds (pour le jour actuel), j'espère que cela vous aidera également.

Sarvan
la source
1
qui ne renverra pas de valeurs croissantes (comme l'affiche originale l'exigeait) puisque TimeOfDay est remis à zéro tous les jours à minuit. De plus, il y aurait les mêmes problèmes potentiels que ceux mentionnés par l'affiche lors de l'utilisation de DateTime.
Jim O'Neil
3
Jim O'Neil Je suis d'accord avec vous, c'est pourquoi j'ai mentionné "(pour le jour actuel)" dans mon message ... Btw, ma solution a fonctionné pour mon problème, comme mon problème n'est pas spécifique à une date, j'avais simplement besoin d'obtenir la partie Millisecondes à utiliser comme compteur, je l'ai donc postée ici. Je suis nouveau ici, donc si je l'ai posté au mauvais endroit, je suis désolé :)
Sarvan
2

Utilisez System.DateTime.Now.ToUniversalTime(). Cela met votre lecture dans un format de milliseconde basé sur des références qui élimine totalement le changement de jour, etc.

John Tobler
la source
Bon à savoir, mais pas pertinent par rapport à la question posée, qui concerne le timing (mesure du passage du temps), pas la communication précise du temps.
ToolmakerSteve