使用以下方法进行转换时,我读到的大多数文件都是合适的时间:
// 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:\ Users \ Tono \ Documents \ Visual Studio 2010 \ Projects \ WpfApplication4 \ WpfApplication4 \ obj \ x86 \ Debug \ App.g.cs”
这是我试图转换为DateTime的FILETIME“顺便说一下我需要LastWriteTime”
在这里,您可以看到dwHighDateTime = 30136437以及该文件中的dwLowDateTime = -2138979250。
当我运行我的方法加上其他技术时,我得到以下日期:
所以到目前为止,一切似乎都很有效。但是为什么当我在Windows中浏览并查找特定文件时,我会得到一个不同的日期!这是我在查看文件属性时得到的日期:
为什么日期不匹配?我究竟做错了什么?
答案 0 :(得分:16)
您需要按位组合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))
你可以通过添加而不是按位来逃避 - 或者如果你确定值是正的(并且没有共同的位)。但是按位 - 或更好地表达意图。
答案 1 :(得分:7)
我参加派对有点晚了,但这对我来说是可靠的:
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资源管理器。例如,使用File.GetLastWriteTimeUtc方法验证文件系统实际上对此扩展方法返回的内容。资源管理器中存在一些错误,在某些情况下不会更新文件时间。干杯! :)
注意:要对此进行测试,您需要使用最大值。因此,假设dwHighDateTime = dwLowDateTime = UInt32.MaxValue = 4294967295 = 0xFFFFFFFF
,它遵循(long)(((ulong)UInt32.MaxValue << 32) + UInt32.MaxValue) = -1 = 0xFFFFFFFFFFFFFFFF
。不幸的是,Windows API中的谬误似乎是最终需要将时间转换为long
值,以便为任何有用的应用程序使用它(因为大多数Windows API方法将文件时间视为{ {1}}值),这意味着一旦long
上的前导位为高(1
),该值就变为负值。让我们尝试最大时间不高。假设dwHighDateTime
和dwHighDateTime = Int32.MaxValue = 2147483647 = 0x7FFFFFFF
,则遵循dwLowDateTime = UInt32.MaxValue = 4294967295 = 0xFFFFFFFF
。
注意:(long)(((ulong)Int32.MaxValue << 32) + UInt32.MaxValue) = 0x7FFFFFFFFFFFFFFF
已经比0x7FFFFFFFFFFFFFFF
大得多,渲染数量已经无法用于.NET中的任何实际应用程序。
答案 2 :(得分:5)
这是我看到的将FileTime结构转换为long(使用struct中的编码运算符)的另一种方法,然后可以使用DateTime.FromFileTime函数轻松地将其转换为DateTime:
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;
}
}
答案 3 :(得分:0)
dwLowDateTime
和dwHighDateTime
应为uint
,看起来好像是int
。改变这种情况很可能会解决这个问题,因为@Joe指出你仍然应该使用|
代替+
。
答案 4 :(得分:0)
我尝试了以下内容,并且没有给我正确的时间:
我从here
获得了方法