Подтвердить что ты не робот

Безопасное сравнение локальных и универсальных DateTimes

Я только заметил, что кажется смешным недостатком сравнения DateTime.

DateTime d = DateTime.Now;
DateTime dUtc = d.ToUniversalTime();

d == dUtc; // false
d.Equals(dUtc); //false
DateTime.Compare(d, dUtc) == 0; // false

Похоже, что все операции сравнения в DateTimes не могут выполнять какой-либо тип интеллектуального преобразования, если это DateTimeKind.Local и один - DateTimeKind.UTC. Является ли лучший способ надежного сравнения DateTimes, не считая того, что он всегда конвертирует оба участвующих в сравнении времени utc?

4b9b3361

Ответ 1

Отредактировано, мой первоначальный ответ был частично неверным:

Когда вы вызываете .Equal или .Compare, внутренне значение .InternalTicks сравнивается. Это поле является неравным, потому что оно было настроено на пару часов для представления времени в универсальном времени. Вы должны увидеть это следующим образом: объект DateTime представляет время в неназванном часовом поясе, но не универсальное время плюс часовой пояс. Часовой пояс - Локальный (часовой пояс вашей системы) или UTC. Вы можете счесть это недостатком класса DateTime.

При преобразовании в другой часовой пояс время настраивается и должно быть скорректировано. Вероятно, поэтому Microsoft решила использовать метод, а не свойство, чтобы подчеркнуть, что при преобразовании в UTC выполняется действие.

Первоначально я писал здесь, что структуры сравниваются и флаг System.DateTime.Kind отличается. Это не так: количество тиков отличается:

t1.Ticks == t2.Ticks;       // false
t1.Ticks.Equals(t2.Ticks);  // false

Чтобы безопасно сравнить две даты, вы можете преобразовать их в один и тот же вид. Если вы преобразуете любую дату в универсальное время перед сравнением, вы получите результаты, которые вам нужны:

DateTime t1 = DateTime.Now;
DateTime t2 = t1;
DateTime.Compare(t1.ToUniversalTime(), t2.ToUniversalTime());  // 0
DateTime.Equals(t1.ToUniversalTime(), t2.ToUniversalTime());  // true

Мораль: никогда не сравнивай DateTime наивно

Ответ 2

Чтобы справиться с этим, я создал свой собственный объект DateTime (пусть его называют SmartDateTime), который содержит DateTime и TimeZone. Я переопределяю все операторы типа == и сравниваю и конвертирую в UTC перед выполнением сравнения с использованием исходных операторов DateTime.