Безопасное сравнение локальных и универсальных DateTimes - PullRequest
38 голосов
/ 03 августа 2011

Я только что заметил что-то вроде нелепого недостатка в сравнении 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 время?

Ответы [ 2 ]

43 голосов
/ 03 августа 2011

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

Когда вы звоните .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 наивно

5 голосов
/ 03 августа 2011

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

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