Home > front end >  strptime() produces junk times in C
strptime() produces junk times in C

Time:11-22

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.

CodePudding user response:

The strptime function will only set the fields that are specified in the format string. From the man page:

In principle, this function does not initialize tm but only stores the values specified. This means that tm should be initialized before the call. Details differ a bit between different UNIX systems. The glibc implementation does not touch those fields which are not explicitly specified, except that it recomputes the tm_wday and tm_yday field if any of the year, month, or day elements changed.

So in your case, since only year, month, and day were specified, only those corresponding fields (as well as day-of-week and day-of-year) are set.

CodePudding user response:

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.

CodePudding user response:

You may need to set all fields to zero before calling strptime by yourself. Notice that struct tm bd_date; is allocated on stack, so bd_date is full of junk (random values) at this time, instead of full of zero.

  • Related