get a set time before and after an iso 8601 timestamp c++
c++, c++11
Solution
You could:
- Convert the string into a `struct tm` using `std::get_time`.
- Modify the `struct tm` (no need to consider the ranges).
- Normalize the `struct tm` using `mktime`.
- Print the `struct tm` using `std::put_time`
#include <ctime>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
std::string increase_minutes(const std::string& input, int delta) {
struct tm tm;
constexpr auto format = "%Y-%m-%d %T";
std::istringstream iss (input);
iss >> std::get_time(&tm, format);
tm.tm_min += delta;
mktime(&tm);
std::ostringstream oss;
oss << std::put_time(&tm, format);
return oss.str();
}
int main() {
auto s = "2012-12-31 23:59:00";
std::cout << increase_minutes(s, 20) << std::endl;
std::cout << increase_minutes(s, -20) << std::endl;
}
Note that `std::get_time` and `std::put_time` are absent in g++/libstdc++. You may need to parse the string using the C functions `sscanf` or `strptime`, and print the string using `strftime`. See also C++ date and time.
Edit: If we want to change by a generic `std::chrono::duration`, it is better we manipulate on a `std::chrono::time_point` directly. We could create a time_point from a `struct tm` with a two-step conversion: time_point ↔ time_t ↔ struct tm, as illustrated below:
#include <ctime>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <chrono>
template <typename R, typename P>
std::string increase_iso_time(const std::string& input,
const std::chrono::duration<R, P>& duration) {
struct tm tm;
constexpr auto format = "%Y-%m-%d %T";
std::istringstream iss (input);
iss >> std::get_time(&tm, format);
auto time = mktime(&tm);
auto tp = std::chrono::system_clock::from_time_t(time);
tp += duration;
time = std::chrono::system_clock::to_time_t(tp);
tm = *localtime(&time);
std::ostringstream oss;
oss << std::put_time(&tm, format);
return oss.str();
}
int main() {
auto s = "2012-12-31 23:59:00";
std::cout << increase_iso_time(s, std::chrono::minutes(20)) << std::endl;
std::cout << increase_iso_time(s, - std::chrono::hours(4)
- std::chrono::minutes(20)) << std::endl;
}
Problem
given a standard ISO 8601 timestamp, is there an easy way to get a time stamp from 20 minutes before and another time stamp of 20 minutes after the original timestamp? For example given ``` 2010-01-25 18:02:00 ``` I would want one or two functions to return, `2010-01-25 17:48:00` and `2010-01-25 18:22:00` The solution I gave up with is rather cumbersome, I use `s.substr(14,2)` to get the minutes and `s.substr(12,2)` to get the hours, convert the hour and minute strings to int and subtract or add the minute value with a condition if it goes above 60 or below 0. Is there a better/easier way to do this?