Get std::chrono timestamp as string in %H.%M.%S format - c++

I'm working on a logging system for my console, and I'm trying to get a timestamp for when a entry was added to the log. I tried doing this;
time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
char time_buffer[16] = { 0 };
std::strftime(time_buffer, sizeof(time_buffer), "%H.%M.%S", std::localtime(&now));
TextWrapped(time_buffer);
This almost works. The issue is that this works more as a clock then as a timestamp as it will not stay at the time of when the entry was logged, but increment... I think that I might have to use std::chrono::time_point, but I didn't really understand how to use it.

In C++20 there are a number of nice functions in std::chrono to do this:
#include <iostream>
#include <chrono>
#include <format>
int main()
{
// get the current time
auto now = std::chrono::system_clock::now();
// floor till the start of day
auto start_of_day = std::chrono::floor<std::chrono::days>(now);
// round time till nearest seconds
auto time_since_start_of_day = std::chrono::round<std::chrono::seconds>(now - start_of_day);
// convert to hour minute second type
std::chrono::hh_mm_ss hms { time_since_start_of_day };
std::cout << time_since_start_of_day << "\n"; // will output number of seconds since start of day
std::cout << hms << "\n"; // will output formatted time in hh:mm::ss
auto string = std::format("{}", hms);
std::cout << string << "\n"; // will output formatted time in hh:mm::ss
return 0;
}

So I figured it out.
The issue is that since my code snipped is in my render function, it will always update. My fix was to move the snippet above into my "add_log()" function, then write those timestamps into a new array, then in my for loop I would just grab from both arrays.
Kinda like so;
for (int i = 0; i < items.Size; i++) {
TextWrapped(items[i]);
TextWrapped(timestamps[i]);
}
It's a hacky solution, but it works.

Related

C++ chrono: How do I convert an integer into a time point

I managed to convert a time point into an integer and write it into a file using code that looks like the following code:
std::ofstream outputf("data");
std::chrono::time_point<std::chrono::system_clock> dateTime;
dateTime = std::chrono::system_clock::now();
auto dateTimeSeconds = std::chrono::time_point_cast<std::chrono::seconds>(toSerialize->dateTime);
unsigned long long int serializeDateTime = toSerialize->dateTime.time_since_epoch().count();
outputf << serializeDateTime << "\n";
Now I'm trying to read that integer from the file, convert it into a time_point, and print it. Right now, my code looks something like this:
std::ifstream inputf("data");
unsigned long long int epochDateTime;
inputf >> epochDateTime;
std::chrono::seconds durationDateTime(epochDateTime);
std::chrono::time_point<std::chrono::system_clock> dateTime2(durationDateTime);
std::time_t tt = std::chrono::system_clock::to_time_t(dateTime2);
char timeString[30];
ctime_s(timeString, sizeof(timeString), &tt);
std::cout << timeString;
However, it doesn't print anything. Does anyone know where I went wrong?
You have some strange conversions and assign to a variable that you don't use. If you want to store system_clock::time_points as std::time_ts and restore the time_points from those, don't involve other types and use the functions made for this: to_time_t and from_time_t. Also, check that opening the file and that extraction from the file works.
Example:
#include <chrono>
#include <ctime>
#include <fstream>
#include <iostream>
int main() {
{ // save a time_point as a time_t
std::ofstream outputf("data");
if(outputf) {
std::chrono::time_point<std::chrono::system_clock> dateTime;
dateTime = std::chrono::system_clock::now();
outputf << std::chrono::system_clock::to_time_t(dateTime) << '\n';
}
}
{ // restore the time_point from a time_t
std::ifstream inputf("data");
if(inputf) {
std::time_t epochDateTime;
if(inputf >> epochDateTime) {
// use epochDateTime with ctime-like functions if you want:
std::cout << std::ctime(&epochDateTime) << '\n';
// get the time_point back (usually rounded to whole seconds):
auto dateTime = std::chrono::system_clock::from_time_t(epochDateTime);
// ...
}
}
}
}
Putting aside the possibility of the wrong date value, the problem here is with sizeof(timeString). It appears that you think it is 30, but it in fact is the size of the char*, likely 8 (or maybe 4).
According to ctime_s:
the following errors are detected at runtime and call the currently installed constraint handler function:
buf or timer is a null pointer
bufsz is less than 26 or greater than RSIZE_MAX

C++ timedelta with strftime?

I want to do a function to get the current time with a certain format. C++ is not my main language but im trying to do this:
current_datetime(timezone='-03:00', offset=timedelta(seconds=120))
def current_datetime(fmt='%Y-%m-%dT%H:%M:%S', timezone='Z', offset=None):
offset = offset or timedelta(0)
return (datetime.today() + offset).strftime(fmt) + timezone
My best so far searching internet was this, but is missing the offset part:
#include <iostream>
#include <ctime>
std::string current_datetime(std::string timezone="Z", int offset=1)
{
std::time_t t = std::time(nullptr);
char mbstr[50];
std::strftime(mbstr, sizeof(mbstr), "%Y-%m-%dT%H:%M:%S", std::localtime(&t));
std::string formated_date(mbstr);
formated_date += std::string(timezone);
return formated_date;
}
int main()
{
std::cout << current_datetime() << std::endl; //2021-10-26T21:34:48Z
std::cout << current_datetime("-05:00") << std::endl; //2021-10-26T21:34:48-05:00
return 0;
}
The idea is to get a string that is a "start date" and one as "end date" that is X seconds in the future. Im stuck with the offset/delta part
Just add the offset to the seconds since epoch.
std::time_t t = std::time(nullptr) + offset;
You would also make offset of type std::time_t, as it represents a distance in time in seconds.

