C#でのみ日付の型-なぜ日付型がないのですか?


107

C#プロジェクトでは、時間なしで日付を表す必要があります。DateTimeの存在を知っていますが、これには時刻も組み込まれています。特定の変数とメソッド引数が日付ベースであることを明確にしたいと思います。したがって、私はDateTime.Dateプロパティを使用できません

この問題に対する標準的なアプローチは何ですか?確かに私はこれに最初に遭遇したのではありませんか?DateC#にクラスがないのはなぜですか?

誰かが構造体とおそらくDateTimeのいくつかのextensionmethodsを使用して、おそらく==や<、>などのいくつかの演算子を実装する素晴らしい実装を持っていますか?


1
明示的で明確なセマンティクスが必要であることは理解していDateTimeますが、具体的にどのような問題が発生しますか?
ジェフスターナル、2011年

15
1メソッドの開始時に時間を削除することを忘れないでください。2日付のみで機能することをうまく伝えていません。これは、たとえばナロータイプで十分なDbを格納およびロードする場合に重要です。プログラミングはコンピュータではなく人々のための交わりです
Carlo V. Dango

5
日付クラスの欠如は大きな問題であり、DateTimeの使用はまったく役に立たないと言いたいだけです。「日付」を日時として保存するとすぐに、ロケール/タイムゾーンの夏時間節約の問題に人質になります。時間の部分を捨てると、時計が変わったときにすべての日付を戻すことができます(!)。また、異なるタイムゾーンのユーザーは、日時を変換しようとすると、異なる日付が表示されます。日時は、正確な瞬間(ある時点からの瞬間など)を表すのに適していますが、抽象的な日付を表すのには非常に適していません。
TheMathemagician 2012年

2
後で同様の質問 stackoverflow.com/questions/7167710/…、そしてJon Skeetは日付があるはずだと言っています。
goodeye

8
整数のみのデータ型は10進数であるため、日付のみのデータ型はDateTimeになります。時間の部分を捨てることができるので日付は必要ないと主張する人たちは、小数部分を捨てることができるので整数は必要ないと言っているのと同じです。私たちの世界には、時間を含まない日付の概念があります。3月5日は3月5日00:00:00ではありません。
漠然とした

回答:


55

この古典的な質問に更新を追加することを許可します:

  • Jon SkeetのNoda Timeライブラリはかなり成熟し、日付のみの型と呼ばれていLocalDateます。(この場合のローカルは、誰かのローカルを意味するだけで、コードが実行されているコンピューターのローカルである必要はありません。)

  • 呼び出される日付のみのタイプDateは、corefxlabプロジェクトを介した.NET Coreへの追加提案です。System.Timeパッケージ、TimeOfDayタイプ、および既存のタイプに対するいくつかの拡張メソッドとともに、パッケージに含まれています。

この問題を大幅に調査したので、これらのタイプが必要な理由をいくつか紹介します。

  1. 日付のみの値と真夜中の日付の値の間には論理的な矛盾があります。

    • すべての現地日、すべてのタイムゾーンで真夜中があるとは限りません。例:ブラジルの春先の夏時間への移行により、時計は11:59:59から01:00:00に移動します。

    • 日付と時刻は常に1日の中の特定の時刻を指しますが、日付のみは1日の始まり、日の終わり、またはその日の範囲全体を指します。

  2. タイムゾーンを注意深く監視しないと、日付に時刻を付加すると、値が環境間で渡されるときに日付が変わる可能性があります。これは一般にJavaScript(Dateオブジェクトは実際には日付と時刻)で発生しますが、.NETでも、またはJavaScriptと.NETの間でデータが渡されるシリアル化でも簡単に発生します。

  3. DateTimeXMLまたはJSON(およびその他)を使用してをシリアル化すると、たとえそれが重要でなくても、常に時間含まれます。これは非常に混乱します。特に、誕生日と記念日など、時間が関係ない場合を考えると、

  4. アーキテクチャ的にDateTimeDDD 値オブジェクトですが、いくつかの点で単一責任原則に違反しています。

    • 日付と時刻のタイプとして設計されていますが、多くの場合、日付のみ(時刻を無視)または時刻のみ(日付を無視)として使用されます。(TimeSpan時間帯にもよく使用されますが、それは別のトピックです。)

    • DateTimeKind添付値.Kindプロパティは、三つに一つのタイプを分割Unspecified種類が本当に構造の本来の意図であり、その方法を使用する必要があります。Utc種類整列特にUTCと値、およびLocal種類整列環境のローカルタイムゾーンでの値。

      種の別々のフラグを持つ問題は、あなたが消費するたびにということでDateTime、あなたがしているはずチェックするために.Kind取るべき行動を決定します。フレームワークのメソッドはすべてこれを行いますが、他のメソッドはしばしば忘れます。タイプには2つの異なる理由(値と種類)があるため、これは本当にSRP違反です。

    • これらの2つは、コンパイルするAPIの使用につながりますが、多くの場合、無意味であるか、副作用によって奇妙なエッジケースが発生します。検討してください:

      // nonsensical, caused by mixing types
      DateTime dt = DateTime.Today - TimeSpan.FromHours(3);  // when on today??
      
      // strange edge cases, caused by impact of Kind
      var london = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
      var paris = TimeZoneInfo.FindSystemTimeZoneById("Romance Standard Time");
      var dt = new DateTime(2016, 3, 27, 2, 0, 0);  // unspecified kind
      var delta = paris.GetUtcOffset(dt) - london.GetUtcOffset(dt);  // side effect!
      Console.WriteLine(delta.TotalHours); // 0, when should be 1 !!!

