I want to synchronize Windows and Linux clocks. Windows gets its system clock (with GetSystemTimeAsFileTime function) and sends it to Linux. Then, Linux sets its clock accordingly (with settimeofday function).
I also need to transmit the time zone of Windows, and convert it to Linux standard. How can I get the timezone of Windows in C++?
best wishes,
Mustafa
GetTimeZoneInformation is probably what you're looking for.
Even if you're not synching to standard time, but to time between machines, you should use NTP.
NTP is a mature, robust protocol that has solved the whole stack of problems you're going to find, or have found already: discovery, comms transport, latency and jitter, timezone differences, managing drift so you don't confuse other processes sharing the same machine(s), actually setting the time correctly, permissions, etc.
Simply set up an NTP server on the machine you want as a master, and set up the NTP client on the other machine, querying the master. Simple and painless.
It's been a while since I set up NTP servers; I assume that you can use the NTP utilities that come standard with the operating systems to do the job with minimum configuration, as long as you have admin privileges on the boxes.
GetDynamicTimeZoneInformation is more useful function. it gives the Registry Key for timezone also..
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724318(v=vs.85).aspx
GetDynamicTimeZoneInformation doesn't always work. The minimum supported versions are Windows Vista, Windows Server 2008 and Windows Phone 8. So for anything below that GetTimeZoneInformation is better.
However another issue is both sometimes return StandardName or DaylightName empty. In that case you have to use the windows registry. Here is the function taken from gnu cash which was also modified from glib.
static std::string
windows_default_tzname(void)
{
const char *subkey =
"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
constexpr size_t keysize{128};
HKEY key;
char key_name[keysize]{};
unsigned long tz_keysize = keysize;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, subkey, 0,
KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
{
if (RegQueryValueExA(key, "TimeZoneKeyName", nullptr, nullptr,
(LPBYTE)key_name, &tz_keysize) != ERROR_SUCCESS)
{
memset(key_name, 0, tz_keysize);
}
RegCloseKey(key);
}
return std::string(key_name);
}
This is what works for me and ports between windows and linux
#include "time.h"
...
time_t now = time(NULL);
struct tm utctm;
utctm = *gmtime(&now);
utctm.tm_isdst = -1;
time_t utctt = mktime(&utctm);
// diff is the offset in seconds
long diff = now - utctt;
Related
Following is code to put system in sleep state S3, I am looking for a way to perform sleep state S1
bool PerformS3() {
int wait = 100;
LARGE_INTEGER WaitTime;
WaitTime.QuadPart = wait;
WaitTime.QuadPart *= -10000000;
HANDLE hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
if(0 == SetWaitableTimer(hTimer, &WaitTime, 0, NULL, NULL, TRUE))
{
return false;
}
if(0 == SetSuspendState(FALSE, FALSE, FALSE))
{
return false;
}
return true;
}
Short answer: in Windows, there's no S1 or S3, there's only "sleep mode". How it's implemented depends on a number of factors and is hardware- and software-specific. You can only change that, to some degree, by reconfiguring power settings in Control Panel and BIOS setup.
As the article you linked to, System Power States (Windows), hints, Windows Power Management does not expose ACPI power states but rather uses its own states. A somewhat more explicit declaration of that is at Standby Explained (S1, S3) – Omar Shahine – MSDN Blogs.
How these map to ACPI ones depend on motherboard capabilities, driver capabilities and system/BIOS settings.
In particular, Sleep mode used to map to either S1 or S3 (depending on BIOS settings), and newer versions of Windows can also use "Hybrid sleep" or "Away mode".
According to Which sleep mode should I use? S1 or S3? - Tom's Hardware and my personal experience, the S1/S3 switch specifically is either an option in BIOS setup or a jumper on the motherboard.
Judging by your question formulations, you'll probably be fine with "Away mode".
Im trying to use the GetTickCount() in Windows API to get the system uptime. I want to know how long the system has been running.
However the return from GetTickCount is insanely high. This code gives me uptime of over 500 hours.
This goes for GetTickCount64() as well.
Why is this value so high?
DWORD time_ms = GetTickCount();
DWORD seconds = (time_ms / 1000) % 60;
DWORD minutes = time_ms /(1000*60) % 60;
DWORD hours = time_ms / (1000*60*60);
stringstream ss;
ss << "Hours: ";
ss << hours;
ss << " Minutes: ";
ss << minutes;
ss << " seconds: ";
ss << seconds;
MessageBoxA(0, ss.str().c_str(), "Uptime", 0);
As i run the program I can see that it is progressing correctly, but cannot comprehend how I will get the total uptime for my desktop.
Thanks
Edit:
I checked the uptime with "systeminfo" in CMD and found that the "System boot time" was actually aprox ~500hours ago. So I shut down the computer and unplugged the electricity, booted but still,the System boot time had this high value. However, restarting the computer made it reset, and now my code works.
EDIT 2:
This blog https://blogs.msdn.microsoft.com/oldnewthing/20141113-00/?p=43623 states that GetTickCount should rather be used for measuring time intervals than what I'm trying to achieve. Seems like I have to look at the registry.
EDIT 3:
After finding the right counter in the registry, it has the same value has GetTickCount and similar functions. It seems that shut down in Windows brings it to some sort of hibernation. I have not found any solution to this.
The documentation for GetTickCount describes the correct way to get the system up-time:
To obtain the time elapsed since the computer was started, retrieve
the System Up Time counter in the performance data in the registry key
HKEY_PERFORMANCE_DATA. The value returned is an 8-byte value. For more
information, see Performance Counters
I just had the same problem. I solved it by :
using the restart command rather that shutting down the computer : this performs a true restart of the computer and not a "half-hibernation" like the shutdown command when the "fast startup" is enabled
disabling the "fast startup" option. This fast startup option leads to a non reseted GetTickCount at startup !!
I guess that a lot of old programs will bug again with W10 and the fast startup option...
500 hours uptime is not especially surprising. That's around 20 days. Modern systems are seldom shutdown. Typically they are suspended rather than shutdown. I think your system really has been up for 500 hours.
Of course, you should be using GetTickCount64 to work with a 64 bit tick count. That will avoid the 49 day wrap around that is a consequence of the 32 bit values returned by GetTickCount.
Im trying to use the GetTickCount() in Windows API to get the system uptime. I want to know how long the system has been running.
In addition to what others have said, there is another alternative solution.
You can call NtQuerySystemInformation() from ntdll.dll, setting its SystemInformationClass parameter to SystemTimeOfDayInformation to retrieve a SYSTEM_TIMEOFDAY_INFORMATION structure containing BootTime and CurrentTime fields as LARGE_INTEGER values:
typedef struct _SYSTEM_TIMEOFDAY_INFORMATION {
LARGE_INTEGER BootTime;
LARGE_INTEGER CurrentTime;
LARGE_INTEGER TimeZoneBias;
ULONG TimeZoneId;
ULONG Reserved;
ULONGLONG BootTimeBias;
ULONGLONG SleepTimeBias;
} SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION;
You can simply subtract BootTime from CurrentTime to get the elapsed time that Windows has been running (this is exactly how Task Manager calculates the "System Up Time").
How to get Windows boot time?
How does Task Manager compute Up Time, and why doesn’t it agree with GetTickCount?
Can anyone give an example to get date/time from internet, which I only found info using NetRemoteTOD function so far.
But the point is I do not know how to use it, what is the server name. I just tried the below code in my function but it gives run time error.
Appreciate helps
LPTIME_OF_DAY_INFO pBuf = NULL;
NET_API_STATUS nStatus;
LPTSTR pszServerName = NULL;
int CurrentYear ;
int CurrentMonth ;
int CurrentDay ;
int CurrentHour;
int CurrentMin;
pszServerName = (LPTSTR) "time.windows.com";
//
// Call the NetRemoteTOD function.
//
nStatus = NetRemoteTOD((LPCWSTR) pszServerName,(LPBYTE *)&pBuf);
//
// If the function succeeds, display the current date and time.
//
if (nStatus == NERR_Success)
{
if (pBuf != NULL)
{
CurrentYear = pBuf->tod_year;
CurrentMonth =pBuf->tod_month;
CurrentDay = pBuf->tod_day;
CurrentHour=pBuf->tod_hours;
CurrentMin=pBuf->tod_mins;
}
}
//
// Otherwise, display a system error.
else
{
m_SharesEdit[9].SetWindowText("No time");
}
//
// Free the allocated buffer.
//
if (pBuf != NULL)
NetApiBufferFree(pBuf);
if( CTime(CurrentYear,CurrentMonth,CurrentDay,CurrentHour,CurrentMin,0) >= CTime(2013,11,25,9,00,00) )
return true;
else
return false;
NetRemoteTOD only works with Windows servers, not to read the time using something like NTP or SNTP. It actually uses RPC to get the time, and I can't quite imagine most people running a Windows server allowing unverified users to make RPC calls on their server, so for most practical purposes, this is going to be restricted to your own local server.
To get the date/time from the Internet (which seems to be your real intent) you want to write or use an NTP or SNTP client, not NetRemoteTOD. Windows already has an SNTP client in the form of the w32time service. Others were mentioned in answers to a previous question.
Edit in response to comment: Given that you probably don't care about split-second precision, or anything like that, you might want to write code that follows RFC 868 to retrieve time. It's only precise to the second, and makes no attempt at compensating for things like network delays (as NTP can), but when the precision you care about is (roughly) to the day, it's probably more than adequate.
It's also quite simple to implement: open a UDP1 socket on port 37 and read a 4-byte time stamp. That will be given in roughly the traditional Unix format: number of seconds since midnight January 1, 1900. Much simpler than NTP (or SNTP) and probably still entirely adequate to the task at hand.
1. TCP port 37 will work as well, but UDP is usually preferable--you're not doing anything to justify the overhead of TCP.
So quite simply, the question is how to get the system boot up time in windows with c/c++.
Searching for this hasn't got me any answer, I have only found a really hacky approach which is reading a file timestamp ( needless to say, I abandoned reading that halfway ).
Another approach that I found was actually reading windows diagnostics logged events? Supposedly that has last boot up time.
Does anyone know how to do this (with hopefully not too many ugly hacks)?
GetTickCount64 "retrieves the number of milliseconds that have elapsed since the system was started."
Once you know how long the system has been running, it is simply a matter of subtracting this duration from the current time to determine when it was booted. For example, using the C++11 chrono library (supported by Visual C++ 2012):
auto uptime = std::chrono::milliseconds(GetTickCount64());
auto boot_time = std::chrono::system_clock::now() - uptime;
You can also use WMI to get the precise time of boot. WMI is not for the faint of heart, but it will get you what you are looking for.
The information in question is on the Win32_OperatingSystem object under the LastBootUpTime property. You can examine other properties using WMI Tools.
Edit:
You can also get this information from the command line if you prefer.
wmic OS Get LastBootUpTime
As an example in C# it would look like the following (Using C++ it is rather verbose):
static void Main(string[] args)
{
// Create a query for OS objects
SelectQuery query = new SelectQuery("Win32_OperatingSystem", "Status=\"OK\"");
// Initialize an object searcher with this query
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
string dtString;
// Get the resulting collection and loop through it
foreach (ManagementObject envVar in searcher.Get())
dtString = envVar["LastBootUpTime"].ToString();
}
The "System Up Time" performance counter on the "System" object is another source. It's available programmatically using the PDH Helper methods. It is, however, not robust to sleep/hibernate cycles so is probably not much better than GetTickCount()/GetTickCount64().
Reading the counter returns a 64-bit FILETIME value, the number of 100-NS ticks since the Windows Epoch (1601-01-01 00:00:00 UTC). You can also see the value the counter returns by reading the WMI table exposing the raw values used to compute this. (Read programmatically using COM, or grab the command line from wmic:)
wmic path Win32_PerfRawData_PerfOS_System get systemuptime
That query produces 132558992761256000 for me, corresponding to Saturday, January 23, 2021 6:14:36 PM UTC.
You can use the PerfFormattedData equivalent to get a floating point number of seconds, or read that from the command line in wmic or query the counter in PowerShell:
Get-Counter -Counter '\system\system up time'
This returns an uptime of 427.0152 seconds.
I also implemented each of the other 3 answers and have some observations that may help those trying to choose a method.
Using GetTickCount64 and subtracting from current time
The fastest method, clocking in at 0.112 ms.
Does not produce a unique/consistent value at the 100-ns resolution of its arguments, as it is dependent on clock ticks. Returned values are all within 1/64 of a second of each other.
Requires Vista or newer. XP's 32-bit counter rolls over at ~49 days and can't be used for this approach, if your application/library must support older Windows versions
Using WMI query of the LastBootUpTime field of Win32_OperatingSystem
Took 84 ms using COM, 202ms using wmic command line.
Produces a consistent value as a CIM_DATETIME string
WMI class requires Vista or newer.
Reading Event Log
The slowest method, taking 229 ms
Produces a consistent value in units of seconds (Unix time)
Works on Windows 2000 or newer.
As pointed out by Jonathan Gilbert in the comments, is not guaranteed to produce a result.
The methods also produced different timestamps:
UpTime: 1558758098843 = 2019-05-25 04:21:38 UTC (sometimes :37)
WMI: 20190524222528.665400-420 = 2019-05-25 05:25:28 UTC
Event Log: 1558693023 = 2019-05-24 10:17:03 UTC
Conclusion:
The Event Log method is compatible with older Windows versions, produces a consistent timestamp in unix time that's unaffected by sleep/hibernate cycles, but is also the slowest. Given that this is unlikely to be run in a loop it's this may be an acceptable performance impact. However, using this approach still requires handling the situation where the Event log reaches capacity and deletes older messages, potentially using one of the other options as a backup.
C++ Boost used to use WMI LastBootUpTime but switched, in version 1.54, to checking the system event log, and apparently for a good reason:
ABI breaking: Changed bootstamp function in Windows to use EventLog service start time as system bootup time. Previously used LastBootupTime from WMI was unstable with time synchronization and hibernation and unusable in practice. If you really need to obtain pre Boost 1.54 behaviour define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME from command line or detail/workaround.hpp.
Check out boost/interprocess/detail/win32_api.hpp, around line 2201, the implementation of the function inline bool get_last_bootup_time(std::string &stamp) for an example. (I'm looking at version 1.60, if you want to match line numbers.)
Just in case Boost ever dies somehow and my pointing you to Boost doesn't help (yeah right), the function you'll want is mainly ReadEventLogA and the event ID to look for ("Event Log Started" according to Boost comments) is apparently 6005.
I haven't played with this much, but I personally think the best way is probably going to be to query the start time of the "System" process. On Windows, the kernel allocates a process on startup for its own purposes (surprisingly, a quick Google search doesn't easily uncover what its actual purposes are, though I'm sure the information is out there). This process is called simply "System" in the Task Manager, and always has PID 4 on current Windows versions (apparently NT 4 and Windows 2000 may have used PID 8 for it). This process never exits as long as the system is running, and in my testing behaves like a full-fledged process as far as its metadata is concerned. From my testing, it looks like even non-elevated users can open a handle to PID 4, requesting PROCESS_QUERY_LIMITED_INFORMATION, and the resulting handle can be used with GetProcessTimes, which will fill in the lpCreationTime with the UTC timestamp of the time the process started. As far as I can tell, there isn't any meaningful way in which Windows is running before the System process is running, so this timestamp is pretty much exactly when Windows started up.
#include <iostream>
#include <iomanip>
#include <windows.h>
using namespace std;
int main()
{
unique_ptr<remove_pointer<HANDLE>::type, decltype(&::CloseHandle)> hProcess(
::OpenProcess(
PROCESS_QUERY_LIMITED_INFORMATION,
FALSE, // bInheritHandle
4), // dwProcessId
::CloseHandle);
FILETIME creationTimeStamp, exitTimeStamp, kernelTimeUsed, userTimeUsed;
FILETIME creationTimeStampLocal;
SYSTEMTIME creationTimeStampSystem;
if (::GetProcessTimes(hProcess.get(), &creationTimeStamp, &exitTimeStamp, &kernelTimeUsed, &userTimeUsed)
&& ::FileTimeToLocalFileTime(&creationTimeStamp, &creationTimeStampLocal)
&& ::FileTimeToSystemTime(&creationTimeStampLocal, &creationTimeStampSystem))
{
__int64 ticks =
((__int64)creationTimeStampLocal.dwHighDateTime) << 32 |
creationTimeStampLocal.dwLowDateTime;
wios saved(NULL);
saved.copyfmt(wcout);
wcout << setfill(L'0')
<< setw(4)
<< creationTimeStampSystem.wYear << L'-'
<< setw(2)
<< creationTimeStampSystem.wMonth << L'-'
<< creationTimeStampSystem.wDay
<< L' '
<< creationTimeStampSystem.wHour << L':'
<< creationTimeStampSystem.wMinute << L':'
<< creationTimeStampSystem.wSecond << L'.'
<< setw(7)
<< (ticks % 10000000)
<< endl;
wcout.copyfmt(saved);
}
}
Comparison for my current boot:
system_clock::now() - milliseconds(GetTickCount64()):
2020-07-18 17:36:41.3284297
2020-07-18 17:36:41.3209437
2020-07-18 17:36:41.3134106
2020-07-18 17:36:41.3225148
2020-07-18 17:36:41.3145312
(result varies from call to call because system_clock::now() and ::GetTickCount64() don't run at exactly the same time and don't have the same precision)
wmic OS Get LastBootUpTime
2020-07-18 17:36:41.512344
Event Log
No result because the event log entry doesn't exist at this time on my system (earliest event is from July 23)
GetProcessTimes on PID 4:
2020-07-18 17:36:48.0424863
It's a few seconds different from the other methods, but I can't think of any way that it is wrong per se, because, if the System process wasn't running yet, was the system actually booted?
Is there a way to get notified when there is update to the system time from a time-server or due to DST change? I am after an API/system call or equivalent.
It is part of my effort to optimise generating a value for something similar to SQL NOW() to an hour granularity, without using SQL.
You can use timerfd_create(2) to create a timer, then mark it with the TFD_TIMER_CANCEL_ON_SET option when setting it. Set it for an implausible time in the future and then block on it (with poll/select etc.) - if the system time changes then the timer will be cancelled, which you can detect.
(this is how systemd does it)
e.g.:
#include <sys/timerfd.h>
#include <limits.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
int main(void) {
int fd = timerfd_create(CLOCK_REALTIME, 0);
timerfd_settime(fd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
&(struct itimerspec){ .it_value = { .tv_sec = INT_MAX } },
NULL);
printf("Waiting\n");
char buffer[10];
if (-1 == read(fd, &buffer, 10)) {
if (errno == ECANCELED)
printf("Timer cancelled - system clock changed\n");
else
perror("error");
}
close(fd);
return 0;
}
I don't know if there is a way to be notified of a change in the system time, but
The system time is stored as UTC, so there is never a change due to DST change to be notified.
If my memory is correct, NTP deamon usually adjust the clock by changing its speed, again no change to be notified.
So the only times where you would be notified is after an uncommon manipulation.
clock_gettime on most recent Linux systems is incredibly fast, and usually pretty amazingly precise as well; you can find out the precision using clock_getres. But for hour level timestamps, gettimeofday might be more convenient since it can do the timezone adjustment for you.
Simply call the appropriate system call and do the division into hours each time you need a timestamp; all the other time adjustments from NTP or whatever will already have been done for you.