std::chrono::year_month_day_last
provides a very convenient way to express last days of year/month pairs.
Is there a possibility using std::chrono::parse
, Howard Hinnant's free, open-source, C++11, header-only datetime library or boost to parse a date-string where the "last" part is modeled as the value zero or the absence of a value, f.e. parse "2023-01-00" or "2023-01" as year_month_day_last{2023y / January / last}
?
How about the last
part being modeled with the string "last"
?
#include "date/date.h"
#include <chrono>
#include <iostream>
#include <sstream>
date::year_month_day
my_parse(std::istream& is)
{
using namespace date;
using namespace std;
using namespace chrono;
year_month_day result{};
year_month ym;
is >> parse(" %Y-%m-", ym);
if (!is.fail())
{
if (isdigit(is.peek()))
{
day d;
is >> parse("%d", d);
if (!is.fail())
result = ym/d;
}
else
{
string word;
is >> word;
if (word != "last")
is.setstate(ios::failbit);
else
result = ym/last;
}
}
return result;
}
For C++20, drop #include "date/date.h"
and using namespace date;
.
Just read in a year, month and the trailing -
, and then test to see if you have a number or not following. If number it is a day number, else it better be the string "last".
The beginning space in the format string matches zero or more white space characters.
This could be exercised with:
int
main()
{
using namespace std;
istringstream in{"2023-01-30 2023-01-last"};
in.exceptions(ios::failbit);
auto date1 = my_parse(in);
cout << date1 << '\n';
auto date2 = my_parse(in);
cout << date2 << '\n';
}
which outputs:
2023-01-30
2023-01-31