web-dev-qa-db-ja.com

C#でのみ日付のタイプ-なぜ日付タイプがないのですか?

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

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

誰もが構造体とおそらくDateTimeの一部の拡張メソッドを使用し、おそらく==や<、>などの演算子を実装するNice実装を持っていますか?

92
Carlo V. Dango

この古典的な質問に更新を追加させてください:

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

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

私はこの問題をかなり研究してきたので、これらのタイプが必要ないくつかの理由も共有します。

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

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

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

  2. 時間帯を注意深く監視しないと、ある環境から別の環境に値が渡されるため、日付に時刻を付加すると、日付changeingにつながる可能性があります。これは一般にJavaScript(Dateオブジェクトが実際に日付と時刻である)で発生しますが、.NETでも簡単に発生する可能性があります。

  3. DateTimeをXMLまたはJSON(およびその他)でシリアル化すると、重要ではない場合でもalwaysに時間が含まれます。これは非常に複雑です。特に、誕生日や記念日など、時間が関係のないものを考えると、これは混乱を招きます。

  4. アーキテクチャ上、DateTime[〜#〜] ddd [〜#〜]value-object ですが、複数の方法で Single Responsibly Principle に違反しています:

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

    • .Kindプロパティに付加されたDateTimeKind値は、単一の型を3つに分割します。Unspecifiedの種類は、構造の本来の意図であり、そのように使用する必要があります。 Utc kindは、特にUTCに値を合わせ、Local kindは、値を環境のローカルタイムゾーンに合わせます。

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

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

      // 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 !!!
      

要約すると、DateTimeは日付のみに使用できますが、それを使用するすべての場所が時間を無視するように非常に注意してください。また、UTCまたは他のタイムゾーンとの間で変換を試みないように注意してください。

40

専用の純粋なDateクラスがないのは、それを処理できるDateTimeが既にあるからだと思います。 Dateがあると、複製と混乱につながります。

標準的なアプローチが必要な場合は、DateTime.Dateプロパティは、DateTimeの日付部分のみを提供し、時刻の値は深夜12:00:00(00:00:00)に設定されます。

17
Robert MacLean

[email protected]にメールを送りましたが、それが彼らの答えです

マルコス、これはこのような質問をするのに適した場所ではありません。 http://stackoverflow.com簡単な答えは、特定の時点を表すモデルが必要であり、DateTimeがそれを行うということです。これは、 practice。人間が2つの概念(日付と時刻)を使用して時点をマークするという事実はfact意的であり、分離するのに役立ちません。

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

HTH、キリル・オセンコフ

私の電子メールでは、DateTimeがTimeZoneInfoを使用してマシンの時刻を取得しているためかどうかを疑問視していました。だから、「ビジネスルール」が「あまりにも結合されている」からだと言って、彼らはそれを私に打ち明けた。

11
MVCDS

単純な Date struct を作成しました。時間部分、タイムゾーン、ローカルvs. utcなどを気にせずに単純な日付が必要な場合に使用します。

https://github.com/claycephus/csharp-date

10
Clay

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

yourdatetime.Date;

画面に表示している場合は、

yourdatetime.ToShortDateString();
4
MattP

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

3
Pleun

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

2
siride

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

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

2
jason

DateTimeの時間部分を遮断するDateTime.Dateプロパティが常にあります。たぶん、DateTimeを独自のDate型にカプセル化またはラップできます。

そして、なぜ、質問については、Anders Heljsbergに尋ねる必要があると思います。

2
Mikael Östberg

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

2
Matt

日付を知るためには、時刻を含むシステム時間(ティック単位)を知る必要があるので、なぜその情報を捨てるのでしょうか?

DateTimeには、Dateプロパティがあります。これは、時間をまったく気にしない場合です。

1
Massif

ええ、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を簡単に抽出できるからです。

1
kd7

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

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

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

0
eph_tagh