Get current number of hours and minutes using chrono::time_point - c++

I have been trying to find an example using std::chrono which simply gets a chrono::time_point and extracts the number of hours and number of minutes as integers.
I have:
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
but I cannot find out how to then extract the hours and the minutes (since midnight)? I am looking for something like:
int hours = now.clock.hours();

Here is a free, open-source date library which will do this for you. Feel free to inspect the code if you want to know exactly how it is done. You can use it to get the current hours and minutes since midnight in the UTC timezone like this:
#include "date/date.h"
#include <iomanip>
#include <iostream>
int
main()
{
auto now = date::floor<std::chrono::minutes>(std::chrono::system_clock::now());
auto dp = date::floor<date::days>(now);
auto time = date::make_time(now - dp);
int hours = time.hours().count();
int minutes = time.minutes().count();
std::cout.fill('0');
std::cout << std::setw(2) << hours << ':' << std::setw(2) << minutes << '\n';
}
If you want the information in some other timezone, you will need this additional IANA time zone parser (or you can write your own timezone management system). The above code would be modified like so to get the hours and minutes since midnight in the local timezone:
#include "date/tz.h"
#include <iomanip>
#include <iostream>
int
main()
{
auto zt = date::make_zoned(date::current_zone(),
std::chrono::system_clock::now());
auto now = date::floor<std::chrono::minutes>(zt.get_local_time());
auto dp = date::floor<date::days>(now);
auto time = date::make_time(now - dp);
int hours = time.hours().count();
int minutes = time.minutes().count();
std::cout.fill('0');
std::cout << std::setw(2) << hours << ':' << std::setw(2) << minutes << '\n';
}
These libraries are available on github here:
https://github.com/HowardHinnant/date
Here is a video presentation of the date library:
https://www.youtube.com/watch?v=tzyGjOm8AKo
And here is a video presentation of the time zone library:
https://www.youtube.com/watch?v=Vwd3pduVGKY

The problem is that there isn't really any such functionality in the standard library. You have to convert the time point to a time_t and use the old functions to get a tm structure.

Related

Converting time in milliseconds since epoch to time in yy-dd-hh-ss format

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();
}

c++ chrono Clock in HH:MM:SS when it needs to be in seconds.milliseconds

So right now, the code im using is
using std::chrono::system_clock;
std::time_t tt = system_clock::to_time_t (system_clock::now());
struct std::tm * ptm = std::localtime(&tt);
std::cout << "Current time: " << std::put_time(ptm,"%X") << '\n';
std::this_thread::sleep_for (std::chrono::seconds(7));
It is simple in that this is in a loop, and chrono sleep_for delays the system for however many seconds.
The problem is that it is in the HH:MM:SS format when I really need seconds.milliseconds to show the system clock transaction time. How would I do this? I really just need someone to explain the code, why is it making a struct? And what should I do to change the format? Thanks!
I've got two answers for you:
How to do this next year (in C++20), which isn't implemented today, and
How you can do it today with some minor syntax changes and an open-source 3rd party library.
First 1:
#include <chrono>
#include <iostream>
#include <thread>
int
main()
{
using namespace std::chrono;
auto tp = system_clock::now();
while (true)
{
zoned_time zt{current_zone(), floor<milliseconds>(system_clock::now())};
cout << "Current time: " << std::format("{:%T}", zt) << '\n';
tp += 7s;
std::this_thread::sleep_until (tp);
}
}
This creates a local time using the computer's currently set time zone, with a precision of milliseconds. And then just prints it out with the desired format (%T). I'm using sleep_until instead of sleep_for so that each iteration of the loop doesn't drift off of the desired 7s interval due to loop overhead.
Second 2:
Nobody has C++20 chrono yet, but you can approximate it today with Howard Hinnant's free open source date/time library:
#include "date/tz.h"
#include <chrono>
#include <iostream>
#include <thread>
int
main()
{
using namespace date;
using namespace std::chrono;
auto tp = system_clock::now();
while (true)
{
zoned_time zt{current_zone(), floor<milliseconds>(system_clock::now())};
cout << "Current time: " << format("%T", zt) << '\n';
tp += 7s;
std::this_thread::sleep_until (tp);
}
}
The difference is that the format statement is slightly different, and the library lives in namespace date instead of namespace std::chrono. And there's an extra header to include. And some installation is required to handle the time zones.
If you're happy with a UTC time stamp, instead of a local time stamp, then you can use a header-only version of the same library like this (no installation required):
#include "date/date.h"
#include <iostream>
#include <thread>
int
main()
{
auto tp = std::chrono::system_clock::now();
while (true)
{
using namespace date;
using namespace std::chrono;
std::cout << "Current time: "
<< format("%T", floor<milliseconds>(system_clock::now())) << '\n';
tp += 7s;
std::this_thread::sleep_until (tp);
}
}

