C # DateTime сравнения точности и округления - PullRequest
3 голосов
/ 19 ноября 2009

У меня две даты. Один предоставляется пользователем и точен для второго, а другой - из базы данных и точен до уровня тиков. Это означает, что когда они оба представляют 13/11/2009 17:22:17 (британские даты)

userTime == dbTime 

возвращает ложь

Тиковые значения: 633937297368344183 и 633937297370000000.

Чтобы исправить это, я использую код

userTime = new DateTime(
                userTime.Year, 
                userTime.Month, 
                userTime.Day, 
                userTime.Hour, 
                userTime.Minute, 
                userTime.Second);

dbTime = new DateTime(
                dbTime.Year, 
                dbTime.Month, 
                dbTime.Day, 
                dbTime.Hour, 
                dbTime.Minute, 
                dbTime.Second);

Есть ли более элегантный способ добиться этого?

Ответы [ 5 ]

8 голосов
/ 19 ноября 2009

Наиболее очевидным рефакторингом будет удаление дублирования:

public static DateTime TruncateToSecond(DateTime original)
{
    return new DateTime(original.Year, original.Month, original.Day,
        original.Hour, original.Minute, original.Second);
}

...
if (TruncateToSecond(userTime) == TruncateToSecond(dbTime))
    ...

Вы вполне могли бы написать:

if (userTime.Ticks / TimeSpan.TicksPerSecond
    == dbTime.Ticks / TimeSpan.TicksPerSecond)
   ...

Я считаю, , что это сработает, просто потому, что отметка 0 стоит в начале секунды.

Вы должны быть осторожны с аспектом часового пояса всего этого, конечно. Возможно, вы захотите использовать DateTimeOffset.

5 голосов
/ 19 ноября 2009

Можете ли вы попробовать

UserDateTime.Substract(dbDateTime).TotalSeconds == 0
1 голос
/ 19 ноября 2009

Очень похоже на Cheeso. Я написал это расширение для DateTime, которое особенно используется в модульных тестах:

public static bool IsSimilarTo(this DateTime thisDateTime, DateTime otherDateTime, TimeSpan tolerance)
{
    DateTime allowedMinimum = thisDateTime.Subtract(tolerance);
    DateTime allowedMaximum = thisDateTime.Add(tolerance);

    if (otherDateTime < allowedMinimum || otherDateTime > allowedMaximum)
    {
        return false;
    }

    return true;
}

Это поможет вам с вашей проблемой, должно быть в базовой библиотеке: -)

1 голос
/ 19 ноября 2009

Я вычитаю их и получаю объект TimeSpan. Затем возьмите значение этой разницы (или абсолютное значение разницы, в зависимости от того, что вам подходит) и сравните его с небольшим пороговым значением, например 0,002 с.

TimeSpan delta = dt1 - dt2;

// get the delta as an absolute value:
if (delta < new TimeSpan(0, 0, 0))
    delta = new TimeSpan(0, 0, 0) - delta;

// My threshold is 1 second.  The difference can be no more than 1 second. 
TimeSpan threshold = new TimeSpan(0, 0, 1);

if (delta > threshold)
{
    // error...
}
0 голосов
/ 19 ноября 2009

вы можете использовать Microsoft.VisualBasic пространство имен, а затем

  DateTime a = new DateTime(633937297368344183L);
  DateTime b = new DateTime(633937297370000000L);

  Console.WriteLine(Microsoft.VisualBasic.DateAndTime.DateDiff(DateInterval.Second, a, b,FirstDayOfWeek.Sunday ,FirstWeekOfYear.System) == 0); //true

Кажется, в C # вам нужно указать FirstDayOfWeek и FirstWeekOfYear .

Не под VB.net

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...