BUG: Time Moves Backwards 24 Hours with GetSystemTimeAsFileTime()

ID: Q224423


The information in this article applies to:


SYMPTOMS

If GetSystemTimeAsFileTime() is called at the precise split second during which the date changes from one day to the next (12:00:00.000 AM), the API may return a value indicating 12:00 AM for the previous day.


RESOLUTION

If it is necessary for your program to guard against this bug, you should keep track of the previously retrieved time and compare the newly retrieved time to it. This method is demonstrated in the sample code at the end of this article. In the event that time "moves backwards," you can immediately call GetSystemTimeAsFileTime() again to retrieve the correct time.


STATUS

Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article.


MORE INFORMATION

Steps to Reproduce Behavior

The code below demonstrates the bug by repeatedly setting the system time to just before midnight and calling GetSystemTimeAsFileTime(); it does this in a loop until the error occurs:


#include <windows.h>
#include <stdio.h>

typedef union {
    unsigned __int64 ft_scalar;
    FILETIME ft_struct;
} FT;

// Function used to display a FILETIME in a human readable format.
void DisplayFileTime(FILETIME* lpFt) {
    FILETIME ftLocalFileTime;
    SYSTEMTIME stLocalSystemTime;

    FileTimeToLocalFileTime(lpFt, &ftLocalFileTime);
    FileTimeToSystemTime( &ftLocalFileTime, &stLocalSystemTime);

    printf("%d/%d/%d %d:%d:%d\n",
        stLocalSystemTime.wMonth,
        stLocalSystemTime.wDay,
        stLocalSystemTime.wYear,
        stLocalSystemTime.wHour,
        stLocalSystemTime.wMinute,
        stLocalSystemTime.wSecond);
}

void main() {

    SYSTEMTIME st;
    FT ft1, ft2;

    DWORD dwStart;
    int i = 0;

    st.wYear = 1999;
    st.wMonth = 1;
    st.wDayOfWeek = 3;
    st.wDay = 12;
    st.wHour = 23;
    st.wMinute = 59;
    st.wSecond = 59;
    st.wMilliseconds = 0;

    while (TRUE)
    {
        i++;
        printf("Test number %u.\n", i);

        // Set the local time to just before midnight.
        SetLocalTime(&st);

        GetSystemTimeAsFileTime(&ft2.ft_struct);
        dwStart = GetTickCount();

        do
        {
            ft1 = ft2;
            GetSystemTimeAsFileTime(&ft2.ft_struct);

            // Check to see if time moved backwards.
            if (ft2.ft_scalar - ft1.ft_scalar > 100000000i64)
            {
                // If discrepancy greater than 100 seconds...
                printf("Time went backwards!\n");
                printf("Time before: ");
                DisplayFileTime(&ft1.ft_struct);
                printf("Time after: ");
                DisplayFileTime(&ft2.ft_struct);

                // Call the API again to get the correct time.
                GetSystemTimeAsFileTime(&ft2.ft_struct);
                printf("Correct time: ");
                DisplayFileTime(&ft2.ft_struct);
                return;
            }
        } while (GetTickCount() - dwStart < 1050);
    }
} 

Additional query words:


Keywords          : kbDateTime kbKernBase kbWinOS95 kbWinOS98 
Version           : winnt:
Platform          : winnt 
Issue type        : kbbug 

Last Reviewed: April 7, 1999