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.
Related
I wrote the following code using Howard Hinnants date.h library, to compute the fractional day of the year of the current time. I was wondering if there are shorter ways of doing it, because my code feels like an overkill of std::chrono and date calls. Can I directly calculate the number of fractional days since the start of the year (at microsecond precision) and avoid my two-step approach?
#include <iostream>
#include <chrono>
#include "date.h"
int main()
{
// Get actual time.
auto now = std::chrono::system_clock::now();
// Get the number of days since start of the year.
auto ymd = date::year_month_day( date::floor<date::days>(now) );
auto ymd_ref = date::year{ymd.year()}/1/1;
int days = (date::sys_days{ymd} - date::sys_days{ymd_ref}).count();
// Get the fractional number of seconds of the day.
auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(now - date::floor<date::days>(now));
double seconds_since_midnight = 1e-6*microseconds.count();
// Get fractional day number.
std::cout << "Fractional day of the year: " << days + seconds_since_midnight / 86400. << std::endl;
return 0;
}
Good question (upvoted).
I think first we need to decide on what the right answer is. There's your answer, and currently the only other answer is Matteo's. For demonstration purposes, I've modified both answers to substitute in a "fake now" so that we can compare apples to apples:
using namespace std::chrono_literals;
auto now = date::sys_days{date::March/27/2019} + 0h + 32min + 22s + 123456us;
(approximately now at the time I'm writing this)
Chiel's code gives:
Fractional day of the year: 85.0225
Matteo's code gives:
Fractional day of the year: 85.139978280740735
They are close, but not close enough to both be considered right.
Matteo's code works with "average years":
auto this_year = date::floor<date::years>(now);
The length of a date::years is 365.2425 days, which is exactly right if you average all civil years over a 400 year period. And working with the average year length can be very useful, especially when dealing with systems that don't care about human made calendars (e.g. physics or biology).
I'm going to guess that because of the way Chiel's code is written, he would prefer a result that refers more precisely to this specific year. Therefore the code presented below is Chiel's's algorithm, resulting in exactly the same result, only slightly more efficient and concise.
// Get actual time.
auto now = std::chrono::system_clock::now();
// Get the number of days since start of the year.
auto sd = date::floor<date::days>(now);
auto ymd = date::year_month_day( sd );
auto ymd_ref = ymd.year()/1/1;
std::chrono::duration<double, date::days::period> days = sd - date::sys_days{ymd_ref};
// Get the fractional number of seconds of the day.
days += now - sd;
// Get fractional day number.
std::cout << "Fractional day of the year: " << days.count() << std::endl;
The first thing I noted was that date::floor<date::days>(now) was being computed in 3 places, so I'm computing it once and saving it in sd.
Next, since the final answer is a double-based representation of days, I'm going to let <chrono> do that work for me by storing the answer in a duration<double, days>. Any time you find yourself converting units, it is better to let <chrono> do it for you. It probably won't be faster. But it definitely won't be slower, or wrong.
Now it is a simple matter to add the fractional day to the result:
days += now - sd;
using whatever precision now has (microseconds or whatever). And the result is now simply days.count().
Update
And with just a little bit more time to reflect ...
I noticed that with the simplified code above, one can more easily see the entire algorithm as a single expression. That is (removing namespace qualification in order to get everything on one line):
duration<double, days::period> days = sd - sys_days{ymd_ref} + now - sd;
And this clearly algebraically simplifies down to:
duration<double, days::period> days = now - sys_days{ymd_ref};
In summary:
using namespace std::chrono;
using namespace date;
// Get actual time.
auto now = system_clock::now();
// Get the start of the year and subract it from now.
using ddays = duration<double, days::period>;
ddays fd = now - sys_days{year_month_day{floor<days>(now)}.year()/1/1};
// Get fractional day number.
std::cout << "Fractional day of the year: " << fd.count() << '\n';
In this case, letting <chrono> do the conversions for us, allowed the code to be sufficiently simplified such that the algorithm itself could be algebraically simplified, resulting in cleaner and more efficient code that is provably equivalent to the original algorithm in the OP's question.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 6 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
I am testing for runtimes with visual studio 2015's Perftips and I noticed that when I use the STL "list" and access the push_front() function, it is running a 1000x's longer than it should and is also in O(n) time when it should be O(1).
For example:
I am creating a doubly linked list with a million random integers and it takes about 2000ms to add a single int value to the front of that million long list when I know it should be around 3ms. I also noticed that the run times expand linearly with the size of the list I make, which is not what big-O predicts.
Here is the line of code I am testing:
list.push_front(10); // 10 is an arbitrary number
I am also getting the same problem for singly linked lists and for O(1) vector functions. Does anyone know what is going on? Thanks for your time.
Side note:
I'm not sure if my hardware has anything to do with it but, I have a 2.4Ghz laptop i7 and half empty 700 gb hard drive with 8Gb of ram
Edit:
I am also running microsoft Excel, Adobe Reader, and chrome simultaneously while testing. I closed the programs and it actually bumped up my run times by about 100ms oddly enough.
The time O(1) means constant relative to size. So to claim a slow down, you need to describe measurements at different sizes.
Whilst the std::list does adhere to this, neither the memory runtime (new, delete) nor the OS (HeapAlloc) do.
Try running release build (stl+ new faster)
Looks pretty O(1) to me:
#include <list>
#include <chrono>
#include <string>
#include <cmath>
#include <iostream>
#include <iomanip>
void run_test(size_t items)
{
std::list<int> mylist;
std::cout << "testing " << std::setw(9) << std::right << items << " insertions: ";
std::cout.flush();
auto t0 = std::chrono::high_resolution_clock::now();
while(items) {
mylist.push_front(10);
--items;
}
auto t1 = std::chrono::high_resolution_clock::now();
auto diff = t1 - t0;
auto us = std::chrono::duration_cast<std::chrono::microseconds>(diff);
std::cout << "took " << std::setw(9) << us.count() << "us to get to size " << std::setw(9) << mylist.size() << std::endl;
}
int main()
{
for(int power = 1 ; power < 9 ; ++power)
{
run_test(std::pow(10, power));
}
return 0;
}
example results (clang, -O2, macbook pro on batteries)
testing 10 insertions: took 1us to get to size 10
testing 100 insertions: took 5us to get to size 100
testing 1000 insertions: took 60us to get to size 1000
testing 10000 insertions: took 582us to get to size 10000
testing 100000 insertions: took 5832us to get to size 100000
testing 1000000 insertions: took 66873us to get to size 1000000
testing 10000000 insertions: took 622131us to get to size 10000000
testing 100000000 insertions: took 6636721us to get to size 100000000
Solved by #CraigEstey.
There's just something wrong with my system when using PerfTips. I ran the code using the chrono stl and got way different data that matched what big-O predicted.
Thanks for the feedback guys and gals.
Is it possible to manually set the epoch date/time to the January 1, 0000, so I might use the std::chrono::time_point::time_since_epoch to calculate the difference between a given date and January 1, 0000?
I tried the following:
#include <iostream>
#include <chrono>
#include <ctime>
int main(int argc, char*argv[])
{
std::tm epochStart = {};
epochStart.tm_sec = 0;
epochStart.tm_min = 0;
epochStart.tm_hour = 0;
epochStart.tm_mday = 0;
epochStart.tm_mon = 0;
epochStart.tm_year = -1900;
epochStart.tm_wday = 0;
epochStart.tm_yday = 0;
epochStart.tm_isdst = -1;
std::time_t base = std::mktime(&epochStart);
std::chrono::system_clock::time_point baseTp=
std::chrono::system_clock::from_time_t(base);
std::time_t btp = std::chrono::system_clock::to_time_t(baseTp);
std::cout << "time: " << std::ctime(&btp);
}
but this gives me
time: Thu Jan 1 00:59:59 1970
I would avoid std::time_t altogether. Using days_from_civil from chrono-Compatible Low-Level Date Algorithms, you can immediately compute any difference between std::chrono::system_clock::time_point, and any date in the proleptic Gregorian calendar1.
In addition to days_from_civil which takes a year/month/day triple and converts it into a count of days before/since 1970-01-01 (a chrono-compatible epoch), it is also convenient to create a custom chrono::duration to represent 24 hours:
typedef std::chrono::duration
<
int,
std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>
> days;
Now you can create any epoch you want with just:
constexpr days epoch = days(days_from_civil(0, 1, 1)); // 0000-01-01
In C++1y this is even a compile-time computation!
And you can subtract this std::chrono::duration from any other std::chrono::duration:
auto delta = std::chrono::system_clock::now().time_since_epoch() - epoch;
delta is now a std::chrono::duration representing the amount of time between now, and 0000-01-01. You can then print that out however you want, or otherwise manipulate it. For example here is an entire working demo:
#include "../date_performance/date_algorithms"
#include <iostream>
#include <chrono>
typedef std::chrono::duration
<
int,
std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>
> days;
int
main()
{
constexpr days epoch = days(days_from_civil(0, 1, 1));
auto delta = std::chrono::system_clock::now().time_since_epoch() - epoch;
days d = std::chrono::duration_cast<days>(delta);
std::cout << "It has been " << d.count() << " days, ";
delta -= d;
auto h = std::chrono::duration_cast<std::chrono::hours>(delta);
std::cout << h.count() << " hours, ";
delta -= h;
auto m = std::chrono::duration_cast<std::chrono::minutes>(delta);
std::cout << m.count() << " minutes, ";
delta -= m;
auto s = std::chrono::duration_cast<std::chrono::seconds>(delta);
std::cout << s.count() << " seconds ";
std::cout << " since 0000-01-01\n";
}
Which for me output:
It has been 735602 days, 19 hours, 14 minutes, 32 seconds since 0000-01-01
A word of warning about overflow:
The std::chrono::system_clock::time_point::duration is not guaranteed to have a range large enough to do this. It turns out that on my system it does. It is microseconds in a signed long long which will span +/- 292,000 years. If you need to avoid an overflow problem, you could truncate your std::chrono::system_clock::time_point::duration to courser units (e.g. seconds or days) to extend the range prior to subtracting 0000-01-01.
I got to thinking
And that usually leads to a disaster. However in this case I decided I should add to this post anyway. This:
constexpr days epoch = days(days_from_civil(0, 1, 1));
has type days, which is a duration. But it really isn't a duration. It is a point in time. It is a date. It is a time_point with a coarse precision. By introducing a new typedef, the code in this post can be cleaned up just a little bit more:
typedef std::chrono::time_point<std::chrono::system_clock, days> date_point;
Now instead of writing:
constexpr days epoch = days(days_from_civil(0, 1, 1));
One can write:
constexpr date_point epoch{days(days_from_civil(0, 1, 1))};
But even more importantly, instead of:
auto delta = std::chrono::system_clock::now().time_since_epoch() - epoch;
we can now write:
auto delta = std::chrono::system_clock::now() - epoch;
This delta still has exactly the same type and value as it did previously, and everything else in the demo still proceeds as exactly as it did before.
This is both a small change, and a big change. By treating epoch as a time_point instead of a duration, the algebra of time_point's and duration's works for us, both simplifying and type-checking our expressions to help us write cleaner code with fewer mistakes.
For example one can add two duration's together. But it doesn't make any sense at all to:
epoch + epoch
By using time_point instead of duration for the type of epoch, the compiler catches such non-sensical expressions at compile time.
1The proleptic Gregorian calendar has a year 0. In the year 0 it is 2 days behind the Julian calendar. Using a year 0 is also consistent with ISO 8601. As long as all parties involved know what calendar you are using, then everything is fine. Conversion between non-positive years and "BC years" is trivial if desired.
It's possible, the code you've given (minus a small fix, tm_mday starts with 1) yields:
Sat Jan 1 00:00:00 0
Live example
The real problem is: Are you on 32-bit or 64-bit? With a 32-bit system, time_t is also only 32 bits and you are limited to 1970 +/- 68 years.
On a 64-bit system, the limits are given by std::mktime and std::strftime, in my own code I have unit test for those strings and the corresponding values:
"-2147481748-01-01 00:00:00" maps to -67768040609740800
"2147483647-12-31 23:59:59" maps to 67767976233532799
I should probably also mention that there are systems where the above does not work because the underlying OS functions are buggy. For the record: I'm on Linux.
No. mktime and friends are based on UNIX time, which starts on 1st January 1970.
There is in fact no such thing as 0th January, 0000, so it seems likely that you would be better off finding another way to solve whatever is your actual problem.
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
I'm coding a program to calculate the growth of a bacterial colony until certain point.
Given a "X", that will represent the initial number of bacteria. And given a "Y", that will represent the number limit desired of bacteria in the bacterial colony. Return the number of days and hours that the bacterial colony needs for reaching the limit.
The bacterial colony doubles each hour.
Example.1:
Input: 1, 8
Output: 0, 3
Example.2:
Input: 1000 , 1024000
Output:0, 10
Example.3:
Input: 123, 3453546624536
Output: 1, 10
If the hour calculated returns a fractional number, it must be rounded down.
So far I have written this code:
#include <iostream>
using namespace std;
int main(){
long int binitial, blimit, day, counter=0;
float hour;
cin >> binitial;
cin >> blimit;
while(binitial <= blimit){
binitial = binitial * 2;
counter++;
}
day = counter / 24;
cout << day << " ";
hour = (counter % 24) - 0.5;
cout << (int)hour;
return 0;
}
You can remove the loop by observing that the number of hours is Log2(Y/X). To calculate Log2(A) using the standard functions, calculate log(A)/log(2).
You may need to address precision issues when going from doubles to ints, because the calculations will be approximate. The final expression for the hours may look like this:
int hours = (log(Y/X) / log(2)) + 1E-8; // Add a small delta
Going from hours to days/hours is very simple, too:
cout << hours/24 << " " << hours % 24 << endl;
You can use a long int for hour if you do the following:
hour = counter - (day*24); // The total number of hours minus the number of hours that are in each day.
I don't have a compiler in front of me but you can probably also do something like this:
hour = counter % 24; // this will return the remainder when counter is divided by 24.
If blimit is always a multiple of binitial, the solution is simple:
counter%24 will be always an integer, so you don't have to round it.
In case of day days and hour hours, you only have to do is:
hour = counter%24
A note on the method of calculation: you don't need to iterate if you're only doubling each time. You're just looking for a value of n such that 2n gives the right result.
So, note that ngenerations = log2 blimit - log2 binitial
Once you have the number of generations (as a floating-point number) you can just truncate that to an integer number of hours.
Depending on the amount of input data, I have a program that runs in seconds or in days. At the end of my program, I want to print the elapsed "clock wall" time: in seconds if it is less then one minute, in min and sec if it is less than one hour, in hour-min-sec if it is less than one day, and in day-hour-min-sec otherwise. Here is the code I am using:
#include <cstdio>
#include <ctime>
#include <unistd.h> // for sleep
int main (int argc, char ** argv)
{
time_t startRawTime, endRawTime;
time (&startRawTime);
printf ("%s", ctime (&startRawTime));
sleep (3); // any preprocessing of input data
time (&endRawTime);
printf ("%s", ctime (&endRawTime));
printf ("%.0fs\n", difftime (endRawTime, startRawTime));
time_t elapsed = static_cast<time_t>(difftime (endRawTime, startRawTime));
struct tm * ptm = gmtime (&elapsed);
printf ("%id %ih %im %is\n", ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
return 0;
}
Here is what it prints:
Mon Apr 9 14:43:16 2012
Mon Apr 9 14:43:19 2012
3s
1d 0h 0m 3s
Of course the last line is wrong (it should be "0d"). It seems it can be solved easily by printing ptm->tm_mday - 1. However, ptm->tm_mday will also be "1" when there really was one day elapsed between the two dates. And so in that case, I don't want to make it appear as "0d".
So is there a way to handle this properly? Or should I get the result of difftime as a double (that is, as a number of seconds) and then calculate myself the number of sec/min/hours/days?
Remark: my code is used only on Linux, compiled with gcc -lstdc++.
A time_t value represents a particular moment in time. The result of difftime is the interval, in seconds, between two moments. That's a very different thing.
In your code, difftime() returns 3.0, since there are 3 seconds between the two specified times. Converting that to time_t gives you a moment 3 seconds after the epoch; on most systems, that's going to be 3 seconds past midnight GMT on January 1, 1970. The tm_mday value is 1 because that was the first day of the month.
You might be able to make this work by subtracting 1 from the tm_mday value, since tm_mday is 1-based rather than 0-based. But you'll still get meaningless results for longer intervals. For example, an interval of 31.5 days will give you noon on February 1, because January has 31 days; that's not relevant to the information you're trying to get.
Just treat the result of difftime() as a double (because that's what it is) and compute the number of days, hours, minutes, and seconds by simple arithmetic.
(With some loss of portability, you can just subract the time_t values directly rather than using difftime(). That will make some of the arithmetic a little easier, but it will break on systems where a time_t value is something other than an integer count of seconds since some epoch. difftime() exists for a reason.)
Of course the last line is wrong (it should be "0d"). It seems it can
be solved easily by printing "ptm->tm_mday - 1". However, ptm->tm_mday
will also be "1" when there really was one day elapsed between the two
dates. And so in that case, I don't want to make it appear as "0d".
That's not correct; if the time interval is just over 1 day, ptm->tm_mday will be 2. You can verify this with a small modification to your code:
time (&endRawTime);
endRawTime += 86400; // add this line
printf ("%s", ctime (&endRawTime));
When I make this change, I get this output:
Mon Apr 9 13:56:49 2012
Tue Apr 10 13:56:52 2012
86403s
2d 0h 0m 3s
which could be corrected by subtracting 1 from ptm->tm_mday. But again, that's not the right approach.
Here's an example using the <chrono> library, a typesafe timing library that will prevent you from making the kind of mistake you're making. In chrono time_points and durations are not interchangeable, and if you try to use them that way then you get compiler errors.
#include <chrono>
#include <iostream>
#include <thread>
#include <cassert>
template<typename Rep,typename Period>
void print_duration(std::chrono::duration<Rep,Period> t) {
assert(0<=t.count() && "t must be >= 0");
// approximate because a day doesn't have a fixed length
typedef std::chrono::duration<int,std::ratio<60*60*24>> days;
auto d = std::chrono::duration_cast<days>(t);
auto h = std::chrono::duration_cast<std::chrono::hours>(t - d);
auto m = std::chrono::duration_cast<std::chrono::minutes>(t - d - h);
auto s = std::chrono::duration_cast<std::chrono::seconds>(t - d - h - m);
if(t>=days(1))
std::cout << d.count() << "d ";
if(t>=std::chrono::hours(1))
std::cout << h.count() << "h ";
if(t>=std::chrono::minutes(1))
std::cout << m.count() << "m ";
std::cout << s.count() << "s";
}
int main() {
auto start = std::chrono::steady_clock::now();
std::this_thread::sleep_for(std::chrono::seconds(3));
auto finish = std::chrono::steady_clock::now();
print_duration(finish-start);
std::cout << '\n';
}
Notes for GCC
Older versions of GCC have monotonic_clock instead of steady_clock. 4.7 has steady_clock.
In order to access std::this_thread::sleep_for you may have to define _GLIBCXX_USE_NANOSLEEP for some reason.