Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Time64 - 64 bit Times for 32 bit Windows Apps

0.00/5 (No votes)
5 Aug 2003 4  
64-bit version of C time routines for Windows

1:43:38 PM Saturday, July 30, 2095 GMT Daylight Time

Introduction

The C time routines such as time(), localtime(), etc. represent time as seconds from 1st January 1970. The variable type time_t is defined as a 32 bit signed integer - to permit negative times for the seconds difference between two times.

This means that if you use them in a 32-bit build, then normally, the maximum time that can be represented is Tue Jan 19 03:14:07 2038. This is the C language equivalent of the Y2K bug - but is far more easily solved. You just need to do a 64 bit build to solve it.

However, maybe you want to do a 32 bit build for 32 bit operating systems. Maybe also, you want your program to work fine beyond 2038 without a new build, in case anyone uses it still in those days as a legacy app. Well - this library solves the problem. The Windows operating system uses 64 bit times internally (in a rather eccentric format of 100 nanosecond intervals from 1st January 1601). So, it is just a matter of interfacing with those properly, to make a 64 bit version of the C routines for Windows.

It is suitable for use with MSVC or any compiler that supports the __int64 data type. If your compiler has a native 64 bit integer type, but it has some other name, then you need to edit the source code accordingly.

I am a pure C programmer and haven't used CTime, but maybe if you include this library, then CTime will also behave as desired - or maybe more work needs to be done. Comments welcome from C++ programmers. Anyone interested in converting this library to C++?

Using the Code

Include the source code time64.c or time64.cpp for C++ programs as part of your program. Place the header time64.h at the head of every file that uses the time routines. All your time_t variables will now be __int64. However, if you need to use them in other routines, you can convert them to UINT, which will still be valid until the end of this century and beyond. Particularly, UINT could be used for file input and output.

That's all there is to it.

See It In Action

The zip for download includes an MSVC project to make a tiny app, that just displays the current time. Test that to see how it works - but first a few warnings are in order. It may sometimes cause a few problems if you vary the calendar on your computer.

Some programs with 30 day trial periods can behave crankily if you change the system time - may tell you that the trial period is over even after you adjust the time back again - so make sure you have no such programs running when you do it.

Others may crash if you go beyond 2038. That's because time_t has to be non negative for the Windows implementation of most of the time routines. If you call them with negative values you may get an access violation. See for instance, Problems Running Windows Media Player 7 or 7.1 with a Date that Is Later than January 18, 2038.

Others may behave strangely if you change the date. For instance, probably it is best to close your browser, in case its history folder gets confused. So, close anything that might be sensitive to the date before varying the calendar date to test this library. If in doubt, use Ctrl Alt + Delete and close everything there except Explorer.

Check out my Work Log program for an example of an app that uses this library.

Points of Interest

This library uses the Windows FILETIME file type, which is 64 bit and represents time in 100 nanosecond intervals since Jan 1 1601. So the task was to make a wrapper for this type which will let one work with a 64 bit time_t variable.

For an introduction to the various time routines used in Windows, see the CodeProject page Date and Time in C++.

The main point to bear in mind to read the code is that FILETIME can't be used directly but has to be converted into an __int64 variable before you can use arithmetical operations with it. Then the Windows equivalent of the tm structure is SYSTEMTIME. Most fields are the same but the month starts at 1 instead of 0, and the year in the tm structure is shown as years since 1900 so you need to subtract 1900 to convert a SYSTEMTIME to a tm and add it to get back again.

Also to convert a FILETIME to a time_t, then you need to subtract the number of seconds between 1st Jan 1601 and 1st Jan 1970. Luckily, we can do that quite easily by making a SYSTEMTIME for 1st Jan 1970 and then use the routine SystemTimeToFileTime to find what this date is in seconds.

The 64 bit variable type for time_t is called t64 internally in the library. So that should be enough to follow the code. Here is the heart of it - where the various data types get inter-converted:

#define SECS_TO_FT_MULT 10000000
static void T64ToFileTime(t64 *pt,FILETIME *pft)
{
 LARGE_INTEGER li;    
 *pt*=SECS_TO_FT_MULT;
 li.QuadPart=*pt;
 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;
}

static t64 FindTimeTBase(void)
{
 // Find 1st Jan 1970 as a FILETIME 
 t64 tbase;
 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);
 return t;
}

Then we also need to do those conversions just mentioned, to get from SYSTEMTIME to / from tm. That is easy to do - I will leave it for you to look at the file in the zip, if you want more information.

History

  • 30th July, 2003: First release

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here