Jump to content
Tuts 4 You

Edit History

Progman

Progman

Just to add to this discussion since I needed for writing scripts that can fix time seeded random number generators for reproducible output, here is a Windows and Posix compatible way of dealing with this.  Note I do not provide a way to take a user friendly specified date/time combination and convert it to a high/low part or a time/microseconds pair but these also can be done programmatically (and is now implemented as shown using a format with command line arguments of year 1601-30827, month 1-12, day 1-31, hour 0-23, minute 0-59, second 0-59, milliseconds 0-999).  The problem is to write the code to be locale sensitive is some work and even the batch/bash scripts will almost certainly not handle all aspects of that.

//root/admin priviledge needed to set time
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#else
//can sudo chown root prestime and sudo chgrp root prestime or just run with sudo
//must disable automatic date & time: timedatectl set-ntp 0
//re-enable with timedatectl set-ntp 1
//#include <errno.h>
#include <sys/time.h>
#include <time.h>
#endif

/*Example usage on Windows and Linux:
>echo %date% %time%
Sat 11/03/2018 17:29:11.97

>prestime 0 0
30700434 1558713536

>echo %date% %time%
Mon 01/01/1601  1:00:01.54

>prestime 0 0 30700434 1558713536

>echo %date% %time%
Sat 11/03/2018 17:29:39.34


$ date
2018. nov. 3., Saturday, 17:30:52 GMT

$ sudo ./prestime 100000 0
[sudo] password for user:
1541262654 925289

$ date
1970. jan. 2., Friday, 04:46:42 GMT

$ sudo ./prestime 100000 0 1541262654 925289

$ date
2018. nov. 3., Saturday, 17:31:18 GMT
*/

int main(int argc, char* argv[])
{
#ifdef WIN32
	//parameters: desired time high part, desired time low part - sets the desired time and returns the old time
	//parameters: desired time high part, desired time low part, old time high part, old time low part - sets the old time plus the difference between the desired time and the current time
	SYSTEMTIME SysTm;
	FILETIME FlTm;
	GetSystemTime(&SysTm);
	SystemTimeToFileTime(&SysTm, &FlTm);
	if (argc == 8) {
		printf("%lu %lu\n", FlTm.dwHighDateTime, FlTm.dwLowDateTime);
		//normalized Gregorian calendar date-time conversion
		//year 1601-30827, month 1-12, day 1-31, hour 0-23, minute 0-59, second 0-59, milliseconds 0-999
		sscanf(argv[1], "%lu", &SysTm.wYear);
		sscanf(argv[2], "%lu", &SysTm.wMonth);
		sscanf(argv[3], "%lu", &SysTm.wDay);
		sscanf(argv[4], "%lu", &SysTm.wHour);
		sscanf(argv[5], "%lu", &SysTm.wMinute);
		sscanf(argv[6], "%lu", &SysTm.wSecond);
		sscanf(argv[7], "%lu", &SysTm.wMilliseconds);	
		SystemTimeToFileTime(&SysTm, &FlTm); //wDayOfWeek 0-6 is ignored...
		printf("%lu %lu\n", FlTm.dwHighDateTime, FlTm.dwLowDateTime);				
	} else if (argc == 5) {
		ULARGE_INTEGER ul, ulsub; //must copy and not cast due to problems with alignment faults in 64-bit windows per MSDN docs
		ul.HighPart = FlTm.dwHighDateTime;
		ul.LowPart = FlTm.dwLowDateTime;
		sscanf(argv[1], "%lu", &ulsub.HighPart);
		sscanf(argv[2], "%lu", &ulsub.LowPart);
		ulsub.QuadPart = ul.QuadPart - ulsub.QuadPart;
		sscanf(argv[3], "%lu", &ul.HighPart);
		sscanf(argv[4], "%lu", &ul.LowPart);
		ul.QuadPart = ul.QuadPart + ulsub.QuadPart;
		FlTm.dwHighDateTime = ul.HighPart;
		FlTm.dwLowDateTime = ul.LowPart;
	} else {
		printf("%lu %lu\n", FlTm.dwHighDateTime, FlTm.dwLowDateTime);
		sscanf(argv[1], "%lu", &FlTm.dwHighDateTime);
		sscanf(argv[2], "%lu", &FlTm.dwLowDateTime);
	}
	FileTimeToSystemTime(&FlTm, &SysTm);
	SetSystemTime(&SysTm);
#else
	//parameters: desired time seconds, desired time microseconds - sets the desired time and returns the old time
	//parameters: desired time seconds, desired time microseconds, old time seconds, old time microseconds - sets the old time plus the difference between the desired time and the current time
	struct timeval now;
	gettimeofday(&now, NULL);
	if (argc == 8) {
		printf("%lu %lu\n", now.tv_sec, now.tv_usec);
		struct tm Tm = {0}; //tm_isdst = 0
		sscanf(argv[1], "%d", &Tm.tm_year);
		sscanf(argv[2], "%d", &Tm.tm_mon);
		sscanf(argv[3], "%d", &Tm.tm_mday);
		sscanf(argv[4], "%d", &Tm.tm_hour);
		sscanf(argv[5], "%d", &Tm.tm_min);
		sscanf(argv[6], "%d", &Tm.tm_sec);
		now.tv_sec = mktime(&Tm); //tm_wday, tm_yday are ignored...
		sscanf(argv[7], "%lu", &now.tv_usec);	
		now.tv_usec *= 1000; //milliseconds to microseconds
	} else if (argc == 5) {
		struct timeval desired;
		sscanf(argv[1], "%lu", &desired.tv_sec);
		sscanf(argv[2], "%lu", &desired.tv_usec);
		timersub(&now, &desired, &desired);
		sscanf(argv[3], "%lu", &now.tv_sec);
		sscanf(argv[4], "%lu", &now.tv_usec);
		timeradd(&now, &desired, &now);
	} else {
		printf("%lu %lu\n", now.tv_sec, now.tv_usec);
		sscanf(argv[1], "%lu", &now.tv_sec);
		sscanf(argv[2], "%lu", &now.tv_usec);
	}
	return settimeofday(&now, NULL);
#endif
}

 

