2013-10-25 4 views
1

According to MSDN, методы поиска (например, FindByLogonTime и FindByBadPasswordAttempt) классов UserPrinciple и ComputerPrinciple используют время UTC для фильтрации результатов. Тем не менее, тестирование показывает, что эти методы, по-видимому, принимают локальное время в качестве входных данных, тогда как результирующие объекты используют UTC для своих временных свойств и должны быть преобразованы в локальное время..NET DirectoryServices Поиск методов использует UTC или локальное время?

Вот пример, который, кажется, правильно список всех пользователей с неудачной попытки входа в систему на сервере, так как 6am по местному времени:

static void Main() 
    { 
     var pc = new PrincipalContext(ContextType.Domain, dcServer); 
     PrincipalSearchResult<UserPrincipal> uFailed = UserPrincipal.FindByBadPasswordAttempt(pc, DateTime.Now.Date.AddHours(6), MatchType.GreaterThan); 
     string s = ""; 
     foreach (UserPrincipal u in uFailed) 
     { 
      s += u.SamAccountName + ": " + Convert.ToDateTime(u.LastBadPasswordAttempt).ToLocalTime().ToString() + "\r\n"; 
     } 
     Console.Write(s); 
     Console.Read(); 
    } 

Примечание преобразование UTC для свойства LastBadPasswordAttempt, но не в фильтре FindByBadPasswordAttempt.

Я нервничаю из-за того, что ввел это в производство, не зная, не хватает ли я чего-то (вероятно) или если документы MSDN ошибочны. Код запускается на запросе DC, поэтому не должно быть проблем с часовым поясом.

ответ

2

Документы MSDN являются точными, вам просто необходимо обратить внимание на .Kind свойства DateTime значений, которые проходят в.

Если вы копаться в справочных источниках или разборке достаточно далеко, вы обнаружите, что DateTime Значение, которое вы передаете, в конечном итоге переходит к DateTime.ToFileTimeUtc, что учитывает Kind в своем поведении.

Таким образом, вы можете передать значение на основе DateTime.UtcNow, который имеет .Kind в DateTimeKind.Utc и он будет работать, или вы можете сделать, как вы сейчас делаете и прохождение DateTime.Now который имеет .Kind в DateTimeKind.Local и что местное время будет преобразованный в UTC перед запросом. Убедитесь в том, что это местное время компьютера, на котором работает код. Если есть вероятность, что это не тот же часовой пояс, что и ваш пользователь, вам может понадобиться использовать TimeZoneInfo, чтобы получить эквивалент времени UTC для другого локального часового пояса.

Если по какой-либо причине вы решите передать дату, которую вы создали самостоятельно, она, вероятно, будет иметь DateTimeKind.Unspecified. Для этой конкретной функции это будет обрабатываться так, как если бы это был UTC. Это не обязательно верно для всех функций даты и времени, поэтому будьте осторожны с этим.

Кроме того, на выходе нет необходимости звонить Convert.ToDateTime, когда значение, с которым вы работаете, уже является DateTime. В этом случае вам даже не нужен ToString в этом коде, если вы не планируете передавать спецификатор формата. И снова, если ваш пользователь, возможно, находится в каком-либо другом часовом поясе, не используйте .ToLocalTime, используйте один из методов на , чтобы сделать преобразование.

Еще одна небольшая оптимизация, вы можете использовать DateTime.Today вместо DateTime.Now.Date, если хотите. (Это не имеет значения, кроме того, что оно немного читаемо.)

+1

Извините за задержку и спасибо за помощь - это помогает мне понять, что происходит, и советы приветствуются и оцениваются. – nedm

+0

Нет проблем. Рад, что смог помочь! –

Смежные вопросы