34

デフォルトでは、C# は DateTime オブジェクトを 100ns ティックと比較します。ただし、私のデータベースは DateTime 値を最も近いミリ秒単位で返します。指定された許容範囲を使用してC#で2つのDateTimeオブジェクトを比較する最良の方法は何ですか?

編集:丸めの問題ではなく、切り捨ての問題を扱っています。Joe が以下で指摘しているように、丸めの問題は新しい問題をもたらします。

私にとって有効な解決策は、以下の組み合わせです。

(dateTime1 - dateTime2).Duration() < TimeSpan.FromMilliseconds(1)

差が 1 ミリ秒未満の場合、これは true を返します。Duration() の呼び出しは、2 つの日付の差の絶対値を取得するために重要です。

4

7 に答える 7

31

私は通常、TimeSpan.FromXXX メソッドを使用して次のようなことを行います。

if((myDate - myOtherDate) > TimeSpan.FromSeconds(10))
{
   //Do something here
}
于 2008-12-19T16:16:24.283 に答える
10

DateTime の拡張メソッドを使って流暢なインターフェイスを作成するのはどうでしょうか (これらは大流行ですよね?)。

public static class DateTimeTolerance
{
    private static TimeSpan _defaultTolerance = TimeSpan.FromSeconds(10);
    public static void SetDefault(TimeSpan tolerance)
    {
        _defaultTolerance = tolerance;
    }

    public static DateTimeWithin Within(this DateTime dateTime, TimeSpan tolerance)
    {
        return new DateTimeWithin(dateTime, tolerance);
    }

    public static DateTimeWithin Within(this DateTime dateTime)
    {
        return new DateTimeWithin(dateTime, _defaultTolerance);
    }
}

これは、状態を格納し、 == と != のいくつかの演算子のオーバーロードを定義するクラスに依存しています。

public class DateTimeWithin
{
    public DateTimeWithin(DateTime dateTime, TimeSpan tolerance)
    {
        DateTime = dateTime;
        Tolerance = tolerance;
    }

    public TimeSpan Tolerance { get; private set; }
    public DateTime DateTime { get; private set; }

    public static bool operator ==(DateTime lhs, DateTimeWithin rhs)
    {
        return (lhs - rhs.DateTime).Duration() <= rhs.Tolerance;
    }

    public static bool operator !=(DateTime lhs, DateTimeWithin rhs)
    {
        return (lhs - rhs.DateTime).Duration() > rhs.Tolerance;
    }

    public static bool operator ==(DateTimeWithin lhs, DateTime rhs)
    {
        return rhs == lhs;
    }

    public static bool operator !=(DateTimeWithin lhs, DateTime rhs)
    {
        return rhs != lhs;
    }
}

次に、コードで次のことができます。

DateTime d1 = DateTime.Now;
DateTime d2 = d1 + TimeSpan.FromSeconds(20);

if(d1 == d2.Within(TimeSpan.FromMinutes(1))) {
    // TRUE! Do whatever
}

拡張クラスにはデフォルトの静的許容範囲も含まれているため、プロジェクト全体の許容範囲を設定し、パラメータなしで Within メソッドを使用できます。

DateTimeTolerance.SetDefault(TimeSpan.FromMinutes(1));

if(d1 == d2.Within()) {  // Uses default tolerance
    // TRUE! Do whatever
}

いくつかの単体テストがありますが、ここに貼り付けるにはコードが多すぎます。

于 2008-12-19T16:20:45.363 に答える
5

日付オブジェクトからミリ秒コンポーネントを削除する必要があります。1 つの方法は次のとおりです。

    DateTime d = DateTime.Now;
    d.Subtract(new TimeSpan(0, 0, 0, 0, d.Millisecond));

2 つの日時を減算することもできます

d.Subtract(DateTime.Now);

これにより、日、時間、分、秒のコンポーネントを比較して違いを確認するために使用できる timespan オブジェクトが返されます。

于 2008-12-19T16:18:03.420 に答える
2
        if (Math.Abs(dt1.Subtract(dt2).TotalSeconds) < 1.0)
于 2008-12-19T16:20:05.630 に答える
1

デフォルトでは、C# は DateTime オブジェクトをミリ秒と比較します。

実際の解像度は 100ns 刻みです。

データベースの 2 つの DateTime 値を比較している場合、解像度が 1 秒であれば問題ありません。

別のソースからの DateTime (たとえば、DateTime.Now を使用した現在の DateTime) と比較する場合は、1 秒未満をどのように処理するかを決定する必要があります。たとえば、四捨五入または切り捨てですか? ちょうど 0.5 秒の場合の丸め方。

整数の秒数に丸めるか切り捨ててから、データベースの値と比較することをお勧めします。 DateTime を丸める方法を説明する投稿を次に示します(この例では分に丸めますが、プリンシパルは同じです)。

于 2008-12-19T16:41:52.780 に答える
0

拡張メソッド IsSimilar を作成しました

public static bool IsSimilar(this DateTime? lhs, DateTime? rhs, TimeSpan tolerance)
{
    if (!lhs.HasValue && !lhs.HasValue) return true;//both are null
    if (!lhs.HasValue || !lhs.HasValue) return false;//one of 2 is null
    return IsSimilar(lhs.Value, rhs.Value, tolerance);
}
public static bool IsSimilar(this DateTime lhs, DateTime rhs, TimeSpan tolerance)
{
    return (lhs - rhs).Duration() <= tolerance;
 }
于 2020-04-09T04:29:13.683 に答える