Adding and subtracting time with tm

So say I set a time in tm to be 23:00:00
ptm->tm_hour = 23; ptm->tm_min = 0; ptm->tm_sec = 0;
And I want to allow a user to subtract time from this
ptm->tm_hour -= hourinput; ptm->tm_min -= minuteinput; ptm->tm_sec -= secondinput;
If the user subtracts 0 hours, 5 minutes, and 5 seconds, instead of showing up as 22:54:55, it will show up as 23:-5:-5.
I suppose I could do a bunch of if statements to check if ptm is below 0 and account for this, but is there a more efficient way of getting the proper time?
Yes, you can use std::mktime for this. It doesn't just convert a std::tm to a std::time_t, it also fixes the tm if some field went out of range. Consider this example where we take the current time and add 1000 seconds.
#include <iostream>
#include <iomanip> // put_time
#include <ctime>
int main(int argc, char **argv) {
std::time_t t = std::time(nullptr);
std::tm tm = *std::localtime(&t);
std::cout << "Time: " << std::put_time(&tm, "%c %Z") << std::endl;
tm.tm_sec += 1000; // the seconds are now out of range
//std::cout << "Time in 1000 sec" << std::put_time(&tm, "%c %Z") << std::endl; this would crash!
std::mktime(&tm); // also returns a time_t, but we don't need that here
std::cout << "Time in 1000 sec: " << std::put_time(&tm, "%c %Z") << std::endl;
return 0;
}
My Output:
Time: 01/24/19 09:26:46 W. Europe Standard Time
Time in 1000 sec: 01/24/19 09:43:26 W. Europe Standard Time
As you can see, the time went from 09:26:46 to 09:43:26.
Here's another approach using Howard Hinnant's date library, which is on its way into C++2a.
#include <iostream>
#include "date/date.h"
using namespace std::chrono_literals;
// Time point representing the start of today:
auto today = date::floor<date::days>(std::chrono::system_clock::now());
auto someTp = today + 23h; // Today, at 23h00
auto anotherTp = someTp - 5min - 5s; // ... should be self-explanatory now :)
std::cout << date::format("%b-%d-%Y %T\n", anotherTp);
If you want to expose the manipulation of time points via a user interface, the compile-time constructs 23h, 5min and so on are of course not available. Those literals construct std::chrono::duration objects, so you need a mechanism to turn user input into equivalent instances.

Difference between two timestamps in days C++

I have timestamps in the format (Year.Month.Day) in an XML file.
I need to find out the difference between two timestamps in days.
Sample Timestamps:
<Time Stamp="20181015">
<Time Stamp="20181012">
How can I find the number of days between the above timestamps?
Number of days = date2 - date1. I am considering all the days (don't need to skip weekends or any other day). Time-zone does not matter as well.
PS: I understand that I have to parse the timestamp from XML. I am stuck in the logic after parsing value.
Update-1: std::chrono::year and other such things are part of C++20. But I get a compilation error:
namespace "std::chrono" has no member "year"
There is the old fashioned way:
#include <ctime>
#include <iomanip> // std::get_time
#include <sstream>
// ...
std::string s1 = "20181015";
std::string s2 = "20181012";
std::tm tmb{};
std::istringstream(s1) >> std::get_time(&tmb, "%Y%m%d");
auto t1 = std::mktime(&tmb);
std::istringstream(s2) >> std::get_time(&tmb, "%Y%m%d");
auto t2 = std::mktime(&tmb);
auto no_of_secs = long(std::difftime(t2, t1));
auto no_of_days = no_of_secs / (60 * 60 * 24);
std::cout << "days: " << no_of_days << '\n';
You can use C++20's syntax today (with C++11/14/17) by downloading Howard Hinnant's free, open-source date/time library. Here is what the syntax would look like:
#include "date/date.h"
#include <iostream>
#include <sstream>
int
main()
{
using namespace date;
using namespace std;
istringstream in{"<Time Stamp=\"20181015\">\n<Time Stamp=\"20181012\">"};
const string fmt = " <Time Stamp=\"%Y%m%d\">";
sys_days date1, date2;
in >> parse(fmt, date1) >> parse(fmt, date2);
cout << date2 - date1 << '\n';
int diff = (date2 - date1).count();
cout << diff << '\n';
}
This outputs:
-3d
-3
If you don't need time zone support (as in this example), then date.h is a single header, header-only library. Here is the full documentation.
If you need time zone support, that requires an additional library with a header and source: tz.h/tz.cpp. Here is the documentation for the time zone library.

Convert Date-Time to Milliseconds - C++ - cross platform

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).