Différence entre System.DateTime.Now et System.DateTime.Today

127

Quelqu'un peut-il expliquer la différence entre System.DateTime.Nowet System.DateTime.Todaydans C # .NET? Avantages et inconvénients de chacun si possible.

Samuel Liew
la source

Réponses:

179

DateTime.Nowrenvoie une DateTimevaleur qui se compose de la date et de l'heure locales de l'ordinateur sur lequel le code est exécuté. Il a DateTimeKind.Localcédé à sa Kindproprié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.Todayrenvoie une DateTimevaleur 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.Localdans sa Kindproprié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.Nowelle obtient d'abord l'heure UTC (via la GetSystemTimeAsFileTimefonction 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.DateTimeaura des valeurs similaires à DateTime.Now, mais cela aura DateTimeKind.Unspecifiedplutô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.Nowpremiè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 DateTimeOffsetplace:

// 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 -0600avant la transition, ou 2013-11-03 01:00:00 -0700aprè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' Dateobjet 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 LocalDateclasse 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.Timeobjet 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);
Matt Johnson-Pint
la source
9
Qu'en est-il de l'utilisation de DateTime.UtcNowau lieu de DateTimeOffset.Now?
Samuel Liew
5
DateTime.UtcNowest 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 MyDateUtcau 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.UtcNowpeut être utilisé pour s'assurer que le décalage zéro est transmis avec les valeurs de date et d'heure.
Matt Johnson-Pint
Ils ne sont pas égaux. Aujourd'hui, il est 00:00:00.
James Wilkins
@JamesWilkins - Je ne sais pas trop dans quoi vous voulez en venir. Il en va de même DateTime.Now.Date.
Matt Johnson-Pint
@MattJohnson La question pose la différence entre DateTime.Today et DateTime.Now, pas DateTime.Today et DateTime.Now.Date.
David Anderson
85

Temps. .Nowcomprend le 09:23:12 ou autre; .Todayest la partie date uniquement (à 00:00:00 ce jour-là).

Alors utilisez .Nowsi vous voulez inclure l'heure, et .Todaysi vous voulez juste la date!

.Today est essentiellement le même que .Now.Date

Marc Gravell
la source
27
... et à utiliser UtcNowsauf si vous voulez vraiment le fuseau horaire local du système. (En particulier, sur une application Web, c'est presque toujours le mauvais choix.)
Jon Skeet
22

La DateTime.Nowpropriété renvoie la date et l'heure actuelles, par exemple 2011-07-01 10:09.45310.

La DateTime.Todayproprié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.Todaypropriété est en fait implémentée pour renvoyer DateTime.Now.Date:

public static DateTime Today {
  get {
    DateTime now = DateTime.Now;
    return now.Date;
  }
}
Guffa
la source
9

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

daniel.herken
la source
2
juste une observation ... la documentation 1.1 est beaucoup moins détaillée que la documentation 4.0; il est peut-être préférable de créer un lien vers vLatest?
Marc Gravell
3
@megaperlz: Vous créez maintenant un lien vers 4.0 plutôt que vers vLatest. VLes derniers liens peuvent être créés en supprimant le fichier (v=VS.100).
Brian
6

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);
          }
        }
dekdev
la source
5
DateTime dt = new DateTime();// gives 01/01/0001 12:00:00 AM
DateTime dt = DateTime.Now;// gives today date with current time
DateTime dt = DateTime.Today;// gives today date and 12:00:00 AM time
deepi
la source
1

DateTime.Todayest DateTime.Nowavec 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.Ticksest 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 Kindpropriété est, DateTimeKind.Localelle 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é.

Kobus
la source
-1

DateTime.Now.ToShortDateString() affichera uniquement la partie date

sunnyca99
la source