2

I am trying to parse a date which contains a single digit for each of the month and the day. The following parses correctly:

std::istringstream ss("2015/05/01");
std::tm tmb = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };

ss >> std::get_time(&tmb, "%Y/%m/%d");

But when I try to parse

std::istringstream ss("2015/5/1");

I get a failed state in the stream and the time has not been read into the struct properly. Is there a clean (and efficient) way I can parse this?

EDIT: I am developing on Ubuntu 12.04 and the compiler g++ 5.4.1.

Mohak Saxena
  • 81
  • 1
  • 4
  • Similar question https://stackoverflow.com/questions/19482378/how-to-parse-and-validate-a-date-in-stdstring-in-c – Ravi Chandra Jun 06 '17 at 13:26
  • [Handling time, dates and calendars right is a notoriously hard problem](https://stackoverflow.com/questions/6841333/why-is-subtracting-these-two-times-in-1927-giving-a-strange-result), if possible, use a library (e.g. [1](http://www.boost.org/doc/libs/1_62_0/doc/html/date_time.html), [2](https://github.com/HowardHinnant/date)) – Ivan Aksamentov - Drop Jun 06 '17 at 13:38
  • The leading 0 is optional for `%d` and `%m`. It correctly parses on OS X with clang (8.1) and libc++.Perhaps the error is in your std library's `std::get_time` or elsewhere in your code. – Kelvin Sherlock Jun 06 '17 at 13:40
  • What compiler are you using? – Simon Kraemer Jun 06 '17 at 13:45
  • I'm using g++ 5.4.1 on a linux machine – Mohak Saxena Jun 06 '17 at 14:08
  • This appear to be the bug mentioned [link](https://stackoverflow.com/questions/50579469/stdget-time-did-not-parse-day). – Aelian Mar 21 '19 at 19:27

2 Answers2

0

You don't say which platform you are on.

I would advise against writing your own parser. Take a look at strftime/strptime or Boost.Date_Time.

Paul Floyd
  • 5,530
  • 5
  • 29
  • 43
0

You could use Howard Hinnant's portable, free, open-source date/time library. Here is how the program would look:

#include "date.h"
#include <cassert>
#include <sstream>

int
main()
{
    date::year_month_day ymd;
    std::istringstream ss{"2015/5/1"};
    ss >> date::parse("%Y/%m/%d", ymd);
    assert(!ss.fail());
    using namespace date::literals;
    assert(ymd == may/1/2015);
}

You can convert year_month_day into a std:tm if you really want to (here is how), but unless you need to communicate with some client that really needs a tm, there is no reason to.

"date.h" is header only, so it is easy to install, fully documented, easy to use, and builds on the C++11 <chrono>, so it is very type-safe.

Here is a wandbox link showing it running the above program with gcc 5.4.0.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577