Same function outputs different results when calculating difference between two timestamps

I'm currently facing a weird issue where the same function outputs a different result. The function is supposed to calculate the time difference between a provided date and the current time. Since this function is supposed to work with milliseconds, my function currently looks like this:
int calcDelay(std::string dropTime) {
struct tm tm;
std::istringstream iss(dropTime);
iss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S");
time_t time = mktime(&tm);
SYSTEMTIME t;
GetSystemTime(&t);
struct tm tm1;
memset(&tm1, 0, sizeof(tm1));
tm1.tm_year = t.wYear - 1900;
tm1.tm_mon = t.wMonth - 1;
tm1.tm_mday = t.wDay;
tm1.tm_hour = t.wHour - 1;
tm1.tm_min = t.wMinute;
tm1.tm_sec = t.wSecond;
time_t time2 = mktime(&tm1);
//std::cout << "Input:" << dropTime << " Output:" << (int)(difftime(time, time2) * 1000) - t.wMilliseconds << std::endl;
int retVal = (int)(difftime(time, time2) * 1000) - t.wMilliseconds;
return retVal;
}
The provided date (dropTime) is in UTC/GMT and the WinAPI function GetSystemTime should also return the time in UTC.
I have two different threads that call this function. When the first thread calls this function, it returns the correct time difference. However, when my other thread calls this function with the exactly same input it returns a value that is exactly 3600000 ms larger - this equals the time of exactly one hour.
What's the cause of this bug?
Edit: It seems that the bug is caused by the get_time function. Even though the same string (2021-05-25T21:03:04) is used to parse the time, it sometimes adds a hour and sometimes it doesn't...
Could it be that the get_time function simply cannot be used across multiple threads?
I appreciate all help.
In C++20 your calcDelay can be greatly simplified. And there exists a preview of this functionality in a free, open-source, header-only library1 which works with C++11/14/17.
#include "date/date.h"
#include <chrono>
#include <sstream>
int calcDelay(std::string dropTime) {
using std::chrono::milliseconds;
date::sys_time<milliseconds> time;
std::istringstream iss(dropTime);
iss >> date::parse("%Y-%m-%dT%H:%M:%S", time);
auto time2 = date::floor<milliseconds>(std::chrono::system_clock::now());
return (time - time2).count();
}
As you state in your question, the input is UTC, and the current time is UTC. Time zones are not involved. And unlike the "C version", this version optionally supports millisecond-precision input:
std::cout << calcDelay("2021-05-26T00:41:01.568") << '\n';
Output:
12456
To port the above calcDelay to C++20:
Drop #include "date/date.h"
Change date:: to std::chrono:: (3 places)
You can also (optionally) simplify the parse string from "%Y-%m-%dT%H:%M:%S" to "%FT%T".
Also optional, you could increase type safety in the client code by returning std::chrono::milliseconds instead of int.
1 Full disclosure: I am the lead author of this library. I am not pursuing any financial gain from this effort. But sometimes people get upset if I don't fully disclose this information.
t.wHour - 1 is incorrect. Both the tm and SYSTEMTIME structures use hours from 0...23.
According to std::get_time API, The I/O manipulator std::get_time uses the std::time_get facet of the I/O stream's locale to convert text input to a std::tm object. And maybe all of your threads which are in the same process have the same native locale which is default behavior. So GetSystemTime(&t); has no problem.
The follwing code is API’s example:
#include <iostream>
#include <sstream>
#include <locale>
#include <iomanip>
int main()
{
std::tm t = {};
std::istringstream ss("2011-Februar-18 23:12:34");
ss.imbue(std::locale("de_DE.utf-8"));
ss >> std::get_time(&t, "%Y-%b-%d %H:%M:%S");
if (ss.fail()) {
std::cout << "Parse failed\n";
} else {
std::cout << std::put_time(&t, "%c") << '\n';
}
}

Raspberry pi, C++ chrono function, operations on values?