要約すると、a DateTime 日付のみに使用できますが、使用するすべての場所で時間を無視するように非常に注意し、さらにUTCまたはその他から変換しないように非常に注意する場合にのみ使用する必要があります。時間帯。


2
場合にのみ、System.Time.Date.NETフレームワークに終わるでしょう:/
ロバート・JørgensgaardEngdahl

1
今すぐこれを使用して、corefx mygetフィードを購読するSystem.Timeだけで、他のパッケージと同じように取り込むことができます。それはまだ「公式」ではありません。
Matt Johnson-Pint 2017

16

DateあなたはすでにDateTimeそれを処理することができるので、私は専用の純粋なクラスはないと思います。持つDate重複や混乱につながります。

標準的なアプローチが必要な場合は、時刻値を真夜中12:00:00(00:00:00)に設定したDateTime.Dateaの日付部分のみを提供するプロパティを確認してくださいDateTime


60
専用のDateクラスの大きな利点は、タイムゾーンや夏時間の複雑さに悩まされないことです。
Dimitri C.

3
@DimitriC。私は同意しません-UTCでDateTimeを使用でき、説明された問題に悩まされることはありません。さらに、DateTimeを使用しても、日付のみが必要な場合でも、時間を含む計算を行うことができます(つまり、20 x 2時間を減算すると、日付がわかります)今日から)。
ロバートマクリーン

@Robert MacLean:UTC DateTimesを使用する便利さを強調してくれてありがとう。私はいくつかのテストを行いましたが、減算に関してはDateTimeKind.UnspecifiedがUTCのように動作しているようです。そのため、実際に、使用しているDateTimesの「種類」に注意すれば、すべてがうまくいきます。
Dimitri C.

10
UTCとタイムゾーンとの関係について考える必要があるのは、別のDateクラスで簡単に回避できるため、エネルギーの無駄遣いにすぎません。また、DateとDateTimeの間に混乱は見られません。
maulik13 2015

6
C#には本当にDateクラスが必要であることに同意します。タイムゾーンの変換は海底のバグの常に発生する原因であるだけでなく、時間ではなく営業日に基づいたものを処理する場合に非常に苦痛です。
ジュリアンバーチ

12

私はrefsrcfeedback@microsoft.comに電子メールを送りました、そしてそれは彼らの答えです

マルコス、これはこのような質問をするのに良い場所ではありません。http://stackoverflow.comを 試してください。簡単な答えは、ある時点を表すモデルが必要であり、DateTimeがそれを行うということです。これは、実際に最も有用なシナリオです。人間が2つの概念(日付と時刻)を使用して時刻をマークするという事実は恣意的であり、分離するのに役立ちません。