Example usage on Windows and then Linux:

>echo %date% %time%
Sat 11/03/2018 17:29:11.97

>prestime 0 0
30700434 1558713536

>echo %date% %time%
Mon 01/01/1601  1:00:01.54

>prestime 0 0 30700434 1558713536

>echo %date% %time%
Sat 11/03/2018 17:29:39.34


$ date
2018. nov. 3., Saturday, 17:30:52 GMT

$ sudo ./prestime 100000 0
[sudo] password for user:
1541262654 925289

$ date
1970. jan. 2., Friday, 04:46:42 GMT

$ sudo ./prestime 100000 0 1541262654 925289

$ date
2018. nov. 3., Saturday, 17:31:18 GMT

 

Progman

Progman

Just to add to this discussion since I needed for writing scripts that can fix time seeded random number generators for reproducible output, here is a Windows and Posix compatible way of dealing with this.  Note I do not provide a way to take a user friendly specified date/time combination and convert it to a high/low part or a time/microseconds pair but these also can be done programmatically (and is now implemented as shown using a format with command line arguments of year 1601-30827, month 1-12, day 1-31, hour 0-23, minute 0-59, second 0-59, milliseconds 0-999).  The problem is to write the code to be locale sensitive is some work and even the batch/bash scripts will almost certainly not handle all aspects of that.

//root/admin priviledge needed to set time
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#else
//can sudo chown root prestime and sudo chgrp root prestime or just run with sudo
//must disable automatic date & time: timedatectl set-ntp 0
//re-enable with timedatectl set-ntp 1
//#include <errno.h>
#include <sys/time.h>
#include <time.h>
#endif

/*Example usage on Windows and Linux:
>echo %date% %time%
Sat 11/03/2018 17:29:11.97

>prestime 0 0
30700434 1558713536

>echo %date% %time%
Mon 01/01/1601  1:00:01.54

>prestime 0 0 30700434 1558713536

>echo %date% %time%
Sat 11/03/2018 17:29:39.34


$ date
2018. nov. 3., szombat, 17:30:52 GMT

$ sudo ./prestime 100000 0
[sudo] password for user:
1541262654 925289

$ date
1970. jan. 2., Friday, 04:46:42 GMT

$ sudo ./prestime 100000 0 1541262654 925289

$ date
2018. nov. 3., Saturday, 17:31:18 GMT
*/

