/* Copyright (c) Robert Walker, support@tunesmithy.co.uk * Free source. Do what you wish with it - treat it as you would * example code in a book on c programming. */ #include "time64.h" #undef time #undef localtime #undef mktime #undef difftime #undef gmtime #undef time_t #include #include #include #define SECS_TO_FT_MULT 10000000 #ifdef _DEBUG # define DEBUG_TIME_T #endif /* From MSVC help: * The gmtime, mktime, and localtime functions use the same single, * statically allocated structure to hold their results. Each call to * one of these functions destroys the result of any previous call. * If timer represents a date before midnight, January 1, 1970, * gmtime returns NULL. There is no error return. * * So here is the struct to use for our 64 bit implementation * * However, it may be useful to be able to make this thread safe */ #ifdef USE_THREAD_LOCAL_VARIABLES # define TIME64_THREAD_LOCAL _declspec(thread) #else # define TIME64_THREAD_LOCAL #endif TIME64_THREAD_LOCAL static struct tm today_ret; static void T64ToFileTime(t64 *pt, FILETIME *pft) { LARGE_INTEGER li; li.QuadPart = *pt * SECS_TO_FT_MULT; pft->dwLowDateTime = li.LowPart; pft->dwHighDateTime = li.HighPart; } static void FileTimeToT64(FILETIME *pft, t64 *pt) { LARGE_INTEGER li; li.LowPart = pft->dwLowDateTime; li.HighPart = pft->dwHighDateTime; *pt = li.QuadPart; *pt /= SECS_TO_FT_MULT; } //#define FindTimeTBase() ((t64) 11644473600) #define FindTimeTBase() (((__int64)11644) * 1000000 + 473600) // calculated using /** static t64 FindTimeTBase(void) { // Find 1st Jan 1970 as a FILETIME SYSTEMTIME st; FILETIME ft; memset(&st,0,sizeof(st)); st.wYear=1970; st.wMonth=1; st.wDay=1; SystemTimeToFileTime(&st, &ft); FileTimeToT64(&ft,&tbase); return tbase; } **/ static void SystemTimeToT64(SYSTEMTIME *pst, t64 *pt) { FILETIME ft; SystemTimeToFileTime(pst, &ft); FileTimeToT64(&ft, pt); *pt -= FindTimeTBase(); } static void T64ToSystemTime(t64 *pt, SYSTEMTIME *pst) { FILETIME ft; t64 t = *pt; t += FindTimeTBase(); T64ToFileTime(&t, &ft); FileTimeToSystemTime(&ft, pst); } t64 time_64(t64 *pt) { t64 t; SYSTEMTIME st; GetSystemTime(&st); SystemTimeToT64(&st, &t); #ifdef DEBUG_TIME_T { time_t t2 = time(NULL); if (t2 >= 0) // 2005 assert(abs(t2-(int)t)<=1); assert(abs((long)(t2 - (int)t)) <= 1); // the <=1 here is in case the seconds get incremented // betweeen the GetSystemTime(..) call and the time(..) call } #endif if (pt) *pt = t; return t; } double difftime_64(t64 time1, t64 time0) { return (double)(time1 - time0); } t64 mktime64(struct tm *today) { t64 t; SYSTEMTIME st; st.wDay = (WORD)today->tm_mday; st.wDayOfWeek = (WORD)today->tm_wday; st.wHour = (WORD)today->tm_hour; st.wMinute = (WORD)today->tm_min; st.wMonth = (WORD)(today->tm_mon + 1); st.wSecond = (WORD)today->tm_sec; st.wYear = (WORD)(today->tm_year + 1900); st.wMilliseconds = 0; SystemTimeToT64(&st, &t); return t; } #define DAY_IN_SECS (60 * 60 * 24) struct tm *gmtime_64(t64 t) { SYSTEMTIME st; T64ToSystemTime(&t, &st); today_ret.tm_wday = st.wDayOfWeek; today_ret.tm_min = st.wMinute; today_ret.tm_sec = st.wSecond; today_ret.tm_mon = st.wMonth - 1; today_ret.tm_mday = st.wDay; today_ret.tm_hour = st.wHour; today_ret.tm_year = st.wYear - 1900; { SYSTEMTIME styear; t64 t64Year; memset(&styear, 0, sizeof(styear)); styear.wYear = st.wYear; styear.wMonth = 1; styear.wDay = 1; SystemTimeToT64(&styear, &t64Year); today_ret.tm_yday = (int)((t - t64Year) / DAY_IN_SECS); } today_ret.tm_isdst = 0; #ifdef DEBUG_TIME_T { struct tm today2; long t32 = (int)t; if (t32 >= 0) { // 2005 today2=*gmtime(&t32); today2 = *gmtime((time_t *)&t32); assert(today_ret.tm_yday == today2.tm_yday); assert(today_ret.tm_wday == today2.tm_wday); assert(today_ret.tm_min == today2.tm_min); assert(today_ret.tm_sec == today2.tm_sec); assert(today_ret.tm_mon == today2.tm_mon); assert(today_ret.tm_mday == today2.tm_mday); assert(today_ret.tm_hour == today2.tm_hour); assert(today_ret.tm_year == today2.tm_year); } } { t64 t2 = mktime64(&today_ret); assert(t2 == t); } #endif return &today_ret; } struct tm *localtime_64(t64 *pt) { t64 t = *pt; FILETIME ft, ftlocal; T64ToFileTime(&t, &ft); FileTimeToLocalFileTime(&ft, &ftlocal); FileTimeToT64(&ftlocal, &t); today_ret = *gmtime_64(t); { TIME_ZONE_INFORMATION TimeZoneInformation; switch (GetTimeZoneInformation(&TimeZoneInformation)) { case TIME_ZONE_ID_DAYLIGHT: today_ret.tm_isdst = 1; break; case TIME_ZONE_ID_STANDARD: today_ret.tm_isdst = 0; break; case TIME_ZONE_ID_UNKNOWN: today_ret.tm_isdst = -1; break; } } return &today_ret; }