Microseconds epoch to a Date string using chrono - c++

I have been looking around to get what I want but I couldn't find anything hence my question (hopefully not a duplicate!)
I am looking to get a microsecond resolution epoch time (to be converted to a Date string) of the clock perhaps using chrono.
Following is what works for me for seconds resolution:
auto secondsEpochTime = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
std::cout << "Date string = " << ctime(&secondsEpochTime);
However when I change seconds to microseconds, ctime doesn't seem to reflect the correct date.
auto microSecondsEpochTime = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
std::cout << "Date string = " << ctime(&microSecondsEpochTime); // incorrect Date

Unfortunately std::chrono is not complete to provide a full answer to your question. You will have to use parts of the C library until C++23 at least otherwise you might end up with a race-prone implementation.
The idea is to get the timestamp and convert it to an integer as microseconds since epoch (1970-01-01).
Then use localtime_r to get the local time broken down in year/month/day/hour/minute/seconds and print it to string.
Finally append the milliseconds as an int padded to 3 digits and return the entire result as an std::string.
constexpr static int64_t ONEMICROSECOND = 1000000;
static std::string nowstr() {
auto now = std::chrono::system_clock::now();
auto onems = std::chrono::microseconds(1);
int64_t epochus = now.time_since_epoch()/onems;
time_t epoch = epochus/ONEMICROSECOND;
struct tm tms{};
localtime_r( &epoch, &tms );
char buf[128];
size_t nb = strftime( buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tms );
nb += ::sprintf( &buf[nb], ".%06d", int(epochus%ONEMICROSECOND) );
return std::string( buf, nb );
}
If you run this as-is it will likely return the timestamp in GMT. You will heave to set your timezone programatically if not set in the environment (as it happens with compiler explorer/Godbolt.
int main() {
setenv("TZ", "/usr/share/zoneinfo/America/New_York", 1);
std::cout << nowstr() << std::endl;
}
Results in
Program stdout
2022-10-01 22:51:03.988759
Compiler explorer link: https://godbolt.org/z/h88zhrr73
UPDATE: if you prefer to use boost::format (std::format is still incomplete on most compilers unfortunately) then you can do
static std::string nowstr() {
auto now = std::chrono::system_clock::now();
auto onems = std::chrono::microseconds(1);
int64_t epochus = now.time_since_epoch()/onems;
time_t epoch = epochus/ONEMICROSECOND;
struct tm tms{};
localtime_r( &epoch, &tms );
std::ostringstream ss;
ss << boost::format( "%04d-%02d-%02d %02d:%02d:%02d.%06d" )
% (tms.tm_year+1900) % (tms.tm_mon+1) % tms.tm_mday
% tms.tm_hour % tms.tm_min % tms.tm_sec
% (epochus%ONEMICROSECOND);
return ss.str();
}

You will have to use parts of the C library until C++23 at least
Umm... If your platform supports the full C++20 spec (at least with regards to format and chrono):
#include <chrono>
#include <format>
#include <iostream>
int
main()
{
auto tp = std::chrono::system_clock::now();
std::chrono::zoned_time zt{std::chrono::current_zone(),
std::chrono::time_point_cast<std::chrono::microseconds>(tp)};
std::cout << "Date string = " << std::format("{:%a %b %e %T %Y}", zt) << '\n';
}
Sample output:
Date string = Sat Oct 1 23:32:24.843844 2022

Related

How can I round Time epoch to previous midnight

Let's say I have :
time in msec = 1655205146419 , which is generated using :
auto msec = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
Tuesday, June 14, 2022 11:12:26.419 AM
And I want to round it up to the previous midnight :
Tuesday, June 14, 2022 00:00:00.00 AM
any ideas how ?
You can use https://en.cppreference.com/w/cpp/chrono/time_point/floor with a duration https://en.cppreference.com/w/cpp/chrono/duration of 1 day:
#include <iostream>
#include <chrono>
int main()
{
using Day = std::chrono::days;
using std::chrono::duration_cast;
auto start = std::chrono::system_clock::now();
std::cout << duration_cast<std::chrono::milliseconds>(std::chrono::floor<Day>(start).time_since_epoch()).count() << "\n";
}
https://godbolt.org/z/z89nr4Mo3
increased readability when storing the days in a variable:
auto start = std::chrono::system_clock::now();
auto days = std::chrono::floor<Day>(start).time_since_epoch();
std::cout << duration_cast<std::chrono::milliseconds>(days) << std::endl;
Let's say I have : time in msec = 1655205146419
I'd try to stay within the chrono domain as much as it is possible, but if you are forced to use milliseconds since the epoch as an input value:
auto midnight_tp = system_clock::time_point(milliseconds(msec)) -
milliseconds(msec) % days(1);
// or
auto midnight_tp = floor<days>(system_clock::time_point(milliseconds(msec)));
Getting to the unitless milliseconds since the epoch again is just a repetition what you've already done earlier:
auto midnight_msec =
duration_cast<milliseconds>(midnight_tp.time_since_epoch()).count();
Demo
You could do it this way, not as pretty, but you can play a bit with std::tm and get answers that you wish.
#include <ctime>
#include <iostream>
#include <string>
int main() {
std::time_t now = time(0);
std::tm tstruct;
char current_time[20];
char last_midnight[20];
tstruct = *std::localtime(&now);
std::strftime(current_time, sizeof(current_time), "%Y-%m-%d %X", &tstruct);
tstruct.tm_hour = 00;
tstruct.tm_min = 00;
tstruct.tm_sec = 00;
std::strftime(last_midnight, sizeof(last_midnight), "%Y-%m-%d %X", &tstruct);
std::cout << "current_time: " << current_time << std::endl;
std::cout << "last_midnight: " << last_midnight << std::endl;
return 0;
}
Output results

From xs:dateTime to std::chrono::timepoint [duplicate]

Consider a historic date string of format:
Thu Jan 9 12:35:34 2014
I want to parse such a string into some kind of C++ date representation, then calculate the amount of time that has passed since then.
From the resulting duration I need access to the numbers of seconds, minutes, hours and days.
Can this be done with the new C++11 std::chrono namespace? If not, how should I go about this today?
I'm using g++-4.8.1 though presumably an answer should just target the C++11 spec.
std::tm tm = {};
std::stringstream ss("Jan 9 2014 12:35:34");
ss >> std::get_time(&tm, "%b %d %Y %H:%M:%S");
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
GCC prior to version 5 doesn't implement std::get_time. You should also be able to write:
std::tm tm = {};
strptime("Thu Jan 9 2014 12:35:34", "%a %b %d %Y %H:%M:%S", &tm);
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
New answer for old question. Rationale for the new answer: The question was edited from its original form because tools at the time would not handle exactly what was being asked. And the resulting accepted answer gives a subtly different behavior than what the original question asked for.
I'm not trying to put down the accepted answer. It's a good answer. It's just that the C API is so confusing that it is inevitable that mistakes like this will happen.
The original question was to parse "Thu, 9 Jan 2014 12:35:34 +0000". So clearly the intent was to parse a timestamp representing a UTC time. But strptime (which isn't standard C or C++, but is POSIX) does not parse the trailing UTC offset indicating this is a UTC timestamp (it will format it with %z, but not parse it).
The question was then edited to ask about "Thu Jan 9 12:35:34 2014". But the question was not edited to clarify if this was a UTC timestamp, or a timestamp in the computer's current local timezone. The accepted answer implicitly assumes the timestamp represents the computer's current local timezone because of the use of std::mktime.
std::mktime not only transforms the field type tm to the serial type time_t, it also performs an offset adjustment from the computer's local time zone to UTC.
But what if we want to parse a UTC timestamp as the original (unedited) question asked?
That can be done today using this newer, free open-source library.
#include "date/date.h"
#include <iostream>
#include <sstream>
int
main()
{
using namespace std;
using namespace date;
istringstream in{"Thu, 9 Jan 2014 12:35:34 +0000"};
sys_seconds tp;
in >> parse("%a, %d %b %Y %T %z", tp);
}
This library can parse %z. And date::sys_seconds is just a typedef for:
std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>
The question also asks:
From the resulting duration I need access to the numbers of seconds, minutes, hours and days.
That part has remained unanswered. Here's how you do it with this library.
#include "date/date.h"
#include <chrono>
#include <iostream>
#include <sstream>
int
main()
{
using namespace std;
using namespace date;
istringstream in{"Thu, 9 Jan 2014 12:35:34 +0000"};
sys_seconds tp;
in >> parse("%a, %d %b %Y %T %z", tp);
auto tp_days = floor<days>(tp);
auto hms = hh_mm_ss<seconds>{tp - tp_days};
std::cout << "Number of days = " << tp_days.time_since_epoch() << '\n';
std::cout << "Number of hours = " << hms.hours() << '\n';
std::cout << "Number of minutes = " << hms.minutes() << '\n';
std::cout << "Number of seconds = " << hms.seconds() << '\n';
}
floor<days> truncates the seconds-precision time_point to a days-precision time_point. If you subtract the days-precision time_point from tp, you're left with a duration that represents the time since midnight (UTC).
The type hh_mm_ss<seconds> takes any duration convertible to seconds (in this case time since midnight) and creates a {hours, minutes, seconds} field type with getters for each field. If the duration has precision finer than seconds this field type will also have a getter for the subseconds. Prior to C++17, one has to specify that finer duration as the template parameter. In C++17 and later it can be deduced:
auto hms = hh_mm_ss{tp - tp_days};
Finally, one can just print out all of these durations. This example outputs:
Number of days = 16079d
Number of hours = 12h
Number of minutes = 35min
Number of seconds = 34s
So 2014-01-09 is 16079 days after 1970-01-01.
Here is the full example but at milliseconds precision:
#include "date/date.h"
#include <chrono>
#include <iostream>
#include <sstream>
int
main()
{
using namespace std;
using namespace std::chrono;
using namespace date;
istringstream in{"Thu, 9 Jan 2014 12:35:34.123 +0000"};
sys_time<milliseconds> tp;
in >> parse("%a, %d %b %Y %T %z", tp);
auto tp_days = floor<days>(tp);
hh_mm_ss hms{tp - tp_days};
std::cout << tp << '\n';
std::cout << "Number of days = " << tp_days.time_since_epoch() << '\n';
std::cout << "Number of hours = " << hms.hours() << '\n';
std::cout << "Number of minutes = " << hms.minutes() << '\n';
std::cout << "Number of seconds = " << hms.seconds() << '\n';
std::cout << "Number of milliseconds = " << hms.subseconds() << '\n';
}
Output:
2014-01-09 12:35:34.123
Number of days = 16079d
Number of hours = 12h
Number of minutes = 35min
Number of seconds = 34s
Number of milliseconds = 123ms
This library is now part of C++20, but is in namespace std::chrono and found in the header <chrono>.
This is rather C-ish and not as elegant of a solution as Simple's answer, but I think it might work. This answer is probably wrong but I'll leave it up so someone can post corrections.
#include <iostream>
#include <ctime>
int main ()
{
struct tm timeinfo;
std::string buffer = "Thu, 9 Jan 2014 12:35:00";
if (!strptime(buffer.c_str(), "%a, %d %b %Y %T", &timeinfo))
std::cout << "Error.";
time_t now;
struct tm timeinfo2;
time(&now);
timeinfo2 = *gmtime(&now);
time_t seconds = difftime(mktime(&timeinfo2), mktime(&timeinfo));
time(&seconds);
struct tm result;
result = *gmtime ( &seconds );
std::cout << result.tm_sec << " " << result.tm_min << " "
<< result.tm_hour << " " << result.tm_mday;
return 0;
}
Cases covered (code is below):
since a give date until now
long int min0 = getMinutesSince( "2005-02-19 12:35:00" );
since the epoch until now
long int min1 = getMinutesSince1970( );
between two date+hours (since the epoch until a given date)
long int min0 = getMinutesSince1970Until( "2019-01-18 14:23:00" );
long int min1 = getMinutesSince1970Until( "2019-01-18 14:27:00" );
cout << min1 - min0 << endl;
Complete code:
#include <iostream>
#include <chrono>
#include <sstream>
#include <string>
#include <iomanip>
using namespace std;
// ------------------------------------------------
// ------------------------------------------------
long int getMinutesSince1970Until( string dateAndHour ) {
tm tm = {};
stringstream ss( dateAndHour );
ss >> get_time(&tm, "%Y-%m-%d %H:%M:%S");
chrono::system_clock::time_point tp = chrono::system_clock::from_time_t(mktime(&tm));
return
chrono::duration_cast<chrono::minutes>(
tp.time_since_epoch()).count();
} // ()
// ------------------------------------------------
// ------------------------------------------------
long int getMinutesSince1970() {
chrono::system_clock::time_point now = chrono::system_clock::now();
return
chrono::duration_cast<chrono::minutes>( now.time_since_epoch() ).count();
} // ()
// ------------------------------------------------
// ------------------------------------------------
long int getMinutesSince( string dateAndHour ) {
tm tm = {};
stringstream ss( dateAndHour );
ss >> get_time(&tm, "%Y-%m-%d %H:%M:%S");
chrono::system_clock::time_point then =
chrono::system_clock::from_time_t(mktime(&tm));
chrono::system_clock::time_point now = chrono::system_clock::now();
return
chrono::duration_cast<chrono::minutes>(
now.time_since_epoch()-
then.time_since_epoch()
).count();
} // ()
// ------------------------------------------------
// ------------------------------------------------
int main () {
long int min = getMinutesSince1970Until( "1970-01-01 01:01:00" );
cout << min << endl;
long int min0 = getMinutesSince1970Until( "2019-01-18 14:23:00" );
long int min1 = getMinutesSince1970Until( "2019-01-18 14:27:00" );
if ( (min1 - min0) != 4 ) {
cout << " something is wrong " << endl;
} else {
cout << " it appears to work !" << endl;
}
min0 = getMinutesSince( "1970-01-01 01:00:00" );
min1 = getMinutesSince1970( );
if ( (min1 - min0) != 0 ) {
cout << " something is wrong " << endl;
} else {
cout << " it appears to work !" << endl;
}
} // ()

Epoch time to date/time format in boost c++

In Linux, i am reading epoch time from "/proc/stat" as btime and i want to convert to readable date and time format with c++ boost.
I have tried below things and date is working properly.
time_t btime_ = 1505790902; //This is epoch time read from "/proc/stat" file.
std::wstring currentDate_ = L"";
boost::gregorian::date current_date_ =
boost::posix_time::from_time_t(btime_).date();
std::wstring year_ = boost::lexical_cast<std::wstring>
(current_date_.year());
std::wstring day_ = boost::lexical_cast<std::wstring>
(current_date_.day());
Here i am getting correct year and day. BUT How can i get time( HH::MM:SS) from above epoch time ? Let me give hint - i can try.
Thanks in Advance.
Just:
Live On Coliru
#include <ctime>
#include <boost/date_time/posix_time/posix_time_io.hpp>
int main() {
std::time_t btime_ = 1505790902; //This is epoch time read from "/proc/stat" file.
std::cout << boost::posix_time::from_time_t(btime_) << "\n";
std::cout.imbue(std::locale(std::cout.getloc(), new boost::posix_time::time_facet("%H:%M:%S")));
std::cout << boost::posix_time::from_time_t(btime_) << "\n";
}
Prints
2017-Sep-19 03:15:02
03:15:02
UPDATE
To the comment:
Live On Coliru
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <boost/date_time/c_local_time_adjustor.hpp>
namespace pt = boost::posix_time;
namespace g = boost::gregorian;
using local_adj = boost::date_time::c_local_adjustor<pt::ptime>;
int main() {
std::cout.imbue(std::locale(std::cout.getloc(), new pt::time_facet("%H:%M:%S")));
std::time_t btime_ = 1505790902; // This is epoch time read from "/proc/stat" file.
pt::ptime const timestamp = pt::from_time_t(btime_);
std::cout << timestamp << "\n";
// This local adjustor depends on the machine TZ settings
std::cout << local_adj::utc_to_local(timestamp) << " local time\n";
}
Prints
+ TZ=CEST
+ ./a.out
03:15:02
03:15:02 local time
+ TZ=MST
+ ./a.out
03:15:02
20:15:02 local time
You can use a time_facet. Here's an example that prints UTC date/time:
std::string PrintDateTime()
{
std::stringstream str;
boost::posix_time::time_facet *facet = new boost::posix_time::time_facet("%d.%m.%Y-%H:%M:%S-UTC");
str.imbue(std::locale(str.getloc(), facet));
str << boost::posix_time::second_clock::universal_time(); //your time point goes here
return str.str();
}
Notice that you don't need to worry about the memory management of facet. It's taken care of already from within boost.

C++ std::localtime daylight saving time rule (dst) european vs american

I've problem with use of the std::localtime function. When I transform a std::time_t to a local struct tm, it always use the american daylight saving time whereas I want to use the european one (France).
UTC : 03/19/16 16:56 is transformed in Local : 03/19/16 18:56.
At this date, normally, local is 17:56 (UTC+1). The DST happens on the 27th in France.
After several tests, it seems that the used DST is based on the american rule : DST happens on second sunday in march.
I've also changed the TZ environement variable, but it also fails.
`
if( putenv( "TZ=CET-1CEST-2,M3.5.0/2,M10.5.0/3" ) != 0 ) {
std::cout << "Unable to set TZ" << std::endl;
} else {
tz = getenv("TZ");
if (tz) std::cout << tz << std::endl;
else std::cout << "TZ not defined" << std::endl; tzset();
}
struct std::tm t;
t.tm_sec = 0;
t.tm_min = 56;
t.tm_hour = 18;
t.tm_mday = 19;
t.tm_mon = 3-1;
t.tm_year = 2016-1900;
t.tm_isdst = -1;
std::time_t tt = std::mktime(&t);
std::cout << "UTC: " << std::put_time(std::gmtime(&tt), "%c %Z") << '\n'; // UTC : 03/19/16 16:56
std::cout << "local: " << std::put_time(std::localtime(&tt), "%c %Z") << '\n'; // Local : 03/19/16 18:56 (not waited result)
`
As a precision, I use the bcc32c compiler (the embarcadero C++ clang based computer).
I hope I'm clear enough and you'll be able to help me.
Thanks in advance
If you have C++11 (or later) available, which includes <chrono>, and if you are willing to work with the <chrono> system. And if you are willing to use this free, open-source timezone library. Then this is a very simple matter:
#include "tz.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono_literals;
auto zt = make_zoned("Europe/Paris", sys_days{2016_y/mar/19} + 18h + 56min);
std::cout << format("%m/%d/%y %H:%M %Z", zt.get_sys_time()) << '\n';
std::cout << format("%m/%d/%y %H:%M %Z", zt) << '\n';
}
Output:
03/19/16 18:56 UTC
03/19/16 19:56 CET
In short, you form one zoned_time by pairing a timezone of your choosing
("Europe/Paris"), with a sys_time (UTC). Then you can format that zoned_time both by extracting the sys_time back out of it, and by formatting the zoned_time itself, which will use the local_time of the zoned_time.
I attempted to use formatting that was consistent with your comments. You could of course you any format you want. You can also include any std::locale your system supports as the first argument in the calls to format (which %c would take advantage of).
You can also extract individual fields both from the sys_time and from the local_time if you need to, or do other date or time computations. This is more than just a formatting library.
If you are starting with a time_t, there is a static member function of std::chrono::system_clock to convert a time_t to a system_clock::time_point. You can then use that time_point in place of sys_days{2016_y/mar/19} + 18h + 56min in this example:
auto zt = make_zoned("Europe/Paris", system_clock::from_time_t(t));

Get current time in milliseconds using C++ and Boost

In my thread (using boost::thread) I need to retrieve the current time in ms or less and to convert into ms:
Actually, reading here I've found this:
tick = boost::posix_time::second_clock::local_time();
now = boost::posix_time::second_clock::local_time();
And seems to work, but after I need to have a long value of the milliseconds of the now...
How can I do it?
You can use boost::posix_time::time_duration to get the time range. E.g like this
boost::posix_time::time_duration diff = tick - now;
diff.total_milliseconds();
And to get a higher resolution you can change the clock you are using. For example to the boost::posix_time::microsec_clock, though this can be OS dependent. On Windows, for example, boost::posix_time::microsecond_clock has milisecond resolution, not microsecond.
An example which is a little dependent on the hardware.
int main(int argc, char* argv[])
{
boost::posix_time::ptime t1 = boost::posix_time::second_clock::local_time();
boost::this_thread::sleep(boost::posix_time::millisec(500));
boost::posix_time::ptime t2 = boost::posix_time::second_clock::local_time();
boost::posix_time::time_duration diff = t2 - t1;
std::cout << diff.total_milliseconds() << std::endl;
boost::posix_time::ptime mst1 = boost::posix_time::microsec_clock::local_time();
boost::this_thread::sleep(boost::posix_time::millisec(500));
boost::posix_time::ptime mst2 = boost::posix_time::microsec_clock::local_time();
boost::posix_time::time_duration msdiff = mst2 - mst1;
std::cout << msdiff.total_milliseconds() << std::endl;
return 0;
}
On my win7 machine. The first out is either 0 or 1000. Second resolution.
The second one is nearly always 500, because of the higher resolution of the clock. I hope that help a little.
If you mean milliseconds since epoch you could do
ptime time_t_epoch(date(1970,1,1));
ptime now = microsec_clock::local_time();
time_duration diff = now - time_t_epoch;
x = diff.total_milliseconds();
However, it's not particularly clear what you're after.
Have a look at the example in the documentation for DateTime at Boost Date Time
// Get current date/time in milliseconds.
#include "boost/date_time/posix_time/posix_time.hpp"
namespace pt = boost::posix_time;
int main()
{
pt::ptime current_date_microseconds = pt::microsec_clock::local_time();
long milliseconds = current_date_microseconds.time_of_day().total_milliseconds();
pt::time_duration current_time_milliseconds = pt::milliseconds(milliseconds);
pt::ptime current_date_milliseconds(current_date_microseconds.date(),
current_time_milliseconds);
std::cout << "Microseconds: " << current_date_microseconds
<< " Milliseconds: " << current_date_milliseconds << std::endl;
// Microseconds: 2013-Jul-12 13:37:51.699548 Milliseconds: 2013-Jul-12 13:37:51.699000
}
Try this: import headers as mentioned.. gives seconds and milliseconds only. If you need to explain the code read this link.
#include <windows.h>
#include <stdio.h>
void main()
{
SYSTEMTIME st;
SYSTEMTIME lt;
GetSystemTime(&st);
// GetLocalTime(&lt);
printf("The system time is: %02d:%03d\n", st.wSecond, st.wMilliseconds);
// printf("The local time is: %02d:%03d\n", lt.wSecond, lt.wMilliseconds);
}