How to get accurate <1seconds measurements utilizing std::chrono [duplicate] - c++

This question already has answers here:
Measuring execution time of a function in C++
(14 answers)
Getting an accurate execution time in C++ (micro seconds)
(4 answers)
Closed 2 months ago.
I'm trying to compute the amount of time an algorithm runs in my program, and display that amount in differents meausures such as seconds, miliseconds, microseconds...
This is how I've been approaching it:
auto start = high_resolution_clock::now();
myFunction();
auto stop = high_resolution_clock::now();
auto duration = duration_cast<seconds>(stop - start);
const auto hrs = duration_cast<hours>(duration);
const auto mins = duration_cast<minutes>(duration - hrs);
const auto secs = duration_cast<seconds>(duration - hrs - mins);
const auto ms = duration_cast<milliseconds>(duration - hrs - mins - secs);
std::cout << "Time needed: "<<hrs.count()<<" hours "<<mins.count()<<" mins "<<secs.count()<<" secs " <<ms.count()<<" milisecs "
What I intend it to do (invented example):
Time needed: 0 hours 1 mins 30 seconds 2400miliseconds
BUt for some reasons it prints all 0s (even miliseconds) when times are <1secs, and when times are 1secs or more, it does not prints the exact time either, it does something like
Time needed: 0 hours 0 mins 1 seconds 1000miliseconds
it just print a whole seconds and then it converts it to the others meausures, but the actual time that I took the function to works is not exactly 1 second, how can I get that? (if theres better ways to do that other than std::chrono I'll be interested too)

Related

Converting time string to seconds in C++ issues

I'm writing a C++ application on an embedded ARM device running Embedded Linux.
I am trying to convert a date and time string to seconds, subtract it from the current time in seconds, and taking action if the number of seconds elapsed is greater than a certain number.
Something that should be quite simple to implement has proved quite tricky, and i'm not sure why.
The time difference i'm calculating turns out to be a massive number, when it should really be a low number. See my below code. I'm manually hardcoding a time and date string for testing.
std::string timestr = "2020-12-21T16:07:00";
struct tm t = {0};
sscanf(timestr.c_str(), "%04d-%02d-%02dT%02d:%02d:%02d",
&t.tm_year, &t.tm_mon, &t.tm_mday,
&t.tm_hour, &t.tm_min, &t.tm_sec);
t.tm_year -= 1900; // This is required because my year should be the number of years since 1900
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&t));
auto now = std::chrono::system_clock::now();
auto now_s = std::chrono::time_point_cast<std::chrono::seconds>(now);
auto tp_s = std::chrono::time_point_cast<std::chrono::seconds>(tp);
std::chrono::duration<double> diff = now-tp; // Huge number
auto elapsed = now_s - tp_s; // This value is massive and not as expected when printed out
For those who are interested, I solved this problem.
Not only should we subtract 1900 from the number of years before calling std::mktime(&t) .
t.tm_year -= 1900;
but also 1 must be subtracted from the number of months t.tm_mon -= 1 .
The months are numbered from 0 to 11 and not 1 to 12 as we would expect.
This explains why there was a big difference in seconds.

Convert nanoseconds (since midnight) to printable time using std::chrono? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
How would you convert a uint64_t (representing the number of nanoseconds since midnight) in to a human-readable time such as:
HH:MM:SS.nnnnnnnnn
using the standard C++ Chrono library?
Clarification
If you're only given the number of nanoseconds since the most recent midnight, it will be impossible to know what the date is (as Llya Bursov pointed out).
ie. If I tell you its 4:30, you would have no way of knowing today is August 10th.
So I'm going to assume you're trying to convert epoch time (number or seconds since Jan 1 1970 ) into a human readable date.
To get started, check out this page as a guide.
Answer 1
Here is the "official" way to convert epoch time into human readable time in C++
#include <ctime>
#include <iostream>
int main()
{
std::time_t result = std::time(nullptr);
std::cout << std::ctime(&result);
}
This is for getting the current epoch time and converting it into human readable date and time. This does assume seconds, instead of nano seconds. If you need nano seconds, simply divide the number of nano-seconds by 1E9. There are 1E9 nano-seconds in one second. You'll be left with the number of seconds, and then can convert it to human readable code.
If you also use [number of nano-seconds % 1E9 ] the result will be the number of nano-seconds, in case that's important. This number can be added onto the end of the date returned from the above code.
Answer 2
If instead, you don't need the date, and only need to convert nano-seconds to human readable time (HH:MM:SS.nnnnnnnnn) Then see this example:
#include <iostream>
#include <chrono>
#include <ctime>
long fibonacci(unsigned n)
{
if (n < 2) return n;
return fibonacci(n-1) + fibonacci(n-2);
}
int main()
{
auto start = std::chrono::system_clock::now();
std::cout << "f(42) = " << fibonacci(42) << '\n';
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
std::cout << "finished computation at " << std::ctime(&end_time)
<< "elapsed time: " << elapsed_seconds.count() << "s\n";
}
See this link for help with duration.
Let me know if this solved your question, or if I answered the wrong question.

