Я работаю над программой, которая записывает метаданные даты из файлов, такие как время создания, время последнего изменения и т.д. Старая версия программы написана в VBA и делает что-то вроде этого:
Public Function GetFileLastAccessTime(ByVal FilePath As String) As Date
Dim fso As New Scripting.FileSystemObject
Dim f As Scripting.File
Set f = fso.GetFile(FilePath)
GetFileLastAccessTime = f.DateLastAccessed
End Function
Результат для файла:
?getfilelastaccesstime("SomePath")
7/30/2010 2:16:07 PM
Это значение, которое я получаю из свойств файла в Windows Exploder. Счастье.
Я переношу эту функциональность в приложение VB.Net. Новый код:
Public Function GetLastAccessTime(ByVal FilePath As String) As Date
Return IO.File.GetLastAccessTime(FilePath)
End Function
Простота. Выход:
?GetLastAccessTime("SomePath")
#7/30/2010 3:16:07 PM#
Через час.
Обе функции работают на одном компьютере, проверяя один и тот же файл. Я также попытался использовать класс IO.FileInfo с тем же результатом. Я проверил тысячи файлов, и все они отключены на один час. Другие свойства даты для времени создания и последнего измененного времени также отключены на один час.
Help!
Я забыл упомянуть в исходном сообщении, часовой пояс компьютера - это CST, а летнее время в настоящее время не действует.
Я воспроизвел проблему на 64-разрядной версии Windows 7 и 32-разрядной версии Windows XP.
Спасибо.
Обновление1/6/2011:
Спасибо всем, кто предложил рассчитать желаемую дату из UTC, используя соответствующие смещения часового пояса. В это время я решаю, что не стоит этого рисковать. Для этого конкретного бизнес-требования гораздо лучше сказать, что значение даты не то, что вы ожидали от него, потому что это так, как работает API. Если я попытаюсь "исправить" это, тогда я его получу, и я предпочел бы этого не делать.
Просто для ударов я попытался использовать старый добрый Scripting.FileSystemObject через interop. Он дает ожидаемые результаты, которые согласуются с Windows Explorer, с примерно 5-кратным снижением производительности по сравнению с System.IO. Если окажется, что я должен установить даты, которые соответствуют тому, что есть в Проводнике Windows, я буду укусить пулю и пойти по этому маршруту.
Другой эксперимент, который я попробовал, прямо перешел к функции API GetFileTime в kernel32 через С#:
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GetFileTime(
IntPtr hFile,
ref FILETIME lpCreationTime,
ref FILETIME lpLastAccessTime,
ref FILETIME lpLastWriteTime
);
Это привело к точному поведению System.IO, время было отключено на один час от Проводника Windows.
Еще раз спасибо всем.