Date validation

Can someone teach me how to check the date and day? The input file are with 10k of listed day and date in txt file with this format "23/10/2017, Sunday". I need to output 2 txt file which present the valid date and invalid date. For the valid file need to show the number of Sunday, Monday ,etc.

I really need someone to teach me the ways to solve this.
Thank you
Read the data into a struct tm - defined in <ctime>
If it is valid write it to file 1 otherwise write to file 2.

Here is a tutorial about dates and time:
https://www.tutorialspoint.com/cplusplus/cpp_date_time.htm

About date validation:
https://www.google.co.uk/search?q=validate+date+C%2B%2B&ie=utf-8&oe=utf-8&client=firefox-b&gfe_rd=cr&dcr=0&ei=eEmuWsXaFumzgAaXuJb4CQ
Consider doing the validation in two steps:
a. validate that the line in the file is of the form "dd/mm/yyyy, day_of_week"; for example "23/10/2017, Monday"
b. if the validation in step a is successful, extract the values and verify that they are values which form a valid date.

We can use the standard library for both:
<regex> to match the expected pattern, and extract the strings of interest,
<ctime> to check if the extracted values represent a valid date.
Note that using facilities in <ctime> assumes that the date represents a time point after the beginning of the epoch (almost always 00:00:00 Jan 01 1970 UTC).

Something along these lines, perhaps:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <iostream>
#include <string>
#include <regex>
#include <cctype>
#include <ctime>

// convert three-character string "sun", "mon" etc. to week day (sunday==0)
int str_to_week_day( std::string str )
{
    static constexpr std::size_t NWDAYS = 7 ;
    static const std::string wdays[NWDAYS] { "sun", "mon", "tue", "wednes", "thurs", "fri", "satur" } ;

    for( char& c : str ) c = std::tolower(c) ; // convert str to all lower case

    // http://en.cppreference.com/w/cpp/algorithm/find (1)
    return std::find( wdays, wdays+NWDAYS, str ) - wdays ; // return the position in the array
}

// http://en.cppreference.com/w/cpp/chrono/c/tm
// return true if tm holds valid values for day, month, year and day of week
bool valid_tm( const std::tm& tm )
{
    auto cpy = tm ;

    // this two step process would correct any out of range values which may be present in cpy

    // http://en.cppreference.com/w/cpp/chrono/c/mktime
    //    note: "The values in time are permitted to be outside their normal ranges."
    const auto as_time_t = std::mktime( std::addressof(cpy) ) ;

    // http://en.cppreference.com/w/cpp/chrono/c/localtime
    cpy = *std::localtime( std::addressof(as_time_t) ) ;

    return tm.tm_mday == cpy.tm_mday && // valid day
           tm.tm_mon == cpy.tm_mon && // valid month
           tm.tm_year == cpy.tm_year && // valid year
           tm.tm_wday == cpy.tm_wday ; // valid day of week
}

// fill up tm with the parsed values and return true if dt contains a valid date
// in the form "dd/mm/yyyy, day_of_week" eg. "23/10/2017, Monday"
bool valid_date( const std::string& dt, std::tm& tm )
{
    tm = {} ; // set all members of tm to zeroes

    // http://en.cppreference.com/w/cpp/regex/basic_regex

    // ^       - beginning of string
    // \s*     - zero or more white space
    // (\d\d)  - two decimal digits (day), captured
    // /       - literal /
    // (\d\d)  - two decimal digits (month), captured
    // /       - literal /
    // (\d{4}) - four decimal digits (year), captured
    // \,      - literal ,
    // \s+     - one or more white space
    // (Sun|Mon|Tue|Wednes|Thurs|Fri|Satur) - any one of these seven alternatives, captured
    // day     - literal "day"
    // \s*     - zero or more white space
    // $       - end of string
    static const std::regex date_re( R"(^\s*(\d\d)/(\d\d)/(\d{4})\,\s+(Sun|Mon|Tue|Wednes|Thurs|Fri|Satur)day\s*$)",
                                     std::regex::icase ) ; // ignore case (for names of week days)

    // http://en.cppreference.com/w/cpp/regex/match_results
    std::smatch match ;

    // http://en.cppreference.com/w/cpp/regex/regex_match (4)
    if( std::regex_match( dt, match, date_re ) ) // if the pattern in the regex is matched
    {
        // fill up tm with dd, mm, yy and day of week
        // http://en.cppreference.com/w/cpp/chrono/c/tm
        // http://en.cppreference.com/w/cpp/string/basic_string/stol
        tm.tm_mday = std::stoi( match[1] ) ;
        tm.tm_mon = std::stoi( match[2] ) - 1 ; // -1 because in struct tm, January == 0
        tm.tm_year = std::stoi( match[3] ) - 1900 ; // years since 1900
        tm.tm_wday = str_to_week_day( match[4] ) ; // Sunday == 0
        tm.tm_hour = 12 ; // noon

        return valid_tm(tm) ; // return true if tm holds values within the valid range
    }

    return false ;
}

int main()
{
    const std::string str = " 23/10/2017,   MondaY" ;

    std::tm tm ;
    if( valid_date( str, tm ) )
    {
       std::cout << "valid date '" << str << "'\n\n"
                 << "            day of the month: " << tm.tm_mday << '\n'
                 << "          month (january==1): " << tm.tm_mon + 1 << '\n'
                 << "                        year: " << tm.tm_year + 1900 << '\n'
                 << " day of the week (Sunday==0): " << tm.tm_wday << '\n' ;
    }
}

http://coliru.stacked-crooked.com/a/3e15178fe69ae0c4
http://rextester.com/ZOJC9659
Topic archived. No new replies allowed.