Search code examples
cdatedatetimeparsingstrptime

strptime() produces junk times in C


I tried using strptime() to parse dates in the ISO 8601 format (specified by "%F" or "%Y-%m-%d"), but when i read from the result struct tm i get absurd values for time, minutes and seconds. Here is an example code and the result:

char *s_date = (char *)malloc(sizeof(char) * 255);
scanf("%s", s_date);

struct tm bd_date;
strptime(s_date, "%Y-%m-%d", &bd_date)

printf("%d-%d-%d %d:%d:%d\n", (bd_date.tm_year + 1900), (bd_date.tm_mon + 1), bd_date.tm_mday, bd_date.tm_hour, bd_date.tm_min, bd_date.tm_sec);

The resulting output for the input "1990-05-01" is: 1990-5-1 2007659173:32766:1076394855, which show illegal values for tm_hour, tm_min and tm_sec. What am i doing wrong? is there something i'm missing? I though strptime() would automatically set the unused fields in the format to 0, but it seems like this isn't the case.


Solution

  • Apple’s man page for strptime explicitly says:

    If the format string does not contain enough conversion specifications to completely specify the resulting struct tm, the unspecified members of timeptr are left untouched. For example, if format is “%H:%M:%S”, only tm_hour, tm_sec and tm_min will be modified.

    The Linux man pages are not as explicit but are consistent with this:

    In principle, this function does not initialize tm but stores only the values specified. This means that tm should be initialized before the call.

    The POSIX standard, which both Apple’s macOS and Linux seek to conform to, has neither of the above nor similar text in the 2008 version I have on hand. It is simply silent about whether other structure members are modified or the structure is initialized.

    So, at least in some implementations, strptime does not modify members for which there is no corresponding descriptor in the format string. E.g, if there is no descriptor for hour such as %H, it does not modify the hour member of the structure. If you want those members set, you can set them before calling strptime.