не удается конвертировать из FILETIME (windows time) в dateTime (я получаю другую дату)
большинство файлов, которые я читаю, получают правильное время при использовании следующего метода преобразования:
// works great most of the time
private static DateTime convertToDateTime(System.Runtime.InteropServices.ComTypes.FILETIME time)
{
long highBits = time.dwHighDateTime;
highBits = highBits << 32;
return DateTime.FromFileTimeUtc(highBits + time.dwLowDateTime);
}
здесь у меня есть пример в visual studio, чтобы показать, как этот метод иногда не работает, например, я покажу фактический файл на своем компьютере и отладку. Таким образом, файл, который находится в моей отладке:
"A:UsersTonoDocumentsVisual Studio 2010проектыWpfApplication4WpfApplication4objx86DebugApp.г.в CS"
а вот FILETIME, который я пытаюсь преобразовать в DateTime "мне нужно LastWriteTime кстати"
здесь вы можете увидеть, что dwHighDateTime = 30136437, а также что dwLowDateTime = -2138979250 из этого файла.
и когда я запускаю мой метод и другие методы, я получаю следующие даты:
так до сих пор все, кажется, работает отлично. Но почему это так, когда я просматриваю и ищу этот конкретный файл в windows, я получаю другое свидание !? Вот дата, которую я получаю при просмотре свойств файла:
почему даты не совпадают? Что я делаю не так?
5 ответов
вам нужно объединить значения LS и MS побитово, а не арифметически.
попробуй:
ulong high = 30136437;
unchecked
{
int low = -2138979250;
uint uLow = (uint)low;
high = high << 32;
Date dt = DateTime.FromFileTime((long) (high | (ulong)uLow));
}
или любое из следующего должно работать слишком:
long highBits = time.dwHighDateTime;
highBits = highBits << 32;
return DateTime.FromFileTimeUtc(highBits + (long) (uint) time.dwLowDateTime);
return DateTime.FromFileTimeUtc(highBits | (long) (uint) time.dwLowDateTime);
return DateTime.FromFileTimeUtc(highBits + ((long)low & 0xFFFFFFFF))
return DateTime.FromFileTimeUtc(highBits | ((long)low & 0xFFFFFFFF))
Вы можете уйти с добавлением, а не побитовое или, если вы уверены, что значения являются положительными (и не общего). Но побитовое или лучше выражает намерения.
Это еще один метод, который я видел, чтобы преобразовать структуру FileTime в long (используя закодированный оператор в структуре), который затем может быть легко преобразован в DateTime с помощью DateTime.Функции FromFileTime:
public struct FileTime
{
public uint dwLowDateTime;
public uint dwHighDateTime;
public static implicit operator long(FileTime fileTime)
{
long returnedLong;
// Convert 4 high-order bytes to a byte array
byte[] highBytes = BitConverter.GetBytes(fileTime.dwHighDateTime);
// Resize the array to 8 bytes (for a Long)
Array.Resize(ref highBytes, 8);
// Assign high-order bytes to first 4 bytes of Long
returnedLong = BitConverter.ToInt64(highBytes, 0);
// Shift high-order bytes into position
returnedLong = returnedLong << 32;
// Or with low-order bytes
returnedLong = returnedLong | fileTime.dwLowDateTime;
// Return long
return returnedLong;
}
}
я немного опоздала на вечеринку, но это работает для меня:
public static class FILETIMEExtensions
{
public static DateTime ToDateTime(this System.Runtime.InteropServices.ComTypes.FILETIME time)
{
ulong high = (ulong)time.dwHighDateTime;
uint low = (uint)time.dwLowDateTime;
long fileTime = (long)((high << 32) + low);
try
{
return DateTime.FromFileTimeUtc(fileTime);
}
catch
{
return DateTime.FromFileTimeUtc(0xFFFFFFFF);
}
}
}
Примечание: не доверяйте проводнику Windows. Использовать .GetLastWriteTimeUtc метод, например, чтобы проверить, что файловая система на самом деле имеет против того, что возвращает этот метод расширения. В проводнике есть некоторые ошибки, которые не обновляют время файла в определенных ситуациях. Ура! :)
Примечание: чтобы проверить это, вам нужно использовать максимальные значения. Итак, предполагая, что dwHighDateTime = dwLowDateTime = UInt32.MaxValue = 4294967295 = 0xFFFFFFFF
, следует, что (long)(((ulong)UInt32.MaxValue << 32) + UInt32.MaxValue) = -1 = 0xFFFFFFFFFFFFFFFF
. К сожалению, ошибка в API Windows, кажется, что в конечном итоге время должно быть приведено к long
значение для работы с ним для любых полезных приложений (так как большинство методов Windows API принимают время файла как long
value), что означает, что как только ведущий бит высок (1
) on dwHighDateTime
, значение становится отрицательным. Давайте попробуем с максимальным временем не быть высоким. Предполагая dwHighDateTime = Int32.MaxValue = 2147483647 = 0x7FFFFFFF
и dwLowDateTime = UInt32.MaxValue = 4294967295 = 0xFFFFFFFF
, следует, что (long)(((ulong)Int32.MaxValue << 32) + UInt32.MaxValue) = 0x7FFFFFFFFFFFFFFF
.
Примечание: 0x7FFFFFFFFFFFFFFF
уже намного больше, чем DateTime.MaxValue.ToFileTimeUtc() = 2650467743999999999 = 0x24C85A5ED1C04000
, рендеринг чисел, которые большие уже бесполезны для любых практических приложений.Сеть.
Я попробовал следующее, и не из них, получите меня в нужное время:
и я получил метод от здесь
dwLowDateTime
и dwHighDateTime
должно быть uint
и, похоже, они int
. Изменение этого, скорее всего, исправит это, хотя, как отметил @Joe, вы все равно должны использовать |
вместо +
.