Parse ISO 8601 durations

后端 未结 2 628
囚心锁ツ
囚心锁ツ 2020-12-11 17:34

In ISO 8601, durations are given in the format P[n]Y[n]M[n]DT[n]H[n]M[n]S.

Examples:

20 seconds:

PT20.0S


        
相关标签:
2条回答
  • 2020-12-11 18:03

    Use the standard regex library, the regex you want is something like:

    "P\(\([0-9]+\)Y\)?\(\([0-9]+\)M\)?\(\([0-9]+\)D\)?T\(\([0-9]+\)H\)?\(\([0-9]+\)M\)?\(\([0-9]+\(\.[0-9]+\)?S\)?"
    

    from that you can pull out the number of years, months etc and calculate total seconds.

    0 讨论(0)
  • 2020-12-11 18:04

    Example code for ISO 8601 duration to Unix epoch time converter:

    #include <iostream>
    #include <vector>
    #include <regex>
    
    using namespace std;
    
    void match_duration(const std::string& input, const std::regex& re)
    {
        std::smatch match;
        std::regex_search(input, match, re);
        if (match.empty()) {
            std::cout << "Pattern do NOT match" << std::endl;
            return;
        }
    
        std::vector<double> vec = {0,0,0,0,0,0}; // years, months, days, hours, minutes, seconds
    
        for (size_t i = 1; i < match.size(); ++i) {
    
            if (match[i].matched) {
                std::string str = match[i];
                str.pop_back(); // remove last character.
                vec[i-1] = std::stod(str);
            }
        }
    
        int duration = 31556926   * vec[0] +  // years  
                       2629743.83 * vec[1] +  // months
                       86400      * vec[2] +  // days
                       3600       * vec[3] +  // hours
                       60         * vec[4] +  // minutes
                       1          * vec[5];   // seconds
    
        if (duration == 0) {
            std::cout << "Not valid input" << std::endl;
            return;
        }
    
        std::cout << "duration: " << duration << " [sec.]" << std::endl;
    }
    
    int main()
    {
        std::cout << "-- ISO 8601 duration to Unix epoch time converter--" << std::endl;
        std::cout << "Enter duration (q for quit)" << std::endl;
    
        std::string input;
        //input = "P1Y2M3DT4H5M6S";
        //input = "PT4H5M6S";
        //
        while(true)
        {
            std::cin >> input;
            if (!std::cin)
                break;
            if (input == "q")
                break;
    
            std::regex rshort("^((?!T).)*$");
    
            if (std::regex_match(input, rshort)) // no T (Time) exist
            {
                std::regex r("P([[:d:]]+Y)?([[:d:]]+M)?([[:d:]]+D)?");
                match_duration(input, r);
            }
            else {
    
                std::regex r("P([[:d:]]+Y)?([[:d:]]+M)?([[:d:]]+D)?T([[:d:]]+H)?([[:d:]]+M)?([[:d:]]+S|[[:d:]]+\\.[[:d:]]+S)?");
                match_duration(input, r);
            }
        }
    
        return 0;
      }
    
    0 讨论(0)
提交回复
热议问题