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
One year, 2 month, 3 days, 4 hours, 5 minutes, 6 seconds:
P1Y2M3DT4H5M6S
Question:
Given a string that contains a duration in iso 8601 format. I want to obtain the overall number of seconds of that duration. What is the recommended way in standard C++11 to achieve this?
Remarks:
E.g., there is ptime from_iso_string(std::string) in boost DateTime which does not fit here. Is there a similar way without doing a regex by hand?
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.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With