user1024718
user1024718

Reputation: 575

How to properly check strptime for valid dates in C

I'm doing the following to convert and check a date, however, I'm not sure why the following date keeps validating as true.

Wouldn't %d check only for [01,31] + leading zeros? Is there a better and more accurate way of doing this?

#include <time.h>
#include <stdio.h>
#include <stdlib.h>

int main () {
    struct tm tm; 

    char buffer [80];
    char *str = "29/Jan/2012";
    if (strptime (str, "%Y/%b/%d", &tm) == NULL)
        exit(EXIT_FAILURE);
    if (strftime (buffer,80,"%Y-%m-%d",&tm) == 0)
        exit(EXIT_FAILURE);

    printf("%s\n", buffer); // prints 29-01-20

    return 0;
}

Upvotes: 10

Views: 3938

Answers (1)

caf
caf

Reputation: 239041

It returns non-NULL because the initial substring 29/Jan/20 matches the pattern (in particular the 20 matches the final %d in the pattern).

If strptime() returns non-NULL, it returns a pointer to the next character after the portion of the input string that matches the pattern. So, in this case, it will return a pointer to the '1' character in the date string.

If you want to ensure that there's nothing left over in the input string, you need to check that the return value points to the terminating null at the end of the input string:

int main ()
{
    struct tm tm;

    char buffer [80];
    char *str = "29/Jan/2012";
    char *end = strptime(str, "%Y/%b/%d ", &tm);
    if (end == NULL || *end != '\0')
        exit(EXIT_FAILURE);
    if (strftime (buffer,80,"%Y-%m-%d",&tm) == 0)
        exit(EXIT_FAILURE);

    printf("%s\n", buffer); // prints 29-01-20

    return 0;
}

Note that I've added a trailing space to the strptime() pattern - this allows trailing whitespace in the input to be accepted. If you don't want to allow that, use your original pattern.

Upvotes: 9

Related Questions