Я делаю сравнение DateTime, но не хочу делать сравнения на уровне секунды, миллисекунды и тика. Какой самый элегантный способ?DateTime Точность сравнения
Если я просто сравниваю DateTime, то они редко равны из-за различий тиков.
Я делаю сравнение DateTime, но не хочу делать сравнения на уровне секунды, миллисекунды и тика. Какой самый элегантный способ?DateTime Точность сравнения
Если я просто сравниваю DateTime, то они редко равны из-за различий тиков.
Что об использовании отрезок времени.
if (Math.Truncate((A - B).TotalMinutes) == 0)
{
//There is less than one minute between them
}
Вероятно, не самый изящный способ, но он позволяет в тех случаях, которые один второй друг от друга, и все же разные дни/часы/минуты такие детали, как происходит в течение ночи.
Edit: это произошло со мной, что усечение является ненужным ...
if (Math.Abs((A - B).TotalMinutes) < 1)
{
//There is less than one minute between them
}
Лично я думаю, что это более элегантно ...
Я думаю .. он должен читаться как будто ((A - B) .TotalMinutes <= 1) –
Да, вы правы, я тоже удалил равных, так как комментарий говорит меньше. –
Чтобы ваше редактирование работало, вам нужно вызвать 'Math.Abs', прежде чем проверять, меньше ли он, потому что иначе вы могли бы иметь ** огромную ** разницу в значениях 2' DateTime'. Например, '(DateTime.Now - DateTime.Now.AddMinutes (10)). TotalMinutes' будет меньше 1, но имеет общую разницу в 10 минут. –
Одним из подходов может быть создание двух новых DateTimes из ваших ценностей, которые вы хотите сравнить, но игнорировать все, что от секунд вниз, а затем сравнить их:
DateTime compare1 = new DateTime(year1, month1, day1, hour1, minute1, 0);
DateTime compare2 = new DateTime(year2, month2, day2, hour2, minute2, 0);
int result = DateTime.Compare(compare1, compare2);
Я был бы первым, чтобы признать, что это не изящный, но он решает проблему.
Это решение хорошо, потому что оно обнаруживает, что это одна и та же минута (тогда как некоторые другие решения могут возвращать true для разных минут, которые разделены только на несколько секунд, например, 11:59:59 и 12:00:01). И он должен работать лучше, чем сравнение на основе строк. –
Вы можете преобразовать их в формат String и сравнить строку друг с другом.
Это также дает свободу выбора ваши параметры сравнения, как только время без даты и т.д.
if (String.Format("{0:ddMMyyyyHHmmss}", date1) == String.Format("{0:ddMMyyyyHHmmss}", date2))
{
// success
}
Как об этом ComparerClass?
public class DateTimeComparer : Comparer<DateTime>
{
private string _Format;
public DateTimeComparer(string format)
{
_Format = format;
}
public override int Compare(DateTime x, DateTime y)
{
if(x.ToString(_Format) == y.ToString(_Format))
return 0;
return x.CompareTo(y);
}
}
Это может быть использовано
List.Sort(new DateTimeComparer("hh:mm"));
Использование TimeSpan вы получите всю детализацию вы хотите:
DateTime dt1, dt2;
double d = (dt2 - dt1).TotalDays;
double h = (dt2 - dt1).TotalHours;
double m = (dt2 - dt1).TotalMinutes;
double s = (dt2 - dt1).TotalSeconds;
double ms = (dt2 - dt1).TotalMilliseconds;
double ticks = (dt2 - dt1).Ticks;
Может быть удобен время от времени ... –
Тестирование показывает TimeSpan, созданный из 2 равных значений DateTime до той же миллисекунды, дает всевозможные значения> 1 для всего, кроме TotalMilliseconds. – dudeNumber4
@ dudeNumber4 Можете ли вы показать свой тестовый код? – hoang
Я написал это, чтобы помочь себе:
internal class ImpreciseCompareDate : IComparer<DateTime>
{
private readonly double _Tolerance;
public ImpreciseCompareDate(double MillisecondsTolerance)
{
_Tolerance = MillisecondsTolerance;
}
public int Compare(DateTime x, DateTime y)
{
return Math.Abs((x - y).TotalMilliseconds) < _Tolerance ? 0 : x.CompareTo(y);
}
}
Допуск может быть установлен на (10 d/3d) для учета серверов SQL 1/300th мс. Если допускается превышение допуска, делегируйте его по умолчанию. Пример
Преимущество этого подхода, очевидно, заключается в возможности устанавливать произвольный допуск, независимо от уровней, уже предоставленных datetime (секунда, мс и т. Д.), Поскольку толерантность SQL-сервера не прерывается даже на одном из них. то есть. 1/300th секунды. – Sprague
public class DateTimeComparer : Comparer<DateTime>
{
private Prescision _Prescision;
public enum Prescision : sbyte
{
Millisecons,
Seconds,
Minutes,
Hour,
Day,
Month,
Year,
Ticks
}
Func<DateTime, DateTime>[] actions = new Func<DateTime, DateTime>[]
{
(x) => { return x.AddMilliseconds(-x.Millisecond);},
(x) => { return x.AddSeconds(-x.Second);},
(x) => { return x.AddMinutes(-x.Minute);},
(x) => { return x.AddHours(-x.Hour);},
(x) => { return x.AddDays(-x.Day);},
(x) => { return x.AddMonths(-x.Month);},
};
public DateTimeComparer(Prescision prescision = Prescision.Ticks)
{
_Prescision = prescision;
}
public override int Compare(DateTime x, DateTime y)
{
if (_Prescision == Prescision.Ticks)
{
return x.CompareTo(y);
}
for (sbyte i = (sbyte)(_Prescision - 1); i >= 0; i--)
{
x = actions[i](x);
y = actions[i](y);
}
return x.CompareTo(y);
}
}
Использования:
new DateTimeComparer(DateTimeComparer.Prescision.Day).Compare(Date1, Date2)
Другим способ заключается в преобразование первой обработки на клещи уровня с помощью простого (без округления) расчета:
var now = DateTime.UtcNow;
// 636340541021531973, 2017-06-26T06:08:22.1531973Z
var millisecondsPrecision = new DateTime(now.Ticks/10000 * 10000, now.Kind);
// 636340541021530000, 2017-06-26T06:08:22.1530000Z
var secondsPrecision = new DateTime(now.Ticks/10000000 * 10000000, now.Kind);
// 636340541020000000, 2017-06-26T06:08:22.0000000Z
var minutePrecision = new DateTime(now.Ticks/(10000000*60) * (10000000*60), now.Kind);
// 636340541000000000, 2017-06-26T06:08:00.0000000Z
@ решение Alz выглядит красиво но это слишком сложно и имеет ошибку. Итак, я решил объединить его с решением ChrisF.
public class DateTimeComparer : Comparer<DateTime>
{
public enum Precision
{
Years = 0,
Months,
Days,
Hours,
Minutes,
Seconds,
Millisecons,
Ticks
}
private Precision _precision;
public DateTimeComparer(Precision precision = Precision.Ticks)
{
_precision = precision;
}
public override int Compare(DateTime x, DateTime y)
{
if (_precision == Precision.Ticks)
{
return x.CompareTo(y);
}
var xx = AssembleValue(x, _precision);
var yy = AssembleValue(y, _precision);
return xx.CompareTo(yy);
}
private static DateTime AssembleValue(DateTime input, Precision precision)
{
var p = (int)precision;
var i = 1;
return new DateTime(input.Year,
p >= i++ ? input.Month : 1,
p >= i++ ? input.Day : 1,
p >= i++ ? input.Hour : 0,
p >= i++ ? input.Minute : 0,
p >= i++ ? input.Second : 0,
p >= i++ ? input.Millisecond : 0);
}
}
Я думаю, что здесь нет пули сивера ... Это полностью зависит от ваших предпочтений ...В любом случае, спасибо, что задали этот вопрос ... Я многое узнал из этого вопроса. 0: –
Я просто хотел указать, что на основе выбранного ответа этот вопрос неверен. Вы не просите сравнить * абсолютное время * с точностью до минуты, вы просите проверить, прошло ли * истекшее время *, чем определенный порог. – ErikE