1
1
Fork 0
mirror of https://github.com/QB64Official/qb64.git synced 2024-06-28 19:20:38 +00:00
qb64/internal/c/time64.c
2018-06-30 14:23:33 -03:00

212 lines
5.4 KiB
C

/* 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 <time.h>
#include <windows.h>
#include <assert.h>
#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;
}