Quelqu'un peut-il expliquer la différence entre System.DateTime.Now
et System.DateTime.Today
dans C # .NET? Avantages et inconvénients de chacun si possible.
Quelqu'un peut-il expliquer la différence entre System.DateTime.Now
et System.DateTime.Today
dans C # .NET? Avantages et inconvénients de chacun si possible.
Réponses:
DateTime.Now
renvoie une DateTime
valeur qui se compose de la date et de l'heure locales de l'ordinateur sur lequel le code est exécuté. Il a DateTimeKind.Local
cédé à sa Kind
propriété. Cela équivaut à appeler l'un des éléments suivants:
DateTime.UtcNow.ToLocalTime()
DateTimeOffset.UtcNow.LocalDateTime
DateTimeOffset.Now.LocalDateTime
TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local)
TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local)
DateTime.Today
renvoie une DateTime
valeur qui a les mêmes composants année, mois et jour que l'une des expressions ci-dessus, mais avec les composants temporels définis sur zéro. Il a également DateTimeKind.Local
dans sa Kind
propriété. Il équivaut à l'un des éléments suivants:
DateTime.Now.Date
DateTime.UtcNow.ToLocalTime().Date
DateTimeOffset.UtcNow.LocalDateTime.Date
DateTimeOffset.Now.LocalDateTime.Date
TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local).Date
TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local).Date
Notez qu'en interne, l'horloge système est exprimée en UTC, donc lorsque vous l'appelez, DateTime.Now
elle obtient d'abord l'heure UTC (via la GetSystemTimeAsFileTime
fonction de l'API Win32), puis elle convertit la valeur dans le fuseau horaire local. (C'est donc DateTime.Now.ToUniversalTime()
plus cher que DateTime.UtcNow
.)
Notez également que cela DateTimeOffset.Now.DateTime
aura des valeurs similaires à DateTime.Now
, mais cela aura DateTimeKind.Unspecified
plutôt que DateTimeKind.Local
- ce qui pourrait entraîner d'autres erreurs en fonction de ce que vous en faites.
Donc, la réponse simple est que cela DateTime.Today
équivaut à DateTime.Now.Date
.
Mais à mon humble avis - Vous ne devez utiliser ni l'un ni l'autre, ni aucun des équivalents ci-dessus.
Lorsque vous demandez DateTime.Now
, vous demandez la valeur de l'horloge du calendrier local de l'ordinateur sur lequel le code s'exécute. Mais ce que vous obtenez ne contient aucune information sur cette horloge! Le meilleur que vous obtenez est cela DateTime.Now.Kind == DateTimeKind.Local
. Mais à qui appartient ce local? Ces informations sont perdues dès que vous faites quoi que ce soit avec la valeur, comme la stocker dans une base de données, l'afficher à l'écran ou la transmettre à l'aide d'un service Web.
Si votre fuseau horaire local suit des règles d'heure d'été, vous ne récupérez pas ces informations DateTime.Now
. Dans des moments ambigus, comme lors d'une transition de "repli", vous ne saurez pas lequel des deux moments possibles correspond à la valeur avec laquelle vous avez récupéré DateTime.Now
. Par exemple, supposons que votre fuseau horaire système soit défini sur Mountain Time (US & Canada)
et que vous le demandiez aux DateTime.Now
premières heures du 3 novembre 2013. Que signifie le résultat 2013-11-03 01:00:00
? Il y a deux moments de temps instantané représentés par cette même date-heure calendaire. Si je devais envoyer cette valeur à quelqu'un d'autre, ils n'auraient aucune idée de celui que je voulais dire. Surtout s'ils se trouvent dans un fuseau horaire où les règles sont différentes.
La meilleure chose à faire serait d'utiliser à la DateTimeOffset
place:
// This will always be unambiguous.
DateTimeOffset now = DateTimeOffset.Now;
Maintenant, pour le même scénario que j'ai décrit ci-dessus, j'obtiens la valeur 2013-11-03 01:00:00 -0600
avant la transition, ou 2013-11-03 01:00:00 -0700
après la transition. Quiconque regarde ces valeurs peut dire ce que je voulais dire.
J'ai écrit un article de blog sur ce sujet même. Veuillez lire - L'affaire contre DateTime.Now .
De plus, il y a des endroits dans ce monde (comme le Brésil) où la transition «printanière» se produit exactement à minuit. Les horloges vont de 23h59 à 01h00. Cela signifie que la valeur que vous obtenez DateTime.Today
à cette date n'existe pas! Même si vous utilisez DateTimeOffset.Now.Date
, vous obtenez le même résultat et vous rencontrez toujours ce problème. C'est parce que traditionnellement, il n'y a pas eu d' Date
objet dans .Net. Quelle que soit la façon dont vous obtenez la valeur, une fois que vous supprimez l'heure, vous devez vous rappeler qu'elle ne représente pas vraiment «minuit», même si c'est la valeur avec laquelle vous travaillez.
Si vous voulez vraiment une solution entièrement correcte à ce problème, la meilleure approche consiste à utiliser NodaTime . La LocalDate
classe représente correctement une date sans heure. Vous pouvez obtenir la date actuelle pour n'importe quel fuseau horaire, y compris le fuseau horaire du système local:
using NodaTime;
...
Instant now = SystemClock.Instance.Now;
DateTimeZone zone1 = DateTimeZoneProviders.Tzdb.GetSystemDefault();
LocalDate todayInTheSystemZone = now.InZone(zone1).Date;
DateTimeZone zone2 = DateTimeZoneProviders.Tzdb["America/New_York"];
LocalDate todayInTheOtherZone = now.InZone(zone2).Date;
Si vous ne souhaitez pas utiliser Noda Time, il existe maintenant une autre option. J'ai contribué à l'implémentation d'un objet de date uniquement dans le projet .Net CoreFX Lab . Vous pouvez trouver l' System.Time
objet package dans leur flux MyGet. Une fois ajouté à votre projet, vous constaterez que vous pouvez effectuer l'une des opérations suivantes:
using System;
...
Date localDate = Date.Today;
Date utcDate = Date.UtcToday;
Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);
DateTime.UtcNow
est acceptable si vous pouvez indiquer dans votre application ou spécification que la valeur est en UTC. (J'aime appeler le champ ou la propriété quelque chose comme MyDateUtc
au lieu de juste MyDate
- mais c'est juste la cerise sur le gâteau.) Si vous ne pouvez pas le transmettre dans la spécification ou le nom du champ, alors DateTimeOffset.UtcNow
peut être utilisé pour s'assurer que le décalage zéro est transmis avec les valeurs de date et d'heure.
DateTime.Now.Date
.
Temps. .Now
comprend le 09:23:12 ou autre; .Today
est la partie date uniquement (à 00:00:00 ce jour-là).
Alors utilisez .Now
si vous voulez inclure l'heure, et .Today
si vous voulez juste la date!
.Today
est essentiellement le même que .Now.Date
UtcNow
sauf si vous voulez vraiment le fuseau horaire local du système. (En particulier, sur une application Web, c'est presque toujours le mauvais choix.)
La DateTime.Now
propriété renvoie la date et l'heure actuelles, par exemple 2011-07-01 10:09.45310
.
La DateTime.Today
propriété renvoie la date actuelle avec les composants de l'heure définis sur zéro, par exemple 2011-07-01 00:00.00000
.
La DateTime.Today
propriété est en fait implémentée pour renvoyer DateTime.Now.Date
:
public static DateTime Today {
get {
DateTime now = DateTime.Now;
return now.Date;
}
}
DateTime.Today représente la date système actuelle avec la partie heure définie sur 00:00:00
et
DateTime.Now représente la date et l'heure actuelles du système
(v=VS.100)
.
J'ai pensé à ajouter ces liens -
Pour revenir à la question d'origine, en utilisant Reflector, j'ai expliqué la différence de code
public static DateTime Today
{
get
{
return DateTime.Now.Date; // It returns the date part of Now
//Date Property
// returns same date as this instance, and the time value set to 12:00:00 midnight (00:00:00)
}
}
private const long TicksPerMillisecond = 10000L;
private const long TicksPerDay = 864000000000L;
private const int MillisPerDay = 86400000;
public DateTime Date
{
get
{
long internalTicks = this.InternalTicks; // Date this instance is converted to Ticks
return new DateTime((ulong) (internalTicks - internalTicks % 864000000000L) | this.InternalKind);
// Modulo of TicksPerDay is subtracted - which brings the time to Midnight time
}
}
public static DateTime Now
{
get
{
/* this is why I guess Jon Skeet is recommending to use UtcNow as you can see in one of the above comment*/
DateTime utcNow = DateTime.UtcNow;
/* After this i guess it is Timezone conversion */
bool isAmbiguousLocalDst = false;
long ticks1 = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utcNow, out isAmbiguousLocalDst).Ticks;
long ticks2 = utcNow.Ticks + ticks1;
if (ticks2 > 3155378975999999999L)
return new DateTime(3155378975999999999L, DateTimeKind.Local);
if (ticks2 < 0L)
return new DateTime(0L, DateTimeKind.Local);
else
return new DateTime(ticks2, DateTimeKind.Local, isAmbiguousLocalDst);
}
}
DateTime.Today
est DateTime.Now
avec le temps mis à zéro.
Il est important de noter qu'il existe une différence entre une valeur DateTime, qui représente le nombre de graduations qui se sont écoulées depuis minuit du 1er janvier 0000, et la représentation sous forme de chaîne de cette valeur DateTime, qui exprime une valeur de date et d'heure dans un format spécifique à la culture: https://msdn.microsoft.com/en-us/library/system.datetime.now%28v=vs.110%29.aspx
DateTime.Now.Ticks
est l'heure réelle stockée par .net (essentiellement l'heure UTC), le reste ne sont que des représentations (qui sont importantes pour l'affichage).
Si la Kind
propriété est, DateTimeKind.Local
elle inclut implicitement les informations de fuseau horaire de l'ordinateur local. Lors de l'envoi via un service Web .net, les valeurs DateTime sont par défaut sérialisées avec les informations de fuseau horaire incluses, par exemple 2008-10-31T15: 07: 38.6875000-05: 00, et un ordinateur dans un autre fuseau horaire peut toujours savoir exactement l'heure mentionné.
Donc, utiliser DateTime.Now et DateTime.Today est parfaitement OK.
Vous commencez généralement à avoir des problèmes lorsque vous commencez à confondre la représentation sous forme de chaîne avec la valeur réelle et que vous essayez de "réparer" le DateTime, quand il n'est pas cassé.
DateTime.UtcNow
au lieu deDateTimeOffset.Now
?