正当な理由がある場合にのみ分離し、盲目的に物事を行うためだけに物事を行わないでください。このように考えてください。DateTimeを日付と時刻に分割することで解決される問題は何ですか。そして、あなたが今持っていないことでどんな問題が起こりますか?ヒント:.NETフレームワーク全体でのDateTimeの使用状況を見ると、http//referencesource.microsoft.com/#mscorlib/system/datetime.cs#df6b1eba7461813b#references ほとんどがメソッドから返されていることがわかります。DateTimeのような単一の概念がなかった場合、日付と時刻のペアを返すには、outパラメータまたはタプルを使用する必要があります。

HTH、キリル・オセンコフ

私のメールでは、DateTimeがTimeZoneInfoを使用してマシンの時刻を取得しているためかどうかを質問しました。「ビジネスルール」が「関連しすぎている」ためだと私は言います。彼らは私にそれを打ち明けました。


この投稿は、組み込みの日付クラスを持たないという設計上の決定の背後にある考えに関する洞察を本当に提供します。あなたが彼らに送る質問は何でしたか?@TheMathemagicianが上記に挙げたまさにその理由で、私がこの決定に同意することを意味するものではありません。
RobertJørgensgaardEngdahl 2016

@RobertJørgensgaardEngdahl残念ながら、その電子メールアカウントにはもうアクセスできません。しかし、なぜ私は彼らに日付と時刻の構造で時刻と日付を結合したのかと尋ねたと思います。そして、私はTheMathemagicianに同意すると思いましたが、MSはこの設計アプローチを採用したと思います。なぜなら、国際的な会社として、彼らのニーズは報われます。
MVCDS 2016年

2
たぶんMSは独り占めしてSpaceTimeクラスを実装するだけかもしれません!アインシュタインによれば、空間と時間は密接に結びついているので、それらを区別する必要もないはずですよね?(!!!!!!!!!!!)私はC#にちょっと新しいんだけど、私は言わなければならない、それがされ、単に、VB.NETから来る地雷原だdateToday()now、などいいえDateTimeいいえ、ゴミを前置あざける。(そして、これらのセミコロンとこの大文字と小文字の区別は確かに
厄介

2
また、独自のSQL ServerにはDate型があり、結果は型である必要があります。型のDate場合、結果はDate時間のない文字列として期待されます。たとえば、DelphiにはDateTimeとしてのDateもありますが、DateinfoとDateTimeではtypeinfoが異なります。
user2091150

1
Kirill Osenkovは、「Dateクラス DateTimeクラスを別々にしないのはなぜですか?」という質問に答えています。実際の Qは「なぜしなかったまた別の日付と時刻のクラスを持っています?」。私は、日付と時刻の概念の多くのユースケースを認めるために、日付と時刻を1つのクラスに結合する必要があることを理解しています。ただし、日付の概念だけの有効なユースケースと同じくらい、おそらくそれ以上ではないにせよ、多くのものが存在します。そしてもちろん、時間の概念の多くの有効な使用例もあります。
トム


4

日付比較を実行する必要がある場合は、

yourdatetime.Date;

画面に表示している場合

yourdatetime.ToShortDateString();

.Dateの部分は私が探していたものです。
Brendan Vogt 2013年

3

推測させてください:SQL Server 2008までSQLには日付データ型がなかったため、SQLサーバーに格納するのは難しいためでしょうか?そしてそれは結局のところマイクロソフト製品ですか?


db datetimeはC#のdatetimeとは異なります。db datetimeにはタイムゾーンがないため、実際には特定の瞬間を参照しません。しかし、C#は、インスタントがUTCエポック以降のティックであることを認識し、それを保存します。
artsrc 2011

2
議論は専用のDATEについてであり、日時の部分についてはそれほどではないので、あなたがしようとしている点がわかりませんか?
Pleun、2009

これは質問に対する答えを提供しません。批評したり、著者に説明を求めたりするには、投稿の下にコメントを残してください。
Barranka 2015年

@Barranka-「C#にDateクラスがないのはなぜですか?」
STLDev

2

なぜそうなのか、誰にもわからない。.NETフレームワークには、多くの悪い設計上の決定があります。しかし、これはかなりマイナーなものだと思います。時間の部分はいつでも無視できます。そのため、一部のコードでDateTimeが日付だけではなく参照されるように決定したとしても、気になるコードは日付の部分だけを見る必要があります。または、日付のみを表す新しいタイプを作成し、DateTimeの関数を使用して、負荷のかかる処理(計算)を行うこともできます。


