Click here to Skip to main content
Click here to Skip to main content

Time64 - 64 bit Times for 32 bit Windows Apps

, 5 Aug 2003
Rate this:
Please Sign up or sign in to vote.
64-bit version of C time routines for Windows

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


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)

static void FileTimeToT64(FILETIME *pft,t64 *pt)
 li.LowPart = pft->dwLowDateTime;
 li.HighPart = pft->dwHighDateTime;

static t64 FindTimeTBase(void)
 // Find 1st Jan 1970 as a FILETIME 
 t64 tbase;
 SystemTimeToFileTime(&st, &ft);
 return tbase;

static void SystemTimeToT64(SYSTEMTIME *pst,t64 *pt)
 SystemTimeToFileTime(pst, &ft);

static void T64ToSystemTime(t64 *pt,SYSTEMTIME *pst)
 t64 t=*pt;

t64 time_64(t64 *pt)
 t64 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.


  • First release 30th July 2003


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


About the Author

Robert Inventor
Web Developer
United Kingdom United Kingdom
Trained as a mathematician.
Now I program shareware apps - music and 3D. Main ones so far, Fractal Tune Smithy (music) and Virtual Flower (3D / VRML).

Comments and Discussions

Generalgood approach for visual c++ 6 Pinmemberdavid_joung25-Oct-10 17:45 
GeneralA few small problems.... PinmemberJames Curran14-Aug-03 0:47 
GeneralRe: A few small problems.... PinmemberR. Walker14-Aug-03 7:20 
GeneralInefficaciously Pinsuss???@???5-Aug-03 20:26 
QuestionWhy reinvent teh wheel !? Pinsussanonymous5-Aug-03 7:56 
AnswerRe: Why reinvent teh wheel !? PinsussAnonymous5-Aug-03 9:48 
AnswerRe: Why reinvent teh wheel !? PinmemberJames Curran14-Aug-03 0:41 
GeneralRe: Why reinvent teh wheel !? PinmemberR. Walker14-Aug-03 8:47 
Hi James,
Yes that's true - same for time(..) so I'm not surprised to see it for time64(..). But it's a limitation of the operating system rather than this library.
This library supports negative 64 bit time_t. However, you can't test it by setting the system time.
Instead, try replacing the WM_PAINT call with
 hdc = BeginPaint(hWnd, &ps);
 RECT rt;
 tm *today=localtime(&t);
and you will find that it shows a time in the 17th century.
This could make the library useful for anyone who wants to work with times from 17th century onwards and display them, and find the differences between two such times etc. Also to port any code from Unix that relies on negative time_t to represent dates in the nineteenth century.
You can't set the system clock to any earlier than 1980 - on Win 98 anyway. That's the earliest you can set it using the calender, and the same limitation applies if you try to do it calling the routines in the API.
Here is how one would do it to try to set the system time to the early 17th century:
(usual cautions about setting the system time - and additional caution about possible crashes, as with setting it to later than 2038). You have to enable system-time priviledge to do it.
 time_t  t=-10000000000;
 /* enable system-time privilege, set time, disable privilege */
 HANDLE hToken;
 LUID             luid;      
  ( GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ;
 LookupPrivilegeValue( NULL, SE_SYSTEMTIME_NAME /***"SeSystemTimePrivilege"**/, &luid ); 
 tp.PrivilegeCount           = 1; 
 tp.Privileges[0].Luid       = luid; 
 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
 if(ERROR_SUCCESS==AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL ))
  AdjustTokenPrivileges( hToken, TRUE, &tp,sizeof(TOKEN_PRIVILEGES), NULL, NULL );                  
If this works, then when you use this library (though not normally of course)
should give a time in the early 17th century.
But it doesn't work. You get an error message here that the parameter for SetLocalTime() is incorrect in Windows 98 if you try to set the date to any system date before 1980.
The error handler here is the standard:
void ErrorHandler(char *szError)
#define ONE_K 1024
 char szMsg[ONE_K];
 LPVOID lpMsgBuf;
 static char in_this;
  ,(LPTSTR) &lpMsgBuf
 LocalFree( lpMsgBuf );

GeneralRe: Why reinvent teh wheel !? Pinmemberashishlal5-Mar-09 19:44 
GeneralUpdated zip PinmemberR. Walker2-Aug-03 0:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 6 Aug 2003
Article Copyright 2003 by Robert Inventor
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid