Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
}
like image 652
user1024718 Avatar asked May 30 '12 03:05

user1024718


People also ask

How do you check if a date is valid?

Given a date, check if it is valid or not. It may be assumed that the given date is in range from 01/01/1800 to 31/12/9999. Examples : Input : d = 10, m = 12, y = 2000 Output : Yes The given date 10/12/2000 is valid Input : d = 30, m = 2, y = 2000 Output : No The given date 30/2/2000 is invalid.

What is Strptime in C?

The strptime() function converts the character string pointed to by buf to values that are stored in the tm structure pointed to by tm, using the format specified by format. The format contains zero or more directives.

What is Strptime R?

strptime converts character vectors to class "POSIXlt" : its input x is first converted by as. character . Each input string is processed as far as necessary for the format specified: any trailing characters are ignored. strftime is a wrapper for format.


1 Answers

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.

like image 58
caf Avatar answered Oct 01 '22 12:10

caf