I am beginning in C++ and with the "chrono" function, and I'd like to use it to get the speed of a motor.
For that, I have a coding wheel linked to a motor, an optocoupler is used to gather the square signal generated by the coding wheel.
Therefore, my raspberry pi receive a square signal which speed depends on the motor speed.
I used the chrono function to try to calculate the duration of the frequency of the square signal.
I achieved to have the duration of each signal (almost) which is 7ms.
I'd like to simply extract the frequency through the formula 1/F (therefore, 1/0.007 = 142.85).
I've been eating the documentation of the chrono function for a week, and I still don't get it at all...
Apparently, all the answers are here, but I don't understand that, I'm still a beginner in C++ :( https://en.cppreference.com/w/cpp/chrono
This has been REALLY usefull, but limited : https://www.code57.com/cplusplus-programming-beginners-tutorial-utilities-chrono/
If I understand right, the "value" of 7ms is stored in an "object"...
How can I simply get it out of there and put it in a standard variable so I can divide, multiply and do whatever I want with it?
Here is the interresting part of the C++ code :
#include <iostream>
#include <wiringPi.h>
#include <cstdio>
#include <csignal>
#include <ctime>
#include <chrono>
// global flag used to exit from the main loop
bool RUNNING = true;
bool StartTimer = false;
//int timer = 0;
std::chrono::steady_clock::time_point BeginMeasurement; //chrono variable representing the beginning of the measurement of a motor speed
//some more code in here, but nothing exceptionnal, just calling the interruption when needed
//interruption function for counting the motor speed
void RPMCounter(){
using namespace std;
using namespace std::chrono;
if (StartTimer == true){
StartTimer = false;
steady_clock::duration result = steady_clock::now()-BeginMeasurement;
if (duration_cast<milliseconds>(result).count() < 150){
double freq;
//cout.precision(4);
std::cout << "Time = " << duration_cast<milliseconds>(result).count() << " ms" << '\n';
// I would like the next line to work and give me the frequency of the detection...
freq = 1/(duration_cast<milliseconds>(result).count()/1000);
std::cout << "Frequency = " << freq << " Hz" << '\n';
}
}
else{
BeginMeasurement = steady_clock::now();
StartTimer = true;
}
}
Here is the result in my command prompt :
the value of 7ms increases because I stopped the motor, therefore, it was turning slower until stopping ;)
Edit :
Thanks to Howard Hinnant and Ted Lyngmo, My code now looks like this :
void RPMCounter(){
using namespace std;
using namespace std::chrono;
if (StartTimer == true){
StartTimer = false;
duration<double> result = steady_clock::now() - BeginMeasurement;
if (result < milliseconds{150}){
double freq;//= 1s / result;
//cout.precision(4);
std::cout << "Time = " << duration_cast<milliseconds>(result).count() << " ms" << '\n';
freq = (1.0/(duration<double>{result}.count()/1000))/1000;
std::cout << "Frequency = " << freq << " Hz" << '\n';
}
}
else{
BeginMeasurement = steady_clock::now();
StartTimer = true;
}
}
and it seems to give me a correct frequency.
As i'm a beginner, I'll surely understand all that better in a while and improve it :)
(basically, I'm not exactly sure of what I wrote mean... like the "::" and other ways of :)
The rest of my coding should be more basic and allow me to learn all the tweaks of C++
if (duration_cast<milliseconds>(result).count() < 150){
You can simplify this with:
if (result < 150ms)
Or if you're in C++11:
if (result < milliseconds{150})
The advantage is that you don't have to truncate result to a courser precision, and the code is just easier to read.
freq = 1/(duration_cast<milliseconds>(result).count()/1000);
Instead:
using dsec = duration<double>; // define a double-based second
auto freq = 1/dsec{result}.count();
This could also be written:
auto freq = 1/duration<double>{result}.count();
In any event, this converts result straight to double-based seconds, and inverts that value using floating point arithmetic. The original code uses integral division resulting in an integral result that is always rounding down to 0. I.e. 1/10 == 0, whereas 1/10. == 0.1.
I'd make the result a double based duration:
auto BeginMeasurement = std::chrono::steady_clock::now();
// some work
// a double based duration
std::chrono::duration<double> result = std::chrono::steady_clock::now() - BeginMeasurement;
You can then divide the duration 1s with result to get the frequency:
using namespace std::chrono_literals;
double freq = 1s / result;
std::cout << freq << " Hz\n";
Howard Hinnant pointed out that from C++14 you can make it even easier for youself by changing the dividend from an integer based duration, 1s, to a double based duration, 1.0s, and let result be deduced using auto:
auto result = std::chrono::steady_clock::now() - BeginMeasurement;
double freq = 1.0s / result;
Demo

convert minutes::rep to hours::rep

How should I proceed to convert std::chrono::minutes::rep type value to hours representation.
#include <iostream>
#include <chrono>
using namespace std;
using namespace std::chrono;
int main() {
minutes::rep time = 4;
std::cout << time; // outputs as minutes, need in hours
// duration cast doesn't seems to work here because it
// needs minutes instead of minutes::rep probably
return 0;
}
minutes::rep time = 4;
std::cout << time; // outputs as minutes, need in hours
Because time is just an (implementation-defined) integer type, it has nothing to do with minutes or hours, and doesn't know anything about underlying time representation.
You want to stay in the duration realm:
minutes time{4};
auto as_hours = std::duration_cast<hours>(time);
std::cout << as_hours.count(); // prints 0
Or, likely:
auto as_hours_dbl = std::duration_cast<duration<double, hours::period>>(time);
std::cout << as_hours_dbl.count(); // prints 0.0666667