int main(int argc, char* argv[])
{
#ifdef WIN32
	//parameters: desired time high part, desired time low part - sets the desired time and returns the old time
	//parameters: desired time high part, desired time low part, old time high part, old time low part - sets the old time plus the difference between the desired time and the current time
	SYSTEMTIME SysTm;
	FILETIME FlTm;
	GetSystemTime(&SysTm);
	SystemTimeToFileTime(&SysTm, &FlTm);
	if (argc == 8) {
		printf("%lu %lu\n", FlTm.dwHighDateTime, FlTm.dwLowDateTime);
		//normalized Gregorian calendar date-time conversion
		//year 1601-30827, month 1-12, day 1-31, hour 0-23, minute 0-59, second 0-59, milliseconds 0-999
		sscanf(argv[1], "%lu", &SysTm.wYear);
		sscanf(argv[2], "%lu", &SysTm.wMonth);
		sscanf(argv[3], "%lu", &SysTm.wDay);
		sscanf(argv[4], "%lu", &SysTm.wHour);
		sscanf(argv[5], "%lu", &SysTm.wMinute);
		sscanf(argv[6], "%lu", &SysTm.wSecond);
		sscanf(argv[7], "%lu", &SysTm.wMilliseconds);	
		SystemTimeToFileTime(&SysTm, &FlTm); //wDayOfWeek 0-6 is ignored...
		printf("%lu %lu\n", FlTm.dwHighDateTime, FlTm.dwLowDateTime);				
	} else if (argc == 5) {
		ULARGE_INTEGER ul, ulsub; //must copy and not cast due to problems with alignment faults in 64-bit windows per MSDN docs
		ul.HighPart = FlTm.dwHighDateTime;
		ul.LowPart = FlTm.dwLowDateTime;
		sscanf(argv[1], "%lu", &ulsub.HighPart);
		sscanf(argv[2], "%lu", &ulsub.LowPart);
		ulsub.QuadPart = ul.QuadPart - ulsub.QuadPart;
		sscanf(argv[3], "%lu", &ul.HighPart);
		sscanf(argv[4], "%lu", &ul.LowPart);
		ul.QuadPart = ul.QuadPart + ulsub.QuadPart;
		FlTm.dwHighDateTime = ul.HighPart;
		FlTm.dwLowDateTime = ul.LowPart;
	} else {
		printf("%lu %lu\n", FlTm.dwHighDateTime, FlTm.dwLowDateTime);
		sscanf(argv[1], "%lu", &FlTm.dwHighDateTime);
		sscanf(argv[2], "%lu", &FlTm.dwLowDateTime);
	}
	FileTimeToSystemTime(&FlTm, &SysTm);
	SetSystemTime(&SysTm);
#else
	//parameters: desired time seconds, desired time microseconds - sets the desired time and returns the old time
	//parameters: desired time seconds, desired time microseconds, old time seconds, old time microseconds - sets the old time plus the difference between the desired time and the current time
	struct timeval now;
	gettimeofday(&now, NULL);
	if (argc == 8) {
		printf("%lu %lu\n", now.tv_sec, now.tv_usec);
		struct tm Tm = {0}; //tm_isdst = 0
		sscanf(argv[1], "%d", &Tm.tm_year);
		sscanf(argv[2], "%d", &Tm.tm_mon);
		sscanf(argv[3], "%d", &Tm.tm_mday);
		sscanf(argv[4], "%d", &Tm.tm_hour);
		sscanf(argv[5], "%d", &Tm.tm_min);
		sscanf(argv[6], "%d", &Tm.tm_sec);
		now.tv_sec = mktime(&Tm); //tm_wday, tm_yday are ignored...
		sscanf(argv[7], "%lu", &now.tv_usec);	
		now.tv_usec *= 1000; //milliseconds to microseconds
	} else if (argc == 5) {
		struct timeval desired;
		sscanf(argv[1], "%lu", &desired.tv_sec);
		sscanf(argv[2], "%lu", &desired.tv_usec);
		timersub(&now, &desired, &desired);
		sscanf(argv[3], "%lu", &now.tv_sec);
		sscanf(argv[4], "%lu", &now.tv_usec);
		timeradd(&now, &desired, &now);
	} else {
		printf("%lu %lu\n", now.tv_sec, now.tv_usec);
		sscanf(argv[1], "%lu", &now.tv_sec);
		sscanf(argv[2], "%lu", &now.tv_usec);
	}
	return settimeofday(&now, NULL);
#endif
}

 

Example usage on Windows and then Linux:

>echo %date% %time%
Sat 11/03/2018 17:29:11.97

