无法从 FILETIME (Windows 时间)转换为 dateTime (我得到了不同的日期)

发布于 2024-11-09 10:07:12 字数 1077 浏览 7 评论 0原文

我读到的大多数文件在使用以下方法进行转换时都得到了正确的时间:

// 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 中浏览并查找该特定文件时,我会得到不同的日期!?这是我在查看文件属性时得到的日期: 在此处输入图像描述

为什么日期不匹配?我做错了什么?

Most of the files I read get the right time when using the following method to convert:

// 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);
}

Here I have an example in visual studio to show how this method sometimes does not work for example I will show the actual file in my computer and the debug. So the file that happens to be in my debug is:

"A:\Users\Tono\Documents\Visual Studio 2010\Projects\WpfApplication4\WpfApplication4\obj\x86\Debug\App.g.cs"
enter image description here

And here is the FILETIME that I am trying to convert to DateTime "I need the LastWriteTime by the way"

enter image description here

Here you can see that dwHighDateTime = 30136437 and also that dwLowDateTime = -2138979250 from that file.

And when I run my method plus other techniques I get the following dates:
enter image description here

So so far everything seems to be working great. But why is that that when I browse and look for that specific file in windows I get a different date !? Here is the date that I get when seeing the file's properties:
enter image description here

Why does the dates don't match? What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

剩余の解释 2024-11-16 10:07:12

您需要按位而不是算术方式组合 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))

您可以通过加法而不是按位来逃脱,或者如果您确定这些值是正数(并且没有共同位)。但按位或可以更好地表达意图。

You need to combine the LS and MS values bitwise, not arithmetically.

Try:

        ulong high = 30136437;
        unchecked
        {
            int low = -2138979250;
            uint uLow = (uint)low;
            high = high << 32;
            Date dt = DateTime.FromFileTime((long) (high | (ulong)uLow));
        }

Or any of the following should work too:

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))

You can get away with adding rather than a bitwise-or if you are sure the values are positive (and have no bits in common). But bitwise-or expresses the intent better.

一袭白衣梦中忆 2024-11-16 10:07:12

我参加聚会有点晚了,但这对我来说很可靠:

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< /a> 方法,例如,根据此扩展方法返回的内容来验证文件系统实际具有的内容。资源管理器存在一些错误,在某些情况下不会更新文件时间。干杯! :)

注意:要测试这一点,您需要使用最大值。因此,假设 dwHighDateTime = dwLowDateTime = UInt32.MaxValue = 4294967295 = 0xFFFFFFFF,则可以得出 (long)(((ulong)UInt32.MaxValue << 32) + UInt32.MaxValue) = -1 = 0xFFFFFFFFFFFFFFFF。不幸的是,Windows API 中的谬误似乎是,最终需要将时间转换为 long 值,以便将其用于任何有用的应用程序(因为大多数 Windows API 方法都会占用文件时间)作为 long 值),这意味着一旦 dwHighDateTime 上的前导位为高电平 (1),该值就会变为负值。让我们尝试一下最大时间不要太长。假设 dwHighDateTime = Int32.MaxValue = 2147483647 = 0x7FFFFFFF 和 dwLowDateTime = UInt32.MaxValue = 4294967295 = 0xFFFFFFFF,则得出 (long)(((ulong)Int32 .MaxValue << 32) + UInt32.MaxValue) = 0x7FFFFFFFFFFFFFFF

注意0x7FFFFFFFFFFFFFFF已经比DateTime.MaxValue.ToFileTimeUtc() = 2650467743999999999 = 0x24C85A5ED1C04000大得多,渲染这么大的数字对于任何实际应用来说已经毫无用处.NET 中的应用程序。

I'm a bit late to the party, but this has worked reliably for me:

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);
        }
    }
}

Note: Don't trust Windows Explorer. Use File.GetLastWriteTimeUtc method, for example, to verify what the file system actually has against what this extension method returns. Explorer has some bugs in it that don't update file times in certain situations. Cheers! :)

Note: To test this, you need to use maximum values. So, assuming dwHighDateTime = dwLowDateTime = UInt32.MaxValue = 4294967295 = 0xFFFFFFFF, it follows that (long)(((ulong)UInt32.MaxValue << 32) + UInt32.MaxValue) = -1 = 0xFFFFFFFFFFFFFFFF. Unfortunately, the fallacy in the Windows API seems to be that eventually the time needs to be casted to a long value in order to work with it for any useful applications (since most Windows API methods take the file time as a long value), which means once the leading bit is high (1) on dwHighDateTime, the value becomes negative. Lets try with the maximum time not being high. Assuming dwHighDateTime = Int32.MaxValue = 2147483647 = 0x7FFFFFFF and dwLowDateTime = UInt32.MaxValue = 4294967295 = 0xFFFFFFFF, it follows that (long)(((ulong)Int32.MaxValue << 32) + UInt32.MaxValue) = 0x7FFFFFFFFFFFFFFF.

Note: 0x7FFFFFFFFFFFFFFF is already much larger than DateTime.MaxValue.ToFileTimeUtc() = 2650467743999999999 = 0x24C85A5ED1C04000, rendering numbers that large already useless for any practical applications in .NET.

兰花执着 2024-11-16 10:07:12

这是我见过的另一种将 FileTime 结构转换为 long 的方法(使用结构中的编码运算符),然后可以使用 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;
    }
}

This is another method that I have seen to convert a FileTime structure to a long (using a coded operator in the struct), which can then easily be converted to DateTime using the DateTime.FromFileTime functions:

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;
    }
}
南烟 2024-11-16 10:07:12

我已经尝试过以下方法,但没有一个让我找到合适的时间:
在此处输入图像描述

我从 这里

I have tried the following and non of them get me the right time:
enter image description here

And I got the method from here

夏至、离别 2024-11-16 10:07:12

dwLowDateTimedwHighDateTime 应该是 uint,看起来它们是 int。更改此设置很可能会修复它,但正如 @Joe 指出的那样,您仍然应该使用 | 而不是 +

dwLowDateTime and dwHighDateTime should be uint and it looks like they are int. Changing this will most likely fix it though as @Joe pointed out you should still use | instead of +.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文