1

There is some problem with datetime parsing, that I have no idea about great workaround.

Consider following code:

#include <iostream>
#include <string>
#include <boost/date_time/gregorian/gregorian.hpp>

namespace dt = boost::gregorian;

dt::date parse_date(const std::string& msg, const std::string& format)
{
   std::stringstream s(msg);
   dt::date_input_facet * f = new dt::date_input_facet();
   if (format.empty())
   {
      f->set_iso_format();
   }
   else
   {
      f->format(format.c_str());
   }
   std::locale l(std::locale(), f);
   s.imbue(l);
   dt::date result;
   s >> result;
   return result;
}

int main()
{
    const std::string v = "0229";
    auto p = parse_date(v, "%m%d");
    std::cout << p << std::endl;
}

Live example

Problem is, that default year in datetime parser is 1400, that is not leap, so there is no 29 february in this year. The main question is of course why 1400 year is default and not any leap year, anyway I need some nice workaround, any ideas?

ForEveR
  • 55,233
  • 2
  • 119
  • 133

1 Answers1

3

I think the "why" question is not particularly relevant¹. It's just the way it works. The key is that you know what is stopping you from parsing it.

I'd just do the easy thing, below, or just write a tiny spirit parser (int_parser<unsigned char, 10, 2, 2> twice) and construct a ptime directly).

Live On Coliru

#include <iostream>
#include <string>
#include <boost/date_time/gregorian/gregorian.hpp>

namespace dt = boost::gregorian;

dt::date parse_date_mmdd(const std::string &msg) {
    std::stringstream s("2000" + msg);
    dt::date_input_facet *f = new dt::date_input_facet();
    f->format("%Y%m%d");

    std::locale l(std::locale(), f);
    s.imbue(l);
    dt::date result;
    s >> result;

    return result;
}

int main() {
    const std::string v = "0229";
    auto p = parse_date_mmdd(v);
    std::cout << p << std::endl;
}

Prints

2000-Feb-29

¹ The answer likely centers on "there is no data type associated with DayOfYear" as a DayOfMonth tuple (there is no use for it in a date handling library). So you'll always have to decide on a contextual year. Like you'll always have to decide on what timezone to interpret a posix time in. Or even which calendar model to use.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • 1
    There is a partial_date but sadly it does not respect the format string he uses. If "2902" instead of "0229" would work, he could use [this](http://coliru.stacked-crooked.com/a/8c53d94f3c5e1f44). – llonesmiz Dec 19 '15 at 14:42
  • 1
    Good find, @cv_and_he. I wonder how useful `partial_date` is for other tasks (will have a look one day). Here's [the X3 version](http://coliru.stacked-crooked.com/a/752c3ab1fdd5b4e3) for completeness – sehe Dec 19 '15 at 14:59
  • Interesting. Of course I have idea about just add year, but I don't like that way, but probably it's the best. And it's very interesting solution, using partial_date. – ForEveR Dec 19 '15 at 15:16