>prestime 0 0
30700434 1558713536

>echo %date% %time%
Mon 01/01/1601  1:00:01.54

>prestime 0 0 30700434 1558713536

>echo %date% %time%
Sat 11/03/2018 17:29:39.34


$ date
2018. nov. 3., Saturday, 17:30:52 GMT

$ sudo ./prestime 100000 0
[sudo] password for user:
1541262654 925289

$ date
1970. jan. 2., Friday, 04:46:42 GMT

$ sudo ./prestime 100000 0 1541262654 925289

$ date
2018. nov. 3., Saturday, 17:31:18 GMT

 

Progman

Progman

Just to add to this discussion since I needed for writing scripts that can fix time seeded random number generators for reproducible output, here is a Windows and Posix compatible way of dealing with this.  Note I do not provide a way to take a user friendly specified date/time combination and convert it to a high/low part or a time/microseconds pair but these also can be done programmatically.  The problem is to write the code to be locale sensitive is some work and even the batch/bash scripts will almost certainly not handle all aspects of that.

//root/admin priviledge needed to set time
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#else
//can sudo chown root prestime and sudo chgrp root prestime or just run with sudo
//must disable automatic date & time:
//timedatectl set-ntp 0
#include <errno.h>
#include <sys/time.h>
#endif

int main(int argc, char* argv[])
{
#ifdef WIN32
	//parameters: desired time high part, desired time low part - sets the desired time and returns the old time
	//parameters: desired time high part, desired time low part, old time high part, old time low part - sets the old time plus the difference between the desired time and the current time
	SYSTEMTIME SysTm;
	FILETIME FlTm;
	GetSystemTime(&SysTm);
	SystemTimeToFileTime(&SysTm, &FlTm);
	if (argc == 5) {
		ULARGE_INTEGER ul, ulsub; //must copy and not cast due to problems with alignment faults in 64-bit windows per MSDN docs
		ul.HighPart = FlTm.dwHighDateTime;
		ul.LowPart = FlTm.dwLowDateTime;
		sscanf(argv[1], "%lu", &ulsub.HighPart);
		sscanf(argv[2], "%lu", &ulsub.LowPart);
		ulsub.QuadPart = ul.QuadPart - ulsub.QuadPart;
		sscanf(argv[3], "%lu", &ul.HighPart);
		sscanf(argv[4], "%lu", &ul.LowPart);
		ul.QuadPart = ul.QuadPart + ulsub.QuadPart;
		FlTm.dwHighDateTime = ul.HighPart;
		FlTm.dwLowDateTime = ul.LowPart;
	} else {
		printf("%lu %lu\n", FlTm.dwHighDateTime, FlTm.dwLowDateTime);
		sscanf(argv[1], "%lu", &FlTm.dwHighDateTime);
		sscanf(argv[2], "%lu", &FlTm.dwLowDateTime);
	}
	FileTimeToSystemTime(&FlTm, &SysTm);
	SetSystemTime(&SysTm);
#else
	//parameters: desired time seconds, desired time microseconds - sets the desired time and returns the old time
	//parameters: desired time seconds, desired time microseconds, old time seconds, old time microseconds - sets the old time plus the difference between the desired time and the current time
	struct timeval now;
	gettimeofday(&now, NULL);
	if (argc == 5) {
		struct timeval desired;
		sscanf(argv[1], "%lu", &desired.tv_sec);
		sscanf(argv[2], "%lu", &desired.tv_usec);
		timersub(&now, &desired, &desired);
		sscanf(argv[3], "%lu", &now.tv_sec);
		sscanf(argv[4], "%lu", &now.tv_usec);
		timeradd(&now, &desired, &now);
	} else {
		printf("%lu %lu\n", now.tv_sec, now.tv_usec);
		sscanf(argv[1], "%lu", &now.tv_sec);
		sscanf(argv[2], "%lu", &now.tv_usec);
	}
	return settimeofday(&now, NULL);
#endif
}

 

Example usage on Windows and then Linux:

>echo %date% %time%
Sat 11/03/2018 17:29:11.97

>prestime 0 0
30700434 1558713536

>echo %date% %time%
Mon 01/01/1601  1:00:01.54

>prestime 0 0 30700434 1558713536

>echo %date% %time%
Sat 11/03/2018 17:29:39.34


$ date
2018. nov. 3., Saturday, 17:30:52 GMT