1
日付だけを使用したいかどうかにかかわらず、これは悪い決断だったとは思いません。賛成投票はしませんが、それは私の意見です。
JonH

私はそれをうまく言い表せなかったと思います。抽象化/エレガンスの観点からは、2つか3つのタイプの方がどのように適切であるかはわかりましたが、実際にはそれほど問題はありません。私のポイントは本当に.NETフレームワークには頭を悩ませる可能性のあるものがたくさんあり、特にこの「問題」がいくつかの悪質な設計決定(一般的な制約)。
siride

真実だから+1 ...これが.NETの唯一の問題(または最大の問題)だったのか:-) :-) DATE型とTIME型を追加するために必要なSQL Serverのバージョンの数は?そして、それらは(少なくとも完全性の理由で)はるかに有用でした
xanatos '15年

また、「すべてが-100ポイントから始まる」というのは、貧弱なフレームワークを作成するための良い方法だと思うことも付け加えておきます。これは、そのゴミに巻き込まれたものの1つかもしれません。
siride

2
コードの一部が.Dateプロパティの使用を怠っていたため、正しく比較されなかったため、この問題に悩まされました。このタイプのエラーを回避するために、時間を保存しない日付タイプの必要性は間違いなくあると思います
JoelFan

2

どうして?推測することしかできず、エンジニアリングの問題の解決に役立つことはあまりありません。DateTimeそのような構造体が持つであろうすべての機能が含まれていると思います。

本当に重要な場合DateTimeは、日付のみを公開する独自の不変の構造体でラップする(またはDateTime.Dateプロパティを確認する)。


2

ロバートの答えに加えて、DateTime.ToShortDateStringメソッドもあります。また、本当にDateオブジェクトが必要な場合は、常にAdapterパターンを使用して、DateTimeオブジェクトをラップし、必要なもの(つまり、月、日、年)のみを公開することができます。


2

DateTime.Dateの時間部分を切り取るプロパティが常に存在しDateTimeます。おそらく、DateTimeを独自のDate型にカプセル化またはラップできます。

そして、なぜかというと、なぜ、Anders Heljsbergに質問する必要があるのでしょう。


1

日付を知るためには、時刻を含むシステム時刻(ティック単位)を知る必要があるため、その情報を破棄する理由は何でしょうか。

DateTimeDate時間についてまったく気にしない場合は、プロパティがあります。


1

ええ、System.DateTimeもシールされています。以前の投稿で述べたように、時間の文字列値を取得するためだけにカスタムクラスを作成して、これを使ってゲームをプレイしている人がいるのを見てきました。

class CustomDate
{
    public DateTime Date { get; set; }
    public bool IsTimeOnly { get; private set; }

    public CustomDate(bool isTimeOnly)
    {
        this.IsTimeOnly = isTimeOnly;
    }

    public string GetValue()
    {
        if (IsTimeOnly)
        {
            return Date.ToShortTimeString();
        }

        else
        {
            return Date.ToString();
        }
    }
}

新しいクラスがなくても、プレーンな古いDateTime型からGetShortTimeStringを簡単に抽出できるため、これはおそらく不要です。


0

DateプロパティまたはTodayプロパティを使用して、DateTimeオブジェクトから日付部分のみを取得する場合。

DateTime today = DateTime.Today;
DateTime yesterday = DateTime.Now.AddDays(-1).Date;

次に、時間コンポーネントを真夜中に設定した場合のみ、日付コンポーネントを取得します。


1
これは間違いなく私が欲しかったものではありません
Carlo V. Dango

@Carlo V. Dango:同意しません。まさにあなたが欲しかったものだと思います。
siride

1
@Carlo V. Dango:これらのプロパティでは達成できないと具体的に何をしたいですか?
eph_tagh 2011年

5
それは非常に簡単です。Dateのメモリフットプリントは、おそらくDateTimeのメモリフットプリントの半分(64ビットではなく32ビット)になるでしょう。あなたの愚かな同僚がそれを変更する日付に.AddHours(1)しなかったが、「日付のみ」のPOVから「同じに保つ」ことは確かです。(エラーの場合)DateTimeがDateTimeKind.Localに設定されており、時刻がUTCに正規化されている場合、日付はおそらく変更されます(XmlSerializationを使用して、JSONへのラウンドトリップがうまくいかなかったため)...それで十分ですか?
xanatos 2011年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.