2018-10-01 00:06:16.700000000
I have a time series data file with timestamps as above. I need to convert this to nanoseconds from epoch, then I will need to add milli, micro, or nanos to the timestamp (shift). Finally for select records bring it back to the format above.
I am having trouble with the time point creation - and how to represent nanoseconds ... It works fine with micros.
Can I please request some assistance with the code fragment below .... and also once I have the nanoseconds from epoch - how do I go back to a timestamp like the one above.
std::string ts("23 01 2020 20:59:59.123456789");
XXXX (ts);
void XXXXX (string timestamp)
{
stringstream temp_ss(timestamp);
tm temp_time_object = {};
temp_ss >> get_time (&temp_time_object, "%Y/%m/%d %H:%M:%S");
chrono::system_clock::time_point temp_time_point = system_clock::from_time_t(mktime(&temp_time_object));
// chrono::high_resolution_clock::time_point temp_time_point1 = temp_time_point;
auto nsecs = stol (timestamp.substr (timestamp.find_first_of('.')+1,9));
// +++ This is where I GET stuck forming the time_point....
// I've tried this so many different ways ....
// Is it that the system_clock cannot accept nanos?
temp_time_point += nanoseconds (nsecs);
auto micro_from_epoch = duration_cast<nanoseconds> (temp_time_point.time_since_epoch()).count();
cout << micro_from_epoch << endl;
}
I am having trouble with the time point creation - and how to represent nanoseconds ... It works fine with micros.
This tells me that your system_clock::time_point
has a precision of coarser than nanoseconds (on llvm it is microseconds, on Windows, 1/10 microseconds). The easiest way to add nanoseconds to such a time_point
is:
auto tp = temp_time_point + nanoseconds (nsecs);
This forms a time_point
that is still system_clock
based, but has the precision of the "common type" of system_clock::duration
and nanoseconds
, which in practice, will just be nanoseconds
.
assume all timestamps are GMT, UTC + 0
Now the problem is that mktime
converts from a local tm
to a UTC time_t
. But you are wanting to convert from a UTC field type, to a UTC serial type.
This is easily accomplished in C++20 (I know you don't have it yet, hear me out):
#include <chrono>
#include <iostream>
#include <sstream>
std::chrono::sys_time<std::chrono::nanoseconds>
XXXXX(std::string const& timestamp)
{
using namespace std;
using namespace std::chrono;
istringstream temp_ss{timestamp};
sys_time<nanoseconds> tp;
temp_ss >> parse("%F %T", tp);
return tp;
}
int
main()
{
auto tp = XXXXX("2018-10-01 00:06:16.700000000");
std::cout << tp.time_since_epoch().count() << "ns\n";
std::string s = std::format("{:%F %T}", tp);
std::cout << s << '\n';
}
This converts the string
to a chrono::time_point<system_clock, nanoseconds>
, which is evidently different from your system_clock::time_point
only in that your system_clock::time_point
has precision coarser than nanoseconds
.
Then format
is used to convert the time_point
back into a string
.
Output:
1538352376700000000ns
2018-10-01 00:06:16.700000000
Now I know that a fully conforming C++20 <chrono>
is a rare thing these days (it's coming). Until it gets here, there is a C++20 <chrono>
preview library that is compatible back to C++11. It is free and open source. And requires very few syntactic changes:
#include "date/date.h"
#include <chrono>
#include <iostream>
#include <sstream>
date::sys_time<std::chrono::nanoseconds>
XXXXX(std::string const& timestamp)
{
using namespace date;
using namespace std;
using namespace std::chrono;
istringstream temp_ss{timestamp};
sys_time<nanoseconds> tp;
temp_ss >> parse("%F %T", tp);
return tp;
}
int
main()
{
using namespace date;
auto tp = XXXXX("2018-10-01 00:06:16.700000000");
std::cout << tp.time_since_epoch().count() << "ns\n";
std::string s = format("%F %T", tp);
std::cout << s << '\n';
}
Output:
1538352376700000000ns
2018-10-01 00:06:16.700000000
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With