How to print the current time with fractional seconds, using fmt library - c++

This code
#include <chrono>
#include <fmt/format.h>
#include <fmt/chrono.h>
...
auto now = std::chrono::system_clock::now();
fmt::print("The time is: {:%Y-%m-%d %H:%M:%S}\n", now);
Prints this:
The time is: 2023-01-02 15:51:23
How do I get it to print sub-second precision, for example, milliseconds? Something like:
The time is: 2023-01-02 15:51:23.753

I think you have to do this in two steps -- YMD and HM followed by the high-res seconds. Here is a worked example, using fmt version 9.0 on Ubuntu:
#include <chrono>
#include <fmt/format.h>
#include <fmt/chrono.h>
int main() {
auto now = std::chrono::system_clock::now();
auto sse = now.time_since_epoch();
fmt::print("{:%FT%H:%M:}{:%S}\n", now, sse);
exit(0);
}
for which I get
$ g++ -o answer answer.cpp -lfmt; ./answer
2023-01-02T16:26:17.009359309
$
(Initial, earlier, slightly off attempt to reason based on spdlog follows. But spdlog wraps fmt and overlays its format.)
It is on the format page, you want something like %Y-%m-%d %H:%M:%S.%e. Note that %e, %f and %F give you milli, micro and nanoseconds. Edit: That was the spdlog format though.
Here is a quick example, for simplicity from my R package RcppSpdlog accessing fmt via spdlog:
> library(RcppSpdlog)
> RcppSpdlog::log_set_pattern("[%Y-%m-%d %H:%M:%S.%f] [%L] %v")
> RcppSpdlog::log_warn("Hello")
[2023-01-02 15:00:49.746031] [W] Hello
> RcppSpdlog::log_set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%L] %v")
> RcppSpdlog::log_warn("World")
[2023-01-02 15:01:02.137] [W] World
>
Note the display of micro- and milliseconds as stated.
Edit: There is something else going on with your example. Here is a simplified answer, printing only seconds and it comes by default fractionally down to nanoseconds (for me on Linux):
$ cat answer.cpp
#include <chrono>
#include <fmt/format.h>
#include <fmt/chrono.h>
int main() {
fmt::print("{:%S}\n", std::chrono::system_clock::now().time_since_epoch());
exit(0);
}
$ g++ -o answer answer.cpp -lfmt
$ ./answer
02.461241690
$

Just share my way to output fractional seconds in logging:
std::string Timestamp() {
namespace c = std::chrono;
auto tp = c::time_point_cast<c::microseconds>(c::system_clock::now());
auto us = tp.time_since_epoch().count() % std::micro::den;
return fmt::format("{:%Y-%m-%d_%H:%M:%S}.{:06d}", tp, us);
}
There is a pull request to output fractional seconds for formatting time_point, (but closed, the author did not continue the work):
https://github.com/fmtlib/fmt/pull/2292
My concern is that change %S to include fractional part is some-what breaking change (strftime defines it as seconds from 00 to 60). I hope fmtlib would consider some other way to tackle this requirement.

Related

how do I get consistent execution times?

