In my c project about an Airline Reservation System, I have a class member variable for the date stored as a string (i.e. "4/20/2022") and now I need to store the time as well so I added ctime library. The problem is I cannot compare them because the ctime structure for date gives the date as separate member variables.
Is there a way to compare them?
Here is an example:
time_t ko = time(nullptr);
struct tm time_date_struct = *localtime(&ko);
struct destination_structure {
int offer_id,seat[size];
std::string departure;//store time
std::string arrival;//store time
std::string from_day; // date as string (4/20/2022)
std::string to_day; // date as string (4/21/2022)
destination_structure* next;
};
//...
if(current->from_day < time_date_struct && current->to_day && current->departure < time_date_struct.tm_hour) {
//...
}
CodePudding user response:
- For C 20
<chrono>
, see the bottom half of this answer.
ctime
structure gives them as separate member variables.
First, there's no structure named ctime
. You were describing std::tm
.
To create a std::tm
from given values(year, month, day), you would do something like:
int year = 2022, month = 2, day = 2;
std::tm calendar_time{};
calendar_time.tm_year = year - 1900;
calendar_time.tm_mon = month - 1;
calendar_time.tm_mday = day;
This would assign year, month, and day correspondingly, while keeping the hour, minute, second as 0. Note that you need to minus a number for year and month, because std::tm
uses 1900 as the base year, and January as the base month.
Similarly, you can assign hour/min/sec to calendar_time
with .tm_hour
/.tm_min
/.tm_sec
.
However, std::tm
can't be used to compare with another std::tm
. Instead, you would need to first convert them into a std::time_t
:
auto time_since_epoch = std::mktime(&calendar_time);
Now you can compare the time you create with current time:
auto now = std::time(nullptr);
if (now > time_since_epoch)
std::cout << "time_since_epoch was in the past!";
else
std::cout << "time_since_epoch will be in the future!";
Demo: https://godbolt.org/z/vocGM4WE8
Alternatively, you can format a string from std::time
with the help of std::put_time
:
auto now = std::time(nullptr);
std::stringstream ss;
ss << std::put_time(std::localtime(&now), "%D");
auto now_str = ss.str();
This would create a string in the format of mm/dd/yyyy
. Now you can do a string comparison between this and other strings. However, this is not recommended, as this could easily fail if your strings are not formatted in the exact same way(which will be a problem in your case, since you stored the date as 4/20/2022
instead of 04/20/2022
).
Demo: https://godbolt.org/z/bz36TPfzq
C 20 <chrono>
With the <chrono>
library, creating a date/time object became really simple :
auto now = std::chrono::system_clock::now();
auto another_date = std::chrono::month{2} / 22 / 2022;
if (now > std::chrono::sys_days{another_date})
std::cout << "another_date was in the past!";
else
std::cout << "another_date will be in the future!";
That's all you need!
Demo: https://godbolt.org/z/bMzv9crxh
And you can easily add the time to the date as well:
auto date_time = sys_days{month{2} / 22 / 2022} hours{4} minutes{13} seconds{40};
std::cout << date_time; // prints: 2022-02-22 04:13:40
Sad news is not all compilers fully supports the c 20 <chrono>
yet. A workaround is to use the date
library, written by the same author of <chrono>
, for now.
Demo: https://godbolt.org/z/sWzo5GrE1
CodePudding user response:
chrono::time_point data type can be used for comparing time, calculating durations etc.
Your should parse your string into into this data type first, as well as you'll need to format it back to the string according to the fomat you need maually.
For example:
#include <chrono>
#include <iomanip>
#include <iostream>
#include <sstream>
static std::chrono::time_point<std::chrono::system_clock> parse_time(const std::string& str)
{
std::stringstream in;
if( '/' == str[1] ) {
in.put('0');
}
in << str;
std::tm tmp = {};
in >> std::get_time(&tmp, "%m/%d/%Y");
if(in.fail()) {
throw std::runtime_error("Date parsing failed");
}
return std::chrono::system_clock::from_time_t( std::mktime(&tmp) );
}
static std::size_t diff(const std::chrono::time_point<std::chrono::system_clock>& start,const std::chrono::time_point<std::chrono::system_clock>& end)
{
return std::chrono::duration_cast<std::chrono::days>(end - start).count();
}
std::ostream& operator << (std::ostream& to,const std::chrono::time_point<std::chrono::system_clock>& what)
{
std::time_t tmp = std::chrono::system_clock::to_time_t(what);
to << std::put_time( std::localtime(&tmp), "%d %b %Y" );
return to;
}
int main(int argc, const char** argv)
{
std::chrono::time_point<std::chrono::system_clock> lhs = parse_time("4/20/2022");
std::chrono::time_point<std::chrono::system_clock> rhs = parse_time("4/21/2022");
std::cout << "Left Hand Statement date: " << lhs << std::endl;
std::cout << "Right Hand Statement date: " << rhs << std::endl;
std::cout << std::endl;
if(lhs < rhs) {
std::cout << lhs << " is before " << rhs << std::endl;
}
if(rhs > lhs) {
std::cout << rhs << " is after " << lhs << std::endl;
}
std::cout << diff(lhs,rhs) << " days between " << lhs << " and " << rhs << std::endl;
return 0;
}