Inventive Software
For Windows
Home Music 3D Art Utilities Source Code Search Site Forums About Me Contact Accessibility
Mem Leak Check
Play Midi Lib
Com Ports Monitor
Win Ming
Pop Pal Fast
Gle with time out
Time64

Time64

64-bit version of C time routines for Windows

August 14th 2003 (UK time)

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

Intro, Using the source code, See it in action, Download, Dates before 1980, Changes

Intro

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. For an intro to this, see What is the Year 2038 problem?

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 versions 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.

Note

You may not need this library if you have MSVC 7.0 as it supports 64 bit time_t. See Time Management

However, this library still has some advantages.

It can show dates before 1970 - in fact it can represent times back to just after the start of the 17th century. The MSVC one won't accept negative time_t. Another advantage is that you can use existing source code with no need to rewrite anything. Just include the header and all your usual time_t routines will still work, but will be 64-bit.

Code project page

top

Using the source code

Include the source code and header itself with your app.

Place the header 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 wherever you need to use format specification fields in fprintf and sprintf. If you use %d with __int64 in a 32 bit build then the variable overflows to the next format field.

Perhaps an example may help. This is a simple implimentation of a save of the current time to a .ini file, using the sort of method a pure C programmer (rather than C++ programmer) might use.

fprintf(fp, "time_saved %lu\n", (UINT) time( NULL ) );
   // convert it to unsigned long so that you can use it in sprintf

Then output the string to the file.

When you want to read it in again you could input the line and then use

{
 time_t time_saved=0;
 UINT u=0;
 fscanf( fp, "%*s%lu", &u);
  // read it in as an unsigned long as sscanf can't read to __int64 variables directly
 time_saved=u;
}

(or alternatively use sscanf and sprintf to write to / read from a string, advance along the string as one does so, and then save the string to a file).

At least that is how one might do it if one wanted to use a text format save rather than a binary one. In a binary save you would probably not need to do any conversion but could just write out the variable in binary using sizeof() to find its size.

top

 

See it in action

The zip for download includes a MSVC project to make a tiny app that just displays the current time - see the screen shot at the head of this page. You can change the date on your calender and see how it responds - but first a few warnings are in order.

Note 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 for time_t then you may get an access violation. See 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 calender date to test this library. If in doubt, use Ctrl Alt + Delete and close everything there except Explorer.

Check out my WorkLog program for an example of an app that uses this library

top

Source code

So anyway without further ado, here it is.

time64.zip

Includes the time64.c and time64.h files. Also includes a MSVC project with an example windows program using it.

The example program is a c++ one made simply by modifying the Hello World app to show the time. It has a c++ version of the source code: time64.cpp which differs only in the headers included at the head of the file.

This is free source - do with it as you like. Treat it as you would a demo program in a c programming book.

top

Dates before 1980

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;
t=-10000000000;
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.

Another place where it may be useful - you can use negative time_t values in Unix to represent dates in the twentieth century, but you can only use positive time_t in Windows, so this code could be helpful if you want to port code from Unix.

You can't set the Windows system time to any date 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;
 SYSTEMTIME st;
 T64ToSystemTime(&t,&st);
 /* enable system-time privilege, set time, disable privilege */
 HANDLE hToken;
 TOKEN_PRIVILEGES tp; 
 LUID             luid;      
 OpenProcessToken
  ( 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 ))
 {
  if(!SetLocalTime(&st))
  {
   ErrorHandler("SetLocalTime");
  }
  AdjustTokenPrivileges( hToken, TRUE, &tp,sizeof(TOKEN_PRIVILEGES), NULL, NULL );                  
 }

If this works, then when you use this library (though not normally of course)

t=time(NULL);

should give a time in the early 17th century.

But it doesn't work, at least not in Windows 98. 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:

#include <stdio.h>
void ErrorHandler(char *szError)
{
#define ONE_K 1024
char szMsg[ONE_K];
LPVOID lpMsgBuf;
static char in_this;
if(in_this)
return;
in_this=1;
FormatMessage
(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS
,NULL
,GetLastError()
,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)
,(LPTSTR) &lpMsgBuf
,0
,NULL
);
sprintf(szMsg,"%s\n\n%s",szError,lpMsgBuf);
MessageBox(NULL,szMsg,"Error",MB_ICONEXCLAMATION|MB_TOPMOST);
LocalFree( lpMsgBuf );
in_this=0;
}

top

Changes

Contact e-mail:

Robert Walker support@tunesmithy.co.uk

August 14th

Original version of T64ToFileTime modified its t64 argument. New version:

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;
}

July 30th

First Release.

top


                
Disclaimer Acceptable Use Copyright Privacy  

Site Designed with advice from Sojo Media (Thanks!)

Popups by overLIB!