I am preparing for a coding challenge, where the fastest calculation of pi to the 10000th digit wins. all calculations will be run on a raspberry Pi4 running linux during competition.
I want to know which code runs the fastest, so I can know which function to submit.
so I wrote a little program named "lol" to try and establish a baseline around a known time.
//lol....lol is an exe which calls usleep()
#include <unistd.h>
using namespace std;
int main(){
usleep(100);
return 0;
}
then to measure execution time, I wrote this:
#include <chrono>
#include <stdlib.h>
#include <iostream>
using namespace std::chrono;
using namespace std;
int main(int argc, char **argv){
//returns runtime in nanoseconds
//useage: runtime <program>
//caveates: I put the exe in /home/$USER/bin
//start timing
auto start = high_resolution_clock::now();
//executable being timed:
system(argv[1]);
// After function call
auto stop = high_resolution_clock::now();
auto duration = duration_cast<nanoseconds>(stop - start);
cout << argv[1] << " " << duration.count() << endl;
return 0;
}
my issue is that the run time seems to be wildly variant. Is this because I'm running in userspace and my system is also doing other things? why am I not getting more consistent run times?
$ ./run_time lol
lol 13497886
$ ./run_time lol
lol 11175649
$ ./run_time lol
lol 3340143
./run_time lol
lol 3364727
$ ./run_time lol
lol 3372376
$ ./run_time lol
lol 1981566
$ ./run_time lol
lol 3385961
instead of executing a program, measure a function completion in a single program:
auto start = high_resolution_clock::now();
//function being timed:
my_func();
// After function call
auto stop = high_resolution_clock::now();
you are using chrono header. so why usleepwhen you can use sleep_for:
https://en.cppreference.com/w/cpp/thread/sleep_for
The merits of this contest is not how you micro-optimize to save 1ns. It`s about choosing the right algorithm to calculate pi.

Adding over 30 days to 1900-01-01

How can I add over 30 days in C++ to 1900-01-01 date approx. over 1000 days and then format the time_t after the addition to get a non-broken date.
This is what I have tried so far:
int tmp = 1000;
struct std::tm tm;
std::istringstream ss("1900-01-01");
ss >> std::get_time(&tm, "%Y-%m-%d");
tm.tm_mday = tm.tm_mday + tmp;
return mktime(&tm);
In addition to Joseph Larson's very good suggestion to check out the date/time library to use, I'll show how you could get further using your current idea.
You also have much support in std::chrono nowadays so read about that too.
You try to add the days in the wrong domain, to std::tm. Instead, convert the std::tm to time_t and add the days to that - then convert the result back to std::tm.
Example:
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
int main() {
int days = 1000;
std::tm tm{};
std::istringstream ss("1900-01-01");
if(ss >> std::get_time(&tm, "%Y-%m-%d")) {
tm.tm_isdst = -1; // let mktime "guess" if DST is effect
// convert to time_t and add 1000 days. 1 day = 24*60*60 seconds
std::time_t result = std::mktime(&tm) + days * 60*60*24;
// back to std::tm
tm = *std::localtime(&result);
// print result
std::cout << std::put_time(&tm, "%Y-%m-%d") << '\n';
}
}
Note: This technique will sometimes get the wrong answer. If for the computer's local time zone the UTC offset at 1900-01-01 is greater than it is at 1900-01-01 + days, then the result will be one day less than it should. This happens (for example) with the IANA time zone America/Anchorage with days == 232. It happens again with Africa/Cairo at days == 273.
A better option is clearly to use the facilities in chrono or Howard Hinnant's date library as demonstrated by Howard.
Date/time handling in C++ is awkward as awkward can be. Howard Hinnant has a great library you may want to look at:
https://github.com/HowardHinnant/date
The problem is complicated. If you use local dates, you can't add a fixed amount of time due to daylight savings time and leap seconds. You could use GMT, but you're still subject to leap seconds.
But Howard's library make make this much easier for you. I'd take a peek.
If you are using the latest Visual Studio 2019, then you have C++20 <chrono> which can solve this problem without the errors associated with the mktime/localtime technique demonstrated in Ted Lyngmo's answser.
#include <chrono>
#include <iostream>
#include <sstream>
int
main()
{
// Hold the amount to add in the type std::chrono::days (a chrono duration)
std::chrono::days days{1000};
// std::chrono::sys_days is a Unix Time chrono::time_point with precision days
std::chrono::sys_days tp;
std::istringstream ss("1900-01-01");
if(ss >> std::chrono::parse("%F", tp)) {
// No need to involve time zones.
// Just add and print out
std::cout << tp + days << '\n'; // 1902-09-28
}
}
This program has the same behavior and output as Ted's answser. But if there's no need to read the "constant" 1900-01-01 out of a stream, then we can do even better. C++20 can make 1900-01-01 a compile-time constant:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std::chrono_literals;
std::chrono::days days{1000};
constexpr std::chrono::sys_days tp = 1900y/01/01; // Compile-time date literal
// Just add and print out
std::cout << tp + days << '\n'; // 1902-09-28
}
These solutions don't involve time zones at all. It is simply adding a number of days to a date. The simplicity makes for efficient code and reduces the chance for errors associated with increased complexity.
If you don't have the latest Visual Studio 2019, or otherwise don't have access to C++20, you can use Howard's free, open-source, header-only "date.h" C++20 chrono preview library referred to in Joseph's answer with nearly identical syntax.
#include "date/date.h"
#include <chrono>
#include <iostream>
int
main()
{
using namespace date::literals;
date::days days{1000};
constexpr date::sys_days tp = 1900_y/01/01; // Compile-time date literal
// Just add and print out
using date::operator<<;
std::cout << tp + days << '\n'; // 1902-09-28
}
The C++20 chrono additions are in namespace date instead of namespace std::chrono.
The year literal is spelled _y instead of y.
The time_point streaming operators won't be found by ADL and have to be manually exposed in namespace date.

is there a way to get utc nanoseconds for a date in uint64_t in c++

I want to get number of nano seconds since epoch in uint64_t for a particular date, is there a function in any c++ library to get it.
If you have access to the C++ 11 libraries, check out the std::chrono library. You can use it to get the milliseconds since the Unix Epoch like this:
#include <chrono>
// ...
using namespace std::chrono;
milliseconds ms = duration_cast< milliseconds >(
system_clock::now().time_since_epoch()
);
You could use Howard Hinnant's free, open-source date/time library which extends std::chrono into the real of calendars:
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono_literals;
uint64_t k = (sys_days{2017_y/mar/21} + 10h + 27min + 5s +
123456789ns).time_since_epoch().count();
std::cout << k << '\n';
}
Output:
1490092025123456789

std::chrono multiplies durations

Consider this example of code:
#include <chrono>
#include <iostream>
int main ( )
{
using namespace std::chrono;
system_clock::time_point s = system_clock::now();
for (int i = 0; i < 1000000; ++i)
std::cout << duration_cast<duration<double>>(system_clock::now() - s).count() << "\n";
}
I expect this to print the elapsed time in seconds. But it actually prints time in thousands of second (the expected result multiplied by 0.001). Am I doing something wrong?
Edit
Since seconds is equivalent to duration<some-int-type>, duration_cast<seconds> gives the same result.
I used gcc-4.7.3-r1
You program works as expected using both gcc 4.8.2 and VS2013. I think it might be a compiler bug in your old gcc 4.7
maverik guessed this right: the problem was with binary incompatibility inside std::chrono - gcc-4.8 version of libstdc++ and gcc-4.7 did not agree on internal units of time.
You could use duration_cast < seconds > instead of duration_cast < duration < double > >

How to sleep until next Sunday

How can I sleep until next Sunday using boost? Can i convert boost::gregorian::date object to something that boost::this_thread::sleep_until can handle? Is it possible?
#include <boost/date_time.hpp>
int main()
{
boost::gregorian::date current_date(boost::gregorian::day_clock::local_day());
boost::gregorian::greg_weekday next_sunday_date(boost::gregorian::Sunday);
boost::gregorian::date next_weekday_date = next_weekday(current_date, next_sunday_date);
// ...
}
Here's what I came up with.
Note that I made the code generally more readable. This is important, not just for future maintenance, but also because it will allow you to "see the forest for the trees" - in turn allowing you to remember the important concepts mentally.
At least, that helps me.
Edit DyP contributed a way to use sleep_until (which would behave more accurately in rare circumstances, e.g. where the clock would change during the sleep).
#include <boost/date_time.hpp>
#include <boost/date_time/time_clock.hpp>
#include <iostream>
#include <thread>
#include <chrono>
int main()
{
using namespace boost::gregorian;
using boost::posix_time::ptime;
using clock = boost::posix_time::microsec_clock; // or: boost::posix_time::second_clock;
auto today = date(day_clock::local_day());
auto at_sunday = greg_weekday(Sunday);
auto next_sunday = next_weekday(today, at_sunday);
#if 1
auto as_tm = to_tm(next_sunday);
auto as_time_t = mktime(&as_tm);
auto as_time_point = std::chrono::system_clock::from_time_t(as_time_t);
std::this_thread::sleep_until(as_time_point);
#else
auto duration = (ptime(next_sunday) - clock::local_time());
auto msecs = duration.total_milliseconds();
std::cout << msecs << "\n";
std::this_thread::sleep_for(std::chrono::milliseconds(msecs));
#endif
}
See it compiling on Coliru (obviously times out)
This sounds unstable. What if the user turns the computer off or goes into hibernation, or just does a restart?
I would do this in one of two ways:
Add a scheduled task(or whatever the windows/osx terminology is) / cronjob (linux) and set it to run on Sunday.
Add it to autostart and periodically(once per 10/30/60 minutes) check if it's Sunday.
Both ways handle restart/shut off/hibernation better than sleeping for 5 days.