web-dev-qa-db-ja.com

System.DateTime.NowとSystem.DateTime.Todayの違い

C#.NETのSystem.DateTime.NowSystem.DateTime.Todayの違いは誰でも説明できますか?可能であれば、それぞれの長所と短所。

120
Samuel Liew

DateTime.Nowは、コードが実行されているコンピューターのローカル日時で構成されるDateTime値を返します。 KindプロパティにDateTimeKind.Localが割り当てられています。次のいずれかを呼び出すことと同じです。

  • DateTime.UtcNow.ToLocalTime()
  • DateTimeOffset.UtcNow.LocalDateTime
  • DateTimeOffset.Now.LocalDateTime
  • TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local)
  • TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local)

DateTime.Todayは、上記の式のいずれかと同じ年、月、日のコンポーネントを持つが、時間コンポーネントをゼロに設定したDateTime値を返します。また、KindプロパティにDateTimeKind.Localがあります。次のいずれかと同等です。

  • 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

内部的には、システムクロックはUTCに基づいているため、DateTime.Nowを呼び出すと、最初に(Win32 APIの GetSystemTimeAsFileTime 関数を介して)UTC時間を取得してから、ローカルタイムゾーンの値。 (したがって、DateTime.Now.ToUniversalTime()DateTime.UtcNowよりも高価です。)

また、DateTimeOffset.Now.DateTimeDateTime.Nowと同様の値を持ちますが、DateTimeKind.UnspecifiedではなくDateTimeKind.Localを持つことに注意してください。

したがって、簡単な答えは、DateTime.TodayDateTime.Now.Dateと同等であるということです。
しかし、私見-これらのいずれか、または上記の同等物のいずれも使用しないでください。

DateTime.Nowを要求するとき、コードが実行されているコンピューターのローカルカレンダークロックの値を要求しています。しかし、戻ってきたものにはそのクロックに関する情報がありません!あなたが得る最高のものはDateTime.Now.Kind == DateTimeKind.Localです。しかし、地元の人は誰ですか?その情報は、データベースに保存したり、画面に表示したり、Webサービスを使用して送信したりするなど、値を使用して何かを行うとすぐに失われます。

ローカルタイムゾーンが夏時間規則に従っている場合、DateTime.Nowからその情報を取得することはできません。 「フォールバック」トランジション中などのあいまいな時間では、DateTime.Nowで取得した値に対応する2つの可能性のある瞬間のどちらかがわかりません。たとえば、システムのタイムゾーンがMountain Time (US & Canada)に設定され、2013年11月3日の早い時間にDateTime.Nowを要求するとします。結果2013-11-03 01:00:00はどういう意味ですか?この同じカレンダー日付時刻によって表される瞬時時刻の2つの瞬間があります。この値を他の誰かに送信すると、彼らは私が何を意味するのかわかりません。特に、ルールが異なるタイムゾーンにいる場合。

最善の方法は、代わりにDateTimeOffsetを使用することです。

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

上記と同じシナリオで、移行前に2013-11-03 01:00:00 -0600、または移行後に2013-11-03 01:00:00 -0700の値を取得します。これらの値を見る人は誰でも、私が何を意味したかを知ることができます。

私はこのテーマに関するブログ投稿を書きました。お読みください- DateTime.Nowに対するケース

また、この世界には、ブラジルのように、真夜中に「スプリングフォワード」トランジションが正確に発生する場所がいくつかあります。時計は23:59から01:00に移動します。これは、その日にDateTime.Todayに対して取得した値が存在しないことを意味します!DateTimeOffset.Now.Dateを使用しても、同じ結果が得られます。そして、あなたはまだこの問題を抱えています。これは、従来、.NetにはDateオブジェクトのようなものがなかったためです。したがって、値を取得する方法に関係なく、時間を取り除いた後は、それが実際に「真夜中」を表しているわけではないことを覚えておく必要があります。

この問題の完全に正しい解決策が本当に必要な場合、最良のアプローチは NodaTime を使用することです。 LocalDateクラスは、時刻のない日付を適切に表します。ローカルシステムのタイムゾーンを含む、任意のタイムゾーンの現在の日付を取得できます。

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;

野田タイムを使用したくない場合は、別のオプションがあります。 。Net CoreFX Lab プロジェクトに日付のみのオブジェクトの実装を提供しました。 MyGetフィードでSystem.Timeパッケージオブジェクトを見つけることができます。プロジェクトに追加すると、次のいずれかを実行できることがわかります。

using System;
...

Date localDate = Date.Today;

Date utcDate = Date.UtcToday;

Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);
163

時間。 .Nowには09:23:12などが含まれます。 .Todayは日付部分のみです(その日の00:00:00)。

したがって、時刻を含める場合は.Nowを使用し、日付だけが必要な場合は.Todayを使用します。

.Todayは、本質的に.Now.Dateと同じです

84
Marc Gravell

DateTime.Nowプロパティは、現在の日付と時刻を返します(例:2011-07-01 10:09.45310)。

DateTime.Todayプロパティは、2011-07-01 00:00.00000のように、時刻コンポーネントがゼロに設定された現在の日付を返します。

DateTime.Todayプロパティは、実際に実装されてDateTime.Now.Dateを返します。

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

DateTime.Today は、時刻部分が00:00:00に設定された現在のシステム日付を表します

そして

DateTime.Now は現在のシステムの日付と時刻を表します

9
daniel.herken

これらのリンクを追加することを考えました-

元の質問に戻って、リフレクターを使用してコードの違いを説明しました

 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は、時間をゼロに設定したDateTime.Nowです。

0000年1月1日の午前0時から経過したティックの数を表すDateTime値と、日付と時刻の値を表すそのDateTime値の文字列表現との間に違いがあることに注意することが重要です文化固有の形式: https://msdn.Microsoft.com/en-us/library/system.datetime.now%28v=vs.110%29.aspx

DateTime.Now.Ticksは.netによって保存される実際の時間(基本的にUTC時間)であり、残りは表現(表示目的にとって重要です)です。

KindプロパティがDateTimeKind.Localの場合、implicitlyにはローカルコンピューターのタイムゾーン情報が含まれます。 .net Webサービスを介して送信する場合、DateTime値はデフォルトでタイムゾーン情報を含めてシリアル化されます。 2008-10-31T15:07:38.6875000-05:00、および別のタイムゾーンのコンピューターは、参照されている時間を正確に知ることができます。

したがって、DateTime.NowとDateTime.Todayを使用してもまったく問題ありません。

通常、文字列表現と実際の値を混同し始め、DateTimeが壊れていない場合にDateTimeを「修正」しようとすると、問題が発生し始めます。

1
Kobus