2
Vote

ZlpFileInfo.CreationTime == FileInfo.CreationTimeUtc

description

All the Create/Access/Modified times of ZlpFileInfo are returned in UTC instead of local time.
This is different from FileInfo, which has both (e.g. variables FileInfo.CreationTime and FileInfo.CreationTimeUtc).
 
Not really an issue, but the behavior changes when changing code to using ZlpFileInfo instead of FileInfo.
 
Also, there are 4 functions that get info stored as a long from the same source (GetFileLastWriteTime(), GetFileLastAccessTime(), GetFileCreationTime() and GetFileLength()). Lots of copied code.

file attachments

comments

einarjon wrote Aug 16, 2011 at 12:12 PM

Proposed fix/code cleanup...
Only one private function that actually gets the WIN32_FIND_DATA struct.
Easy to get both UTC and Local dates, like in FileInfo.
enum LongType
{
    CreationTime,
    LastWriteTime,
    LastAccessTime, 
    FileLength
}
    public static DateTime GetFileLastWriteTime(
        string filePath)
    {
        long time = getLongValue(filePath, LongType.LastWriteTime);
        return (time==0)?DateTime.MinValue:DateTime.FromFileTime(time);
    }

    public static DateTime GetFileLastAccessTime(
        string filePath)
    {
        long time = getLongValue(filePath, LongType.LastAccessTime);
        return (time==0)?DateTime.MinValue:DateTime.FromFileTime(time);
    }

    public static DateTime GetFileCreationTime(
        string filePath)
    {
        long time = getLongValue(filePath, LongType.CreationTime);
        return (time==0)?DateTime.MinValue:DateTime.FromFileTime(time);
    }

    public static DateTime GetFileLastWriteTimeUtc(
        string filePath)
    {
        long time = getLongValue(filePath, LongType.LastWriteTime);
        return (time==0)?DateTime.MinValue:DateTime.FromFileTimeUtc(time);
    }

    public static DateTime GetFileLastAccessTimeUtc(
        string filePath)
    {
        long time = getLongValue(filePath, LongType.LastAccessTime);
        return (time==0)?DateTime.MinValue:DateTime.FromFileTimeUtc(time);
    }

    public static DateTime GetFileCreationTimeUtc(
        string filePath)
    {
        long time = getLongValue(filePath, LongType.CreationTime);
        return  (time==0)?DateTime.MinValue:DateTime.FromFileTimeUtc(time);
    }

    // helper function for a total of 7 functions
    private static long getLongValue(
        string filePath,
        LongType type)
    {
        filePath = CheckAddLongPathPrefix(filePath);

        PInvokeHelper.WIN32_FIND_DATA fd;
        long hft2 = 0;
        var result = PInvokeHelper.FindFirstFile(filePath.TrimEnd('\\'), out fd);
        if (result != PInvokeHelper.INVALID_HANDLE_VALUE)
        {
            try
            {
                if (result.ToInt32() != PInvokeHelper.ERROR_FILE_NOT_FOUND)
                {

                    PInvokeHelper.FILETIME ft;

                    switch (type)
                    {
                        case LongType.CreationTime:
                            ft = fd.ftCreationTime;
                            break;
                        case LongType.LastWriteTime:
                            ft = fd.ftLastWriteTime;
                            break;
                        case LongType.LastAccessTime:
                            ft = fd.ftLastAccessTime;
                            break;
                        case LongType.FileLength:
                            ft.dwLowDateTime = (uint)fd.nFileSizeLow;
                            ft.dwHighDateTime = (uint)fd.nFileSizeHigh; 
                            break;
                        default:
                            return 0;
                    }

                    hft2 = (((long)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
                }
            }
            finally
            {
                PInvokeHelper.FindClose(result);
            }
        }
        return hft2;
    }

    public static long GetFileLength(string filePath)
    {
        return getLongValue(filePath, LongType.FileLength);
    }

wrote Jan 30, 2012 at 4:19 AM

bean wrote Jan 30, 2012 at 4:23 AM

I agree, it should not be returning UTC. I know .NET knows the datetime object is UTC then somehow translates the time almost back to local using the timezone only, but if you have daylight saving then it gets it wrong and you end up with the time 1 hour out (adds 1 more hour than it should).

SOLUTION: Change all calls back to: DateTime.FromFileTime(hft2)

wrote Feb 2, 2012 at 9:53 AM

bean wrote Feb 2, 2012 at 9:53 AM

I take it back. Using DateTime.FromFileTime(hft2) works on my Win7 system, but screws up on WinXP.
I looked into a new project - longpathsupport.codeplex.com. Which looks really good. He does the filetimes very differently - calling a Win32 API to do the conversion. I implemented that then had to do a bit of strange conversion, but it works. Different Win versions, timezones etc.
Attached is my version of ZLP (with binary) with all known bugs fixed and corrected time handling.

wrote Feb 14, 2013 at 2:38 AM