9

Is a separator character required to parse a string using std::get_time? I can't find a reference to say that it is. I'm trying to parse an ISO date/time string such as "20140105T123456" - for example:

For example,

#include <iostream>
#include <sstream>
#include <locale>
#include <iomanip>
#include <ctime>

int main(int argc, char* argv[])
{
    std::tm t = { 0 };

    // fails
    std::istringstream ss("20141105T123456");
    ss >> std::get_time(&t, "%Y%m%dT%H%M%S");

    // works
    //std::istringstream ss("2014 11 05 T 12 34 56");
    //ss >> std::get_time(&t, "%Y %m %d T %H %M %S");

    std::ostringstream os;
    std::cout << std::put_time(&t, "%c") << std::endl;
}

I'm using Visual Studio 2013. I tried to build on Linux but the latest version of GCC I have is 4.7.3 which doesn't appear to support get_time yet.

Silly mistake on my part or are separators required?

speedwell
  • 635
  • 4
  • 9
  • 24
  • 2
    I have just hit this issue in visual studio 2016. It is logged here as a bug so please vote it up for a fix: https://connect.microsoft.com/VisualStudio/Feedback/Details/2290315 – NexusSquared Jul 01 '16 at 19:05
  • Even if the format has separators, but input lacks them a debug assertion is raised instead of failing. Bug – dashesy Dec 13 '16 at 23:18

2 Answers2

6

According to the description of second parameter of std::get_time, separators are not required.

The format string consists of zero or more conversion specifiers, whitespace characters, and ordinary characters (except %). Each ordinary character is expected to match one character in the input stream in case-insensitive comparison. Each whitespace character matches arbitrary whitespace in the input string. Each conversion specification begins with % character, optionally followed by E or O modifier (ignored if unsupported by the locale), followed by the character that determines the behavior of the specifier. The format specifiers match the POSIX function strptime()

On my Mac, I use clang++(Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn) ) to compile your code, and run the program, the output is: Sun Nov 5 12:34:56 2014. Acctually, I have gcc 4.8.2 installed, but it doesn't support the std::get_time and std::put_time. Then I search the implementation status for this function, and find that is not implemented in GCC 4.8.0

It did fail in VS2013, after calling std::get_time, all the elements in t are just 0. Format specifiers don't do what's expected here on Windows. It's not your mistake.

Community
  • 1
  • 1
jfly
  • 7,715
  • 3
  • 35
  • 65
  • Thank you for that analysis - for the moment, I'll insert separators myself before I call `std::get_time` – speedwell Jan 17 '14 at 17:44
2

The reference to the POSIX strptime() function in the standard is causing some confusion. The POSIX standard specifies that the conversion operators are separated by non-alpha characters.

The application shall ensure that there is white-space or other non-alphanumeric characters between any two conversion specifications.

The GLIBC version of strptime (and, IMO, any sane implementation) does not require these separators. [http://man7.org/linux/man-pages/man3/strptime.3.html -- see the Notes section.]

Requiring separators makes it impossible to parse conforming ISO-8601 date/time basic formats. As C++ is also an ISO standard, its strptime() function should be able to parse this format.

I think the std::get_time() documentation needs to be clarified to explicitly state that separators shall not be required and justify that statement by pointing to ISO-8601. It should further be clarified that the POSIX strptime() standard only specifies the conversion specifiers that are required to be supported by a conforming implementation.

Colorado.Rob
  • 195
  • 8