it-swarm-fr.com

DateTime.Now vs. DateTime.UtcNow

Je me suis demandé quels sont exactement les principes de fonctionnement des deux propriétés. Je sais que le second est universel et ne traite pas des fuseaux horaires, mais quelqu'un peut-il expliquer en détail comment ils fonctionnent et lequel doit être utilisé dans quel scénario?

197
Slavo

DateTime.UtcNow vous indique la date et l'heure telles qu'elles seraient exprimées en temps universel coordonné, également appelé fuseau horaire de Greenwich, comme vous le feriez si vous étiez à Londres en Angleterre, mais pas pendant l'été. DateTime.Now donne la date et l'heure telles qu'elles sembleraient à quelqu'un de votre environnement local actuel.

Je recommanderais d'utiliser DateTime.Now chaque fois que vous affichez une date à un être humain - de cette façon, ils sont à l'aise avec la valeur qu'ils voient - c'est quelque chose qu'ils peuvent facilement comparer à ce qu'ils voient sur leur montre ou leur horloge. Utilisation DateTime.UtcNow lorsque vous souhaitez stocker des dates ou les utiliser pour des calculs ultérieurs de cette manière (dans un modèle client-serveur), vos calculs ne sont pas confus par les clients situés dans des fuseaux horaires différents de votre serveur ou les uns des autres.

311
Blair Conrad

C'est vraiment très simple, donc je pense que cela dépend de votre public et de son lieu de résidence.

Si vous n'utilisez pas Utc, vous devez connaître le fuseau horaire de la personne à qui vous affichez les dates et heures - sinon, vous lui direz que quelque chose s'est passé à 3 PM dans heure du système ou du serveur, quand cela s'est réellement passé à 5 PM où ils se trouvent.

Nous utilisons DateTime.UtcNow Parce que nous avons un auditoire Web global et que je préfère ne pas ennuyer tous les utilisateurs à remplir un formulaire indiquant le fuseau horaire dans lequel ils vivent.

Nous affichons également les heures relatives (il y a 2 heures, 1 jour, etc.) jusqu'à ce que le message ait suffisamment vieilli pour que l'heure soit "la même", peu importe où vous habitez sur Terre.

80
Jeff Atwood

Notez également la différence de performance. DateTime.UtcNow est environ 30 fois plus rapide que DateTime.Now, car en interne, DateTime.Now effectue de nombreux ajustements de fuseau horaire (vous pouvez facilement le vérifier avec Reflector).

Donc, n'utilisez pas DateTime.Now pour les mesures d'heure relative.

29
Magnus Krisell

Un concept principal à comprendre dans .NET est que maintenant est maintenant tout sur la Terre, quel que soit le fuseau horaire dans lequel vous vous trouvez. Donc, si vous chargez une variable avec DateTime.Now ou DateTime.UtcNow - l'affectation est identique. * Votre objet DateTime sait ce que le fuseau horaire dans lequel vous vous trouvez et en tient compte quelle que soit l'affectation.

L'utilité de DateTime.UtcNow Est particulièrement utile pour calculer des dates dépassant les limites de l'heure d'été. C'est-à-dire que, dans les endroits qui participent à l'heure d'été, il y a parfois 25 heures de midi à midi le jour suivant et parfois 23 heures entre midi et midi le jour suivant. Si vous souhaitez déterminer correctement le nombre d’heures entre les heures A et B, vous devez d’abord traduire chacune d’elles en équivalents UTC avant de calculer le TimeSpan.

Ceci est couvert par un article de blog que j'ai écrit qui explique plus en détail TimeSpan, et inclut un lien vers un article encore plus complet de MS sur le sujet.

* Clarification: l'une ou l'autre affectation stockera l'heure actuelle. Si vous deviez charger deux variables, l'une via DateTime.Now() et l'autre via DateTime.UtcNow(), la différence TimeSpan serait de l'ordre de la milliseconde, et non des heures en supposant que vous êtes dans un fuseau horaire heures loin de GMT. Comme indiqué ci-dessous, imprimer leurs valeurs String afficherait différentes chaînes.

26
Carl Camera

C'est une bonne question. Je le relance pour donner un peu plus de détails sur la manière dont .Net se comporte avec différentes valeurs de Kind. Comme le souligne @Jan Zich, il s'agit en réalité d'une propriété extrêmement importante. Elle est définie différemment selon que vous utilisez Now ou UtcNow.

En interne, la date est stockée sous la forme Ticks qui (contrairement à la réponse de @Carl Camera) diffère selon que vous utilisez Now ou UtcNow.

DateTime.UtcNow se comporte comme les autres langues. Il définit Ticks sur une valeur basée sur GMT. Il définit également Kind sur Utc.

DateTime.Now modifie la valeur Ticks en ce qui serait si c'était votre heure de la journée dans le fuseau horaire GMT. Il définit également Kind sur Local.

Si vous avez 6 heures de retard (GMT-6), vous obtiendrez l'heure GMT d'il y a 6 heures. .Net ignore en fait Kind et traite cette heure comme si c'était il y a 6 heures, même si elle est supposée être "maintenant". Cela se casse davantage si vous créez une instance DateTime, puis changez votre fuseau horaire et essayez de l'utiliser.

Les instances DateTime avec différentes valeurs 'Kind' ne sont PAS compatibles.

