回答:
DateTime.Now
DateTime
コードが実行されているコンピューターのローカルの日付と時刻で構成される値を返します。それはしているDateTimeKind.Local
のに割り当てられたKind
プロパティ。これは、次のいずれかを呼び出すのと同じです。
DateTime.UtcNow.ToLocalTime()
DateTimeOffset.UtcNow.LocalDateTime
DateTimeOffset.Now.LocalDateTime
TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local)
TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local)
DateTime.Today
DateTime
上記の式のいずれかと同じ年、月、日のコンポーネントを持つ値を返しますが、時間コンポーネントはゼロに設定されています。それはまたDateTimeKind.Local
そのKind
特性を持っています。次のいずれかに相当します。
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
最初に呼び出すと(GetSystemTimeAsFileTime
Win32 APIの関数を介して)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
。「フォールバック」遷移中などのあいまいな時間では、2つの可能な瞬間のどちらがで取得した値に対応するかがわかりませんDateTime.Now
。たとえば、システムのタイムゾーンがに設定されていて、2013年11月3日の早い時間にMountain Time (US & Canada)
要求したとします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
、同じ結果が得られ、この問題が依然として発生します。これは、伝統的に、Date
.Netにはオブジェクトなどが存在しないためです。したがって、値を取得する方法に関係なく、一度時間を取り除いてください。これは、作業している値であっても、「真夜中」を表すものではないことを覚えておく必要があります。
この問題の完全に正しい解決策が本当に必要な場合、最良のアプローチは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プロジェクトに提供しました。System.Time
MyGetフィードでパッケージオブジェクトを見つけることができます。プロジェクトに追加すると、次のいずれかを実行できるようになります。
using System;
...
Date localDate = Date.Today;
Date utcDate = Date.UtcToday;
Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);
DateTime.UtcNow
アプリケーションまたは仕様で値がUTCであることを伝えることができる場合は許容されます。(実際には、フィールドやプロパティMyDateUtc
を単にではなく、次のように呼び出すのが好きですMyDate
が、それは単にケーキの上のアイシングです。)スペックまたはフィールド名でそれDateTimeOffset.UtcNow
を伝えることができない場合は、ゼロオフセットが確実に伝えられるように使用できます。日付と時刻の値。
DateTime.Now.Date
です。
これらのリンクを追加することを考えました-
元の質問に戻って、Reflectorを使用して、コードの違いを説明しました
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
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
、それは暗黙のうちに、ローカルコンピュータのタイムゾーン情報が含まれています。.net Webサービスを介して送信する場合、DateTime値はデフォルトで、タイムゾーン情報(2008-10-31T15:07:38.6875000-05:00など)を使用してシリアル化され、別のタイムゾーンのコンピューターでも正確に何時かを知ることができます。参照されています。
したがって、DateTime.NowとDateTime.Todayを使用してもまったく問題ありません。
通常、文字列表現と実際の値を混同し始めて、壊れていないときにDateTimeを「修正」しようとすると、問題が発生し始めます。
DateTime.UtcNow
代わりにの使用についてはどうDateTimeOffset.Now
ですか?