$ sudo ./prestime 100000 0
[sudo] password for user:
1541262654 925289

$ date
1970. jan. 2., Friday, 04:46:42 GMT

$ sudo ./prestime 100000 0 1541262654 925289

$ date
2018. nov. 3., Saturday, 17:31:18 GMT

 

Progman

Progman

Just to add to this discussion since I needed for writing scripts that can fix time seeded random number generators for reproducible output, here is a Windows and Posix compatible way of dealing with this.  Note I do not provide a way to take a user friendly specified date/time combination and convert it to a high/low part or a time/microseconds pair but these also can be done programmatically.  The problem is to write the code to be locale sensitive is some work and even the batch/bash scripts will almost certainly not handle all aspects of that.

//root/admin priviledge needed to set time
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#else
//can sudo chown root prestime and sudo chgrp root prestime or just run with sudo
//must disable automatic date & time:
//timedatectl set-ntp 0
#include <errno.h>
#include <sys/time.h>
#endif

int main(int argc, char* argv[])
{
#ifdef WIN32
	//parameters: desired time high part, desired time low part - sets the desired time and returns the old time
	//parameters: desired time high part, desired time low part, old time high part, old time low part - sets the old time plus the difference between the desired time and the current time
	SYSTEMTIME SysTm;
	FILETIME FlTm;
	GetSystemTime(&SysTm);
	SystemTimeToFileTime(&SysTm, &FlTm);
	if (argc == 5) {
		ULARGE_INTEGER ul, ulsub; //must copy and not cast due to problems with alignment faults in 64-bit windows per MSDN docs
		ul.HighPart = FlTm.dwHighDateTime;
		ul.LowPart = FlTm.dwLowDateTime;
		sscanf(argv[1], "%lu", &ulsub.HighPart);
		sscanf(argv[2], "%lu", &ulsub.LowPart);
		ulsub.QuadPart = ul.QuadPart - ulsub.QuadPart;
		sscanf(argv[3], "%lu", &ul.HighPart);
		sscanf(argv[4], "%lu", &ul.LowPart);
		ul.QuadPart = ul.QuadPart + ulsub.QuadPart;
		FlTm.dwHighDateTime = ul.HighPart;
		FlTm.dwLowDateTime = ul.LowPart;
	} else {
		printf("%lu %lu\n", FlTm.dwHighDateTime, FlTm.dwLowDateTime);
		sscanf(argv[1], "%lu", &FlTm.dwHighDateTime);
		sscanf(argv[2], "%lu", &FlTm.dwLowDateTime);
	}
	FileTimeToSystemTime(&FlTm, &SysTm);
	SetSystemTime(&SysTm);
#else
	//parameters: desired time seconds, desired time microseconds - sets the desired time and returns the old time
	//parameters: desired time seconds, desired time microseconds, old time seconds, old time microseconds - sets the old time plus the difference between the desired time and the current time
	struct timeval now;
	gettimeofday(&now, NULL);
	if (argc == 5) {
		struct timeval desired;
		sscanf(argv[1], "%lu", &desired.tv_sec);
		sscanf(argv[2], "%lu", &desired.tv_usec);
		timersub(&now, &desired, &desired);
		sscanf(argv[3], "%lu", &now.tv_sec);
		sscanf(argv[4], "%lu", &now.tv_usec);
		timeradd(&now, &desired, &now);
	} else {
		printf("%lu %lu\n", now.tv_sec, now.tv_usec);
		sscanf(argv[1], "%lu", &now.tv_sec);
		sscanf(argv[2], "%lu", &now.tv_usec);
	}
	return settimeofday(&now, NULL);
#endif
}

 

Example usage on Windows and then Linux:

>echo %date% %time%
Sat 11/03/2018 17:29:11.97

>prestime 0 0
30700434 1558713536

>echo %date% %time%
Mon 01/01/1601  1:00:01.54

>prestime 0 0 30700434 1558713536

>echo %date% %time%
Sat 11/03/2018 17:29:39.34


$ date
2018. nov. 3., szombat, 17:30:52 GMT

$ sudo ./prestime 100000 0
[sudo] password for user:
1541262654 925289

$ date
1970. jan. 2., Friday, 04:46:42 GMT

$ sudo ./prestime 100000 0 1541262654 925289

$ date
2018. nov. 3., Saturday, 17:31:18 GMT

 

×
×
  • Create New...