A very simple question. I have been using date.h to get epoch in milliseconds and nanoseconds from a full datestamp.
istringstream temp_ss1{timestamp1};
sys_time<nanoseconds> tp1;
temp_ss1 >> parse("%Y/%m/%d,%T", tp1);
std::cout << tp1.time_since_epoch().count() << "ns\n";
What is the method to go from a millisecond epoch to a full datestamp with milliseconds?
Thank you very much for your help !
If you're not picky about the format, you can stream the sys_time<milliseconds> out. If you would like to control the format, you can use date::format with these formatting flags. For example:
std::cout << format("%Y/%m/%d,%T", tp1) << '\n';
The precision of the output will match the precision of the time_point.
Is there a method to convert. "long epoch = 1609330278454" is there a function which take a long and prints a date?
#include "date/date.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
long epoch = 1609330278454;
cout << sys_time<milliseconds>{milliseconds{epoch}} << '\n';
}
Outputs:
2020-12-30 12:11:18.454
You can customize the format like so:
long epoch = 1609330278454;
sys_time<milliseconds> tp{milliseconds{epoch}};
cout << format("%Y/%m/%d,%T", tp) << '\n';
Output:
2020/12/30,12:11:18.454
Related
I have a bunch of tasks which are in the order of microseconds, the below code prints only until seconds (Thu Oct 21 12:48:20 2021) so comparing the values of start and finish always ends up giving 0. I want to be able to compare in the order of milliseconds and microseconds. Is there a function to help with this?
Also, is there a way to convert uint64_t current1 = std::chrono::system_clock::now().time_since_epoch().count(); to time_t to print out the current time based on the count()?
const auto p1 = std::chrono::system_clock::now();
std::time_t now = std::chrono::system_clock::to_time_t(p1);
std::cout << "now: " << std::ctime(&now);
I recommend skipping the C timing API entirely. It is error-prone and doesn't handle sub-second precision.
If UTC (as opposed to local time) is ok, then there is a header-only, open-source preview of C++20 that works with C++11/14/17:
#include "date/date.h"
#include <chrono>
#include <iostream>
int
main()
{
using date::operator<<;
const auto p1 = std::chrono::system_clock::now();
std::cout << "now: " << p1 << '\n';
}
Output:
now: 2021-10-21 20:28:15.754423
To port the above program to C++20 (which is already shipping in the latest Visual Studio), just drop the #include "date/date.h" and using date::operator<<;.
If you need local time, that can be also be had in C++20 (shipping in VS), but the open-source preview of C++20 is no longer header only. There exists one source file that needs to be compiled, and depending on your needs, might require a download of the IANA tz database.
#include "date/tz.h"
#include <chrono>
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
const auto p1 = system_clock::now();
std::cout << "now: " << zoned_time{current_zone(), p1} << '\n';
}
Output:
now: 2021-10-21 16:28:15.754423 EDT
The above syntax assumes C++17. For C++11/14 the template parameter for zoned_time needs to be specified: zoned_time<system_clock::duration>.
The above program ports to C++20 by dropping #include "date/tz.h" and using namespace date;.
In either program you can truncate to millisecond precision with:
const auto p1 = floor<milliseconds>(system_clock::now());
time_t is usually an integer specifying (whole) seconds.
You could get the millseconds by subtracting the whole-second time_t from now:
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
p1 - std::chrono::system_clock::from_time_t(now)).count();
or using operator%:
auto ms = std::chrono::time_point_cast<std::chrono::milliseconds>p1)
.time_since_epoch() % std::chrono::seconds(1);
std::cout << ms.count();
Example how you could do the formatting:
#include <chrono>
#include <iostream>
#include <iomanip>
int main() {
using Clock = std::chrono::system_clock;
using Precision = std::chrono::milliseconds;
auto time_point = Clock::now();
// extract std::time_t from time_point
std::time_t t = Clock::to_time_t(time_point);
// output the part supported by std::tm
std::cout << std::put_time(std::localtime(&t), "%FT%T."); // select format here
// get duration since epoch
auto dur = time_point.time_since_epoch();
// extract the sub second part from the duration since epoch
auto ss =
std::chrono::duration_cast<Precision>(dur) % std::chrono::seconds{1};
// output the millisecond part
std::cout << std::setfill('0') << std::setw(3) << ss.count();
}
Hello I have the following date that I am consuming from an api
string sToParse = "2020-04-17T09:30:00-04:00";
which should be in human form "Friday, April 17, 2020 08:30:00" central time
or epoch of 1587130200
however this code
cout << "raw: " << sToParse << endl;
static const std::string dateTimeFormat { "%Y-%m-%dT%H:%M:%S%Z" };
istringstream ss{ sToParse };
tm dt;
ss >> get_time(&dt, dateTimeFormat.c_str());
cout << mktime(&dt) << endl;
Gives me an epoch of 1587137400 which is a human format of "Friday, April 17, 2020 10:30:00 AM" which is two hours difference. How do i get the %Z to process the timezone appropriately?
Thanks in advance for any help you can give
C++20 will do this:
#include <chrono>
#include <iostream>
#include <sstream>
#include <string>
int
main()
{
using namespace std;
using namespace std::chrono;
string sToParse = "2020-04-17T09:30:00-04:00";
cout << "raw: " << sToParse << endl;
static const std::string dateTimeFormat { "%Y-%m-%dT%H:%M:%S%z" };
istringstream ss{ sToParse };
sys_seconds dt;
ss >> parse(dateTimeFormat, dt);
cout << dt << '\n';
cout << dt.time_since_epoch() << '\n';
}
Output:
2020-04-17 13:30:00
1587130200s
This gets the "epoch time" you're looking for. The big difference is the use of %z instead of %Z. %z is the command for parsing the offset. %Z parses time zone abbreviation.
This doesn't get the "human time" you're expecting. The time printed out above is UTC. This is clearly correct on inspection: 13:30:00 is 4 hours after 09:30:00.
If you are wanting local time, it would be 2020-04-17 09:30:00, same as the input. To come up with 08:30:00 would require more information than you are providing above (e.g. output in some time zone other than that which has a UTC offset of -4h at this local time).
Also it is in general not possible to go from a UTC offset to a time zone name or abbreviation because more than one time zone will generally have the same UTC offset at any point in time.
If the C++20 <chrono> header isn't available for you (to the best of my knowledge it is not yet available anywhere), you can use a free, open-source preview of C+++20 <chrono>. For this problem, one only needs the header-only "date.h" from this preview. And everything is in namespace date instead of namespace std::chrono. It would look like this:
#include "date/date.h"
#include <chrono>
#include <iostream>
#include <sstream>
#include <string>
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
string sToParse = "2020-04-17T09:30:00-04:00";
cout << "raw: " << sToParse << endl;
static const std::string dateTimeFormat { "%Y-%m-%dT%H:%M:%S%z" };
istringstream ss{ sToParse };
sys_seconds dt;
ss >> parse(dateTimeFormat, dt);
cout << dt << '\n';
cout << dt.time_since_epoch() << '\n';
}
Update
With the new knowledge that the "expected human form" of the time should be US Central Time ("America/Chicago" in IANA terms), I'm updating the example code to show how that can be handled.
#include "date/tz.h"
#include <chrono>
#include <iostream>
#include <sstream>
#include <string>
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
string sToParse = "2020-04-17T09:30:00-04:00";
cout << "raw: " << sToParse << endl;
static const std::string dateTimeFormat { "%FT%T%z" };
istringstream ss{ sToParse };
sys_seconds utc;
ss >> parse(dateTimeFormat, utc);
zoned_seconds cst{"America/Chicago", utc};
cout << utc.time_since_epoch() << '\n';
cout << format("%F %T %Z\n", utc);
cout << format("%F %T %Z\n", cst);
}
A few changes above:
A new header is required to handle the time zone issues: "tz.h" (only in the C++20 preview library, not in C++20).
For parsing I've substituted "%Y-%m-%dT%H:%M:%S%z" for "%FT%T%z". These are equivalent. %F is just shorthand for %Y-%m-%d and %T is shorthand for %H:%M:%S. This change is not required.
I've renamed dt to utc to emphasize that this variable holds a UTC time point. This change is not required.
The new line constructs a zoned_time (with seconds precision) with the desired destination time zone ("America/Chicago"), and the UTC time point. This creates an object that knows all about the local time at this time point and in this time zone.
Then everything is printed out using the date::format function and the formatting string "%F %T %Z". %Z is used to output the time zone abbreviation to make the output more readable. In C++20, this will be std::format, and the formatting string will be "{:%F %T %Z}".
The output is now:
raw: 2020-04-17T09:30:00-04:00
1587130200s
2020-04-17 13:30:00 UTC
2020-04-17 08:30:00 CDT
If your computer's current time zone setting happens to be US Central, then the line that constructs zoned_seconds can also look like:
zoned_seconds cst{current_zone(), utc};
Or conversely, you can use this line to find the local time at utc in any time zone which your computer is set to.
Note that whether the time zone is specified with a name such as "America/Chicago", or with current_zone(), any changes of UTC offset within the specified time zone (such as daylight saving time) will be correctly taken into account.
With the preview C+++20 library, the use of the header "tz.h" is not header-only. It requires a single source file, tz.cpp. Here are instructions on how to compile it. But if you are using a fully conforming C++20 <chrono>, then the above will just work by removing #include "date/tz.h", using namespace date;, and adjusting the formatting string as noted in the 5th bullet above.
I have a uint64_t representing the number of nanoseconds since midnight. Would std::chrono allow me to convert this into a meaningful "time", relatively simply?
Also, how would I do it if I have the time since epoch?
For example in such a format:
14:03:27.812374923
And same situation, but when given nanoseconds since epoch? (in case the answer is significantly different)
You could use Howard Hinnant's, free, open-source, header-only library to do this:
#include "date.h"
#include <cstdint>
#include <iostream>
int
main()
{
using namespace std;
using namespace std::chrono;
using namespace date;
uint64_t since_midnight = 50607812374923;
cout << make_time(nanoseconds{since_midnight}) << '\n';
uint64_t since_epoch = 1499522607812374923;
cout << sys_time<nanoseconds>{nanoseconds{since_epoch}} << '\n';
}
This outputs:
14:03:27.812374923
2017-07-08 14:03:27.812374923
Or did you need to take leap seconds into account for since_epoch?
cout << utc_time<nanoseconds>{nanoseconds{since_epoch}} << '\n';
2017-07-08 14:03:00.812374923
For this latter computation, you'll need "tz.h" documented here, and this library is not header only.
I want to convert a string in the format of "20160907-05:00:54.123" into milliseconds.
I know that strptime is not available in Windows and I want to run my program in both windows and linux. I can't use third party libraries as well.
I can tokenize the string and convert it. But is there a more elegant way like using the strptime to do so?
What about std::sscanf?
#include <iostream>
#include <cstring>
int main() {
const char *str_time = "20160907-05:00:54.123";
unsigned int year, month, day, hour, minute, second, miliseconds;
if (std::sscanf(str_time, "%4u%2u%2u-%2u:%2u:%2u.%3u", &year, &month,
&day, &hour, &minute, &second,&miliseconds) != 7)
{
std::cout << "Parse failed" << std::endl;
}
else
{
std::cout << year << month << day << "-" << hour << ":"
<< minute << ":" << second << "." << miliseconds
<< std::endl;
}
}
Output (ideone):
201697-5:0:54.123.
However, you should make sure the input is valid (for example, day can be in the range of [0,99]).
Too bad about no 3rd party libraries, because here is one (MIT license) that is just a single header, runs on linux and Windows, and handles the milliseconds seamlessly:
#include "date.h"
#include <iostream>
#include <sstream>
int
main()
{
date::sys_time<std::chrono::milliseconds> tp;
std::istringstream in{"20160907-05:00:54.123"};
date::parse(in, "%Y%m%d-%T", tp);
std::cout << tp.time_since_epoch().count() << '\n';
}
This outputs:
1473224454123
Error checking is done for you. The stream will fail() if the date is invalid.
date::sys_time<std::chrono::milliseconds> is a type alias for std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>. I.e. it is from the family of system_clock::time_point, just milliseconds precision.
Fully documented:
https://howardhinnant.github.io/date/date.html
Doesn't get much more elegant than this.
Given the format of your string, it is fairly easy to parse it as follows (although a regex or get_time might be more elegant):
tm t;
t.tm_year = stoi(s.substr(0, 4));
t.tm_mon = stoi(s.substr(4, 2));
t.tm_mday = stoi(s.substr(6, 2));
t.tm_hour = stoi(s.substr(9, 2));
t.tm_min = stoi(s.substr(12, 2));
t.tm_sec = 0;
double sec = stod(s.substr(15));
Finding the time since the epoch can be done with mktime:
mktime(&t) + sec * 1000
Note that the fractional seconds need to be handled differently - unfortunately, tm has only integer seconds.
(See the full code here.)
Edit
As Mine and Panagiotis Kanavos correctly note in the comments, Visual C++ apparently supports get_time for quite a while, and it's much shorter with it (note that the fractional seconds need to be handled the same way, though).
I have a device which gives me boost::posix_time::ptime thorugh its API. To sychronize with other Data I need the time as NTP timestamp, differentiated in NTP seconds and NTP fract_seconds.
I tried something like:
#include "boost/date_time/posix_time/posix_time.hpp"
#include <iostream>
using namespace std;
using boost::posix_time::ptime;
using boost::posix_time::time_duration;
using boost::gregorian::date;
int main()
{
ptime t = boost::posix_time::microsec_clock::local_time();
ptime myEpoch(date(1900,boost::gregorian::Jan,1));
time_duration myTimeFromEpoch = t - myEpoch;
boost::uint64_t myTimeAsInt = myTimeFromEpoch.ticks();
cout << myTimeAsInt << endl;
boost::uint32_t seconds = (boost::uint32_t)((myTimeAsInt >> 32) & 0xFFFFFFFF);
boost::uint32_t fraction = (boost::uint32_t)(myTimeAsInt & 0xFFFFFFFF);
cout << seconds << endl;
cout << fraction << endl;
return 0;
}
But it does not give me the correct results? Any help appreciated.
NOTE: boost::ptime may not have the necessary granularity for NTP. However what you can do to obtain the quantity needed (seconds and fractional is as follows)
long seconds = myTimeFromEpoch.total_seconds();
long fractional = myTimeFromEpoch.fractional_seconds()
Now you should have two 32-bit values from which you can construct the necessary NTP timestamp.