Date validation

Mar 18, 2018 at 3:12am
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
Mar 18, 2018 at 11:10am
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
Mar 18, 2018 at 1:47pm
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.