web-dev-qa-db-fra.com

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

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

120
Samuel Liew

DateTime.Now Renvoie une valeur DateTime composée de la date et de l'heure locales de l'ordinateur sur lequel le code est exécuté. Il a DateTimeKind.Local Attribué à sa propriété Kind. Cela revient à appeler l’un des moyens 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 valeur DateTime qui comporte les mêmes composants année, mois et jour que toutes les expressions ci-dessus, mais dont les composants heure sont définis sur zéro. Il a également DateTimeKind.Local Dans sa propriété Kind. Cela é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. Par conséquent, lorsque vous appelez DateTime.Now, Il obtient d'abord l'heure UTC (via la fonction GetSystemTimeAsFileTime de l'API Win32. ) puis convertit la valeur dans le fuseau horaire local. (Par conséquent, DateTime.Now.ToUniversalTime() est plus cher que DateTime.UtcNow.)

Notez également que DateTimeOffset.Now.DateTime Aura des valeurs similaires à DateTime.Now, Mais aura DateTimeKind.Unspecified Plutôt que DateTimeKind.Local - ce qui pourrait entraîner d'autres erreurs en fonction de ce que vous faire avec.

Donc, la réponse simple est que DateTime.Today Est équivalent à DateTime.Now.Date.
Mais IMHO - Vous ne devriez utiliser ni l’un ni l’autre de ces équivalents.

Lorsque vous demandez DateTime.Now, Vous demandez la valeur de l'horloge de calendrier locale de l'ordinateur sur lequel le code est exécuté. Mais ce que vous récupérez ne contient aucune information sur cette horloge! Le meilleur que vous obtenez est que DateTime.Now.Kind == DateTimeKind.Local. Mais à qui appartient ce lieu? Ces informations sont perdues dès que vous modifiez la valeur, par exemple en la stockant dans une base de données, en l'affichant à l'écran ou en la transmettant à l'aide d'un service Web.

Si votre fuseau horaire local respecte les règles de l'heure d'été, vous ne récupérez pas ces informations à partir de 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 que vous avez récupérée avec DateTime.Now. Par exemple, supposons que votre fuseau horaire système soit défini sur Mountain Time (US & Canada) et que vous demandiez DateTime.Now Aux premières heures du 3 novembre 2013. Que signifie le résultat 2013-11-03 01:00:00? Il y a deux moments instantanés représentés par cette même date et heure du calendrier. Si j'envoyais cette valeur à quelqu'un d'autre, ils n'auraient aucune idée de laquelle 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 DateTimeOffset à la place:

// This will always be unambiguous.
DateTimeOffset now = DateTimeOffset.Now;

Maintenant, pour le même scénario que celui 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 - The Case Against DateTime.Now .

De plus, il y a des endroits dans ce monde (comme le Brésil) où la transition "printemps-avant" a lieu exactement à minuit. Les horloges vont de 23h59 à 01h00. Cela signifie que la valeur que vous obtenez pour DateTime.Today À cette date, n'existe pas ! Même si vous utilisez DateTimeOffset.Now.Date, Vous obtenez le même résultat, et vous avez toujours ce problème. C’est parce que traditionnellement, il n’existait pas d’objet Date dans .Net. Donc quelle que soit la manière dont vous obtenez la valeur, une fois que vous supprimez l'heure - vous devez vous rappeler que cela ne représente pas vraiment "minuit", même si c'est la valeur avec laquelle vous travaillez.

Si vous voulez vraiment une solution totalement correcte à ce problème, la meilleure approche consiste à utiliser NodaTime . La classe LocalDate 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 voulez pas utiliser Noda Time, il existe maintenant une autre option. J'ai contribué à la mise en œuvre d'un objet comportant uniquement une date dans le projet . Net CoreFX Lab . Vous pouvez trouver l'objet de package System.Time Dans leur flux MyGet. Une fois ajouté à votre projet, vous constaterez que vous pouvez effectuer les opérations suivantes:

using System;
...

Date localDate = Date.Today;

Date utcDate = Date.UtcToday;

Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);
163
Matt Johnson-Pint

Temps. .Now comprend le 09:23:12 ou autre; .Today est la date seulement (à 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 identique à .Now.Date

84
Marc Gravell

Le DateTime.Now propriété retourne la date et l'heure actuelles, par exemple 2011-07-01 10:09.45310.

Le DateTime.Today La propriété _ renvoie la date actuelle avec les composants d’heure définis sur zéro, par exemple 2011-07-01 00:00.00000.

Le DateTime.Today la propriété est réellement implémentée pour retourner DateTime.Now.Date:

public static DateTime Today {
  get {
    DateTime now = DateTime.Now;
    return now.Date;
  }
}
22
Guffa

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

9
daniel.herken

J'ai pensé à ajouter ces liens -

Pour revenir à la question initiale, 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);
          }
        }
6
dekdev
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
5
deepi

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 ticks écoulés depuis le 1er janvier 0000 à minuit, et la représentation sous forme de chaîne de cette valeur DateTime, qui exprime une valeur de date et d’heure dans 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 représente que représentations (importantes pour l’affichage).

Si la propriété Kind est DateTimeKind.Local il implicitement inclut les informations de fuseau horaire de l'ordinateur local. Lors de l'envoi sur un service Web .net, les valeurs DateTime sont sérialisées par défaut 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 à quelle heure il est fait référence.

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 de chaîne avec la valeur réelle et essayez de "réparer" le DateTime, quand il n'est pas cassé.

1
Kobus