C#.NETのSystem.DateTime.Now
とSystem.DateTime.Today
の違いは誰でも説明できますか?可能であれば、それぞれの長所と短所。
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.DateTime
はDateTime.Now
と同様の値を持ちますが、DateTimeKind.Unspecified
ではなくDateTimeKind.Local
を持つことに注意してください。
したがって、簡単な答えは、DateTime.Today
はDateTime.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);
時間。 .Now
には09:23:12などが含まれます。 .Today
は日付部分のみです(その日の00:00:00)。
したがって、時刻を含める場合は.Now
を使用し、日付だけが必要な場合は.Today
を使用します。
.Today
は、本質的に.Now.Date
と同じです
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;
}
}
これらのリンクを追加することを考えました-
元の質問に戻って、リフレクターを使用してコードの違いを説明しました
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 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
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を「修正」しようとすると、問題が発生し始めます。