Regardons du code ...

    DateTime utc = DateTime.UtcNow;
    DateTime now = DateTime.Now;
    Debug.Log (utc + " " + utc.Kind);  // 05/20/2015 17:19:27 Utc
    Debug.Log (now + " " + now.Kind);  // 05/20/2015 10:19:27 Local

    Debug.Log (utc.Ticks);  // 635677391678617830
    Debug.Log (now.Ticks);  // 635677139678617840

    now = now.AddHours(1);
    TimeSpan diff = utc - now;
    Debug.Log (diff);  // 05:59:59.9999990

    Debug.Log (utc <  now);  // false
    Debug.Log (utc == now);  // false
    Debug.Log (utc >  now);  // true

    Debug.Log (utc.ToUniversalTime() <  now.ToUniversalTime());  // true
    Debug.Log (utc.ToUniversalTime() == now.ToUniversalTime());  // false
    Debug.Log (utc.ToUniversalTime() >  now.ToUniversalTime());  // false
    Debug.Log (utc.ToUniversalTime() -  now.ToUniversalTime());  // -01:00:00.0000010

Comme vous pouvez le voir ici, les comparaisons et les fonctions mathématiques ne sont pas automatiquement converties en temps compatibles. La Timespan aurait dû durer presque une heure, mais au lieu de six. "Utc <maintenant" aurait dû être vrai (j'ai même ajouté une heure pour en être sûr), mais était toujours faux.

Vous pouvez également voir le "contournement" qui consiste à simplement convertir en heure universelle n'importe quel endroit où Kind n’est pas le même.

Ma réponse directe à la question est en accord avec la recommandation de la réponse acceptée sur le moment d'utiliser chacune d'elles. Vous devriez toujours essayer travailler avec DateTime objets qui ont Kind=Utc, sauf pendant les E/S (affichage et analyse). Cela signifie que vous devriez presque toujours utiliser DateTime.UtcNow, sauf dans les cas où vous créez un objet uniquement pour l'afficher et le supprimer immédiatement.

15
Ted Bigham

DateTime n'a aucune idée de ce que sont les fuseaux horaires. Cela suppose toujours que vous êtes à votre heure locale. UtcNow signifie seulement "Soustraire mon fuseau horaire de l'heure".

Si vous souhaitez utiliser des dates tenant compte du fuseau horaire, utilisez DateTimeOffset, qui représente une date/heure avec un fuseau horaire. Je devais apprendre ça à la dure.

6
Omer van Kloeten

La réponse "simple" à la question est:

DateTime.Now renvoie une valeur DateTime représentant l'heure système actuelle (dans le fuseau horaire dans lequel le système est exécuté). La propriété DateTime.Kind sera DateTimeKind.Local

DateTime.UtcNow renvoie une valeur DateTime représentant le temps universel coordonné actuel (ou UTC), qui sera identique quel que soit le fuseau horaire du système. La propriété DateTime.Kind sera DateTimeKind.Utc

4
PapillonUK

Juste un petit ajout aux points mentionnés ci-dessus: la structure DateTime contient également un champ peu connu appelé Kind (au moins, je ne le savais pas depuis longtemps). Il s’agit essentiellement d’un indicateur indiquant si l’heure est locale ou UTC; il ne spécifie pas le décalage réel par rapport à UTC pour les heures locales. Outre le fait qu'il indique dans quelles intentions la structure a été construite, il influence également le fonctionnement des méthodes ToUniversalTime () et ToLocalTime () fonctionne.

4
Jan Zich
2
Sorin Comanescu

DateTime.UtcNow est une échelle de temps continue à valeur unique, alors que DateTime.Now n'est pas continue ou à valeur unique. La principale raison est l'heure avancée, qui ne s'applique pas à UTC. Donc, UTC ne avance ni ne recule d'une heure, contrairement à l'heure locale (DateTime.Now). Et quand il saute en arrière, la même valeur de temps apparaît deux fois.

1
user1315023

DateTime.UtcNow est une échelle de temps universelle omettant l'heure d'été. Donc, UTC ne change jamais en raison de l'heure d'été.

Mais DateTime.Now n'est pas continu ou à valeur unique, car il change en fonction de l'heure d'été. Ce qui signifie DateTime. Maintenant, la même valeur d'heure peut apparaître deux fois, laissant les clients dans un état confus.

1
ChaiVan

Lorsque vous avez besoin d'une heure locale pour la machine sur laquelle votre application s'exécute (comme CEST for Europe), utilisez Maintenant. Si vous voulez un temps universel - UtcNow. Tout dépend de vos préférences - créer probablement un site Web local/une application autonome que vous voudriez utiliser le temps dont dispose l'utilisateur - donc affecté par son paramètre de fuseau horaire - DateTime.Now.

N'oubliez pas que pour un site Web, il s'agit du réglage du fuseau horaire du serveur. Donc, si vous affichez l'heure de l'utilisateur, vous devez soit obtenir son fuseau horaire préféré et décaler l'heure (enregistrez simplement l'heure Utc dans la base de données, puis modifiez-la), ou indiquez qu'il s'agit de l'heure UTC. Si vous oubliez de le faire, l'utilisateur peut voir quelque chose comme: posté il y a 3 points faibles et un temps dans le futur tout près :)

0
kender