is there any function to check if a given date is valid or not? I don't want to write anything from scratch.
e.g. 32/10/2012 is not valid and 10/10/2010 is valid
is there any function to check if a given date is valid or not? I don't want to write anything from scratch.
e.g. 32/10/2012 is not valid and 10/10/2010 is valid
If your string is always in that format the easiest thing to do would be to split the string into its three components, populate a tm
structure and pass it to mktime()
. If it returns -1 then it's not a valid date.
You could also use Boost.Date_Time to parse it:
string inp("10/10/2010");
string format("%d/%m/%Y");
date d;
d = parser.parse_date(inp, format, svp);
The boost date time class should be able to handle what you require. See http://www.boost.org/doc/libs/release/doc/html/date_time.html
If the format of the date is constant and you don't want to use boost, you can always use strptime
, defined in the ctime
header:
const char date1[] = "32/10/2012";
const char date2[] = "10/10/2012";
struct tm tm;
if (!strptime(date1, "%d/%m/%Y", &tm)) std::cout << "date1 isn't valid\n";
if (!strptime(date2, "%d/%m/%Y", &tm)) std::cout << "date2 isn't valid\n";
strptime()
is a non-standard extension that is not available on all systems (including Windows). –
Prowess I faced a similar problem recently, but unfortunately didn't figure out boost
, and mktime
didn't solve my problem. So I decided to manually throw a check for date-time. Hope, it will help someone
bool isDateAndtimeValid( std::vector<int> time ) {
if( time[1]> 12) return false; //month
if( time[2]> 31 ) return false; //day
if( time[2] == 31 and ( time[1] == 4 or time[1] == 6 or time[1] == 9 or time[1] == 11 ) ) return false; //30 days in Apr, Jun, Sen, Nov
if( time[1] == 2) {
if( time[2] > 29 ) return false;
if( time[2] == 29 and ( ( time[0]%100 )%4 != 0) ) return false;
} //Feb
if( time[3] > 23) return false; //hours
if( time[4] > 59 ) return false; //min
if( time[5] > 59) return false; //sec
return true;
}
std::get_time
. But if you're running into the same problem today, that's what you would want to use. –
Duffel You can do it just like this, (in this example I used -
as date separator you can replace -
with \
and test it).
I just split the given date into three parts Y-D-M
then store them into tm
struct, in order to convert it to Unix Time.
Here is the tm
struct content:
struct tm {
int tm_sec; /* seconds, range 0 to 59 */
int tm_min; /* minutes, range 0 to 59 */
int tm_hour; /* hours, range 0 to 23 */
int tm_mday; /* day of the month, range 1 to 31 */
int tm_mon; /* month, range 0 to 11 */
int tm_year; /* The number of years since 1900 */
int tm_wday; /* day of the week, range 0 to 6 */
int tm_yday; /* day in the year, range 0 to 365 */
int tm_isdst; /* daylight saving time */
};
for example you entered this date 2024-02-31
and then stored it into tm
struct, when you will call mktime()
it will fix the bad range you entered, since there is no 31
st day in February
, then you can compare the old tm
and the new tm
and check if their values match, if not then the date is not valid.
bool checkDateFormat(const std::string& dateString) {
char dash;
std::stringstream ss(dateString);
struct tm date;
struct tm newDate;
ss >> date.tm_year >> dash >> date.tm_mon >> dash >> date.tm_mday;
date.tm_year -= 1900; date.tm_mon -= 1;
date.tm_hour = 1; // Hour
date.tm_min = 0; // Minute
date.tm_sec = 0; // Second
newDate = date;
time_t unix_time = mktime(&newDate);
if (
date.tm_year == newDate.tm_year &&
date.tm_mon == newDate.tm_mon &&
date.tm_mday == newDate.tm_mday
)
return true;
return false;
}
int main() {
if (checkDateFormat("2024-02-31") == true)
std::cout << "true" << std::endl;
else
std::cout << "false" << std::endl;
}
you can also print their dates in a readable format like the following:
char buffer[1337];
strftime(buffer, sizeof(buffer), "%c", &date );
std::cout << "date entered: " + std::string(buffer) << std::endl;
strftime(buffer, sizeof(buffer), "%c", &newDate );
std::cout << "date after rounding with mktime: " + std::string(buffer) << std::endl;
insert this code part just after this line
time_t unix_time = mktime(&newDate);
here is an example of what will you get:
date entered: Sun Feb 31 01:00:00 2024
date after rounding with mktime: Sat Mar 2 02:00:00 2024
as you can see 31 Feb
became 2 Mar
, since 2024/Feb
has just 29 days
it got rounded.
C++20 now makes this easier:
#include <chrono>
#include <iostream>
#include <string>
#include <sstream>
bool
is_valid_date(std::string date)
{
std::istringstream in{std::move(date)};
std::chrono::year_month_day ymd;
in >> std::chrono::parse("%d/%m/%Y", ymd);
return !in.fail();
}
int
main()
{
std::cout << is_valid_date("32/10/2012") << '\n';
std::cout << is_valid_date("10/10/2010") << '\n';
}
Output:
0
1
MSVC has this. Coming soon with gcc-14. LLVM is in the implementation stage (as I write this).
© 2022 - 2024 — McMap. All rights reserved.