utc seconds since midnight to datetime

I'm getting radar data as "tracks" and the track data indicates the number of UTC seconds since the last midnight, apparently. This is not the number of seconds since the 1st of jan 1970.
Now I want to convert that to date time, knowing that the clock on the computer could be slightly out of sync with the clock on the radar. I'll assume the radar's seconds are the reference, not the computer's.
I want to convert these seconds to a full date time. Things seem to be a little tricky around
midnight.
Any suggestions? I've got some ideas, but I don't want to miss anything.
I'm working with C++ Qt.
// Function to extend truncated time, given the wall time and period, all
// in units of seconds.
//
// Example: Suppose the truncated period was one hour, and you were
// given a truncated time of 25 minutes after the hour. Then:
//
// o Actual time of 07:40:00 results in 07:25:00 (07:40 + -15)
// o Actual time of 07:10:00 results in 07:25:00 (07:10 + +15)
// o Actual time of 07:56:00 results in 08:25:00 (07:56 + +29)
double extendTruncatedTime(double trunc, double wall, int period) {
return wall + remainder(trunc - wall, period);
}
#define extendTruncatedTime24(t) extendTruncatedTime(t, time(0), 24 * 60 * 60)
Some commentary:
The units of wall are seconds, but its base can be arbitrary. In Unix, it typically starts at 1970.
Leap seconds are not relevant here.
You need #include <math.h> for remainder().
The period in extendTruncatedTime() is almost always twenty-four hours, 24 * 60 * 60, as per the OP's request. That is, given the time of day, it extends it by adding the year, month, and day of month, based on the 'wall' time.
The only exception I know to the previous statement is, since you mention radar, is in the Asterix CAT 1 data item I001/141, where the period is 512 seconds, and for which extendTruncatedTime() as given doesn't quite work.
And there is another important case which extendTruncatedTime() doesn't cover. Suppose you are given a truncated time consisting of the day of month, hour, and minute. How can you fill in the year and the month?
The following code snippet adds the year and month to a time derived from a DDHHMM format:
time_t extendTruncatedTimeDDHHMM(time_t trunc, time_t wall) {
struct tm retval = *gmtime_r(&trunc, &retval);
struct tm now = *gmtime_r(&wall, &now);
retval.tm_year = now.tm_year;
retval.tm_mon = now.tm_mon;
retval.tm_mon += now.tm_mday - retval.tm_mday > 15; // 15 = half-month
retval.tm_mon -= now.tm_mday - retval.tm_mday < -15;
return timegm(&retval);
}
As written, this doesn't handle erroneous inputs. For example, if today is July 4th, then the non-nonsensical 310000 will be quietly converted to July 1st. (This may be a feature, not a bug.)
If you can link against another lib, i'd suggest to use boost::date_time.
It seems you want to take current date in seconds from midnight (epoch) then add the radar time to it, then convert the sum back to a date time, and transform it into a string.
Using boost will help you in:
getting the right local time
calculating the date back
incorporating the drift into the calculation
taking leap seconds into account
since you'll have concept like time intervals and durations at your disposal. You can use something like (from the boost examples):
ptime t4(date(2002,May,31), hours(20)); //4 hours b/f midnight NY time
ptime t5 = us_eastern::local_to_utc(t4);
std::cout << to_simple_string(t4) << " in New York is "
<< to_simple_string(t5) << " UTC time "
<< std::endl;
If you want to calculate the drift by hand you can do time math easily similar to constructs like this:
ptime t2 = t1 - hours(5)- minutes(4)- seconds(2)- millisec(1);
I had the exact same problem but I'm using C#. My implementation is included here if anyone needs the solution in C#. This does not incorporate any clock drift.
DateTime UTCTime = DateTime.UtcNow.Date.AddSeconds(secondSinceMidnightFromRadar);

Seconds to Days, Hours and Minutes (customizable day length)

I have a loop and in every loop I get the current seconds the application has been running for I then want to convert this time into how many, Days, Hours and Seconds that the seconds calculate to but not 'real time' I need to be able to customize how many seconds are in a day, I have tried examples on SO and the web but nothing seems to be out there for this. I have some defines
#define DAY 1200
#define HOUR DAY / 24
#define MINUTE HOUR / 60
#define SECOND MINUTE / 60
So in my define a day would last for 1200 seconds. I have then been trying to convert elapsed seconds into 'my' seconds
seconds_passed = fmodf(SECOND, (float)(GetTicks() / 1000));
Which returns what SECOND equals (0.013889) but then every loop is the same, it never changes I was thinking I would just be able to convert for example: 1real second into 1.25fake seconds then
Minute = (seconds_passed / MINUTE);
seconds_passed = fmodf(seconds_passed, MINUTE);
work out how many (fake)minutes, (fake)hours and (fake)days have elapsed since the application started.
Hope that makes sense, thank you for your time.
Since you want to customise how many seconds are in a day, all you're really doing is changing the ratio of 1 second : 1 second.
For instance, if you did was 1200 seconds in a day your ratio is:
1:72
that is, for every 1 second that passes in your day, it is the equivilent of 72 real seconds.
So yes basically all you need to do in your program is find the ratio of 1 second to 1 second, times your elapsed seconds by that to get the 'fake' seconds, and then use that value...
The code may look something like this:
// get the ratio second:fake_second
#define REAL_DAY_SECONDS 86400
int ratio = REAL_DAY_SECONDS / DAY;
fake_to_real = fake_second*ratio;
real_to_fake = real_second/ratio;
You can make your own time durations with one line in chrono:
using fake_seconds = std::chrono::duration<float, std::ratio<72,1>>;
Some sample code
#include <iostream>
#include <chrono>
using namespace std::chrono_literals;
using fake_seconds = std::chrono::duration<float, std::ratio<72,1>>;
int main()
{
auto f_x = fake_seconds(350s);
std::cout << "350 real seconds are:\n" << f_x.count() << " fake_seconds\n";
}
https://godbolt.org/z/f5G86avxr

Qt seconds to DD HH SS

using Qt 4.8 how can I print the time in the format DD HH SS? I have the seconds and I want to get back a string in that format.
QDateTime::fromTime_t(seconds).toString("ss hh DD");
see http://qt-project.org/doc/qt-5.0/qdatetime.html#toString
If you want a duration ( your question was really unclear) try something like :
QString seconds_to_DHMS(quint32 duration)
{
QString res;
int seconds = (int) (duration % 60);
duration /= 60;
int minutes = (int) (duration % 60);
duration /= 60;
int hours = (int) (duration % 24);
int days = (int) (duration / 24);
if((hours == 0)&&(days == 0))
return res.sprintf("%02d:%02d", minutes, seconds);
if (days == 0)
return res.sprintf("%02d:%02d:%02d", hours, minutes, seconds);
return res.sprintf("%dd%02d:%02d:%02d", days, hours, minutes, seconds);
}
Since you have the server uptime as seconds, you can use the QDateTime class.
QDateTime::fromTime_t(duration).toUTC().toString("dd hh ss");
Notice the toUTC, that's to set the beginning hour to 0. Since you will only be taking the date, hour and seconds, it doesn't really matter if the seconds are not since that date since the year won't be displayed.
You can use QDateTime::fromTime_t :
Returns a datetime whose date and time are the number of seconds that have passed since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC).
What you want to print is a duration of time...not a "moment" in clock time. QDateTime doesn't do much with durations except computing secsTo (and daysTo), and you pretty much have to roll your own printing.
Good news is the math isn't that hard:
Convert seconds to Days, Minutes and Seconds
Although your internationalization of words like seconds / days / years might be a nuisance. :(
The math is incredibly hard. Days are not 24 hours, they are usually 24 hours but sometimes 23 or 25 (daylight savings time changes) or 24 hours and a second or two (leap seconds). The same problem goes for months (obviously, since differently-sized months are common) years (leap day) and really anything that inherits day's problem by being defined in terms of days (weeks).