Dan Harper
Dan Harper

Reputation: 33

How to check if date is valid using mktime in C?

I have a little problem with my code. I need to check if user's given date is valid or not. I want to check it using 2 rules: 1. Date is valid date and found in a calendar (for example 29.2.2015 is invalid because there's only 28 days in February 2015) 2. Day and month can only be max 2 numbers (for example day 10 and 02 are valid but 010 and 002 are not). All help is appreciated!

This is my code this far:

void dateValidator(const char *date1) {
struct tm date = {0};

int day1;
int month1;
int year1;

int vday;
int vmonth;
int vyear;

sscanf(date1, "%3d.%3d.%d",&day1,&month1,&year1);
/**How do I check that if sscanf reads more than 2 characters on month and day, date is 
invalid?**/

date.tm_year = year1 - 1900;
date.tm_mon = month1 - 1;
date.tm_mday = day1;
date.tm_isdst = -1;

vday = date.tm_mday;
vmonth = date.tm_mon;
vyear = date.tm_year;

mktime(&pvm);

if ((vday != date.tm_mday) || (vmonth != date.tm_mon) || (vyear != date.tm_year)) {
        /**This doesnt seem to work**/
        printf("Invalid date");
}
}

Upvotes: 1

Views: 2821

Answers (3)

chux
chux

Reputation: 153498

How do I check that if sscanf reads more than 2 characters on month and day, date is invalid?

Day and month can only be max 2 numbers digits (for example day 10 and 02 are valid but 010 and 002 are not).

An easy check: Record the offset at the end of the scan and tests 1) that it is not the original 0 (scanning got that far) and 2) this is the end of the string so as to detect extra junk in data1[]. Change 3d to 2d.

int n = 0;
sscanf(date1, "%2d.%2d.%d %n",&day1,&month1,&year1, &n);
if (n > 0 && data1[n] == '\0') Success();
else Fail();

Pedantic code would check with "%[]" to disallow leading spaces and '+'.

int n = 0;
sscanf(date1, "%*2[0-9].%*2[0-9].%*4[0-9] %n", &n);
if (n == 0 || data1[n]) Fail();
else {
  sscanf(date1, "%2d.%2d.%d",&day1,&month1,&year1);
  ...

How to check if date is valid using mktime?

@Marian posted a good solution which adds a test of the return value of mktime().

if (-1 == mktime(&data)) Fail();
if (vday != date.tm_mday) || (vmonth != date.tm_mon) || (vyear != date.tm_year) Fail();

Upvotes: 0

Jimmy
Jimmy

Reputation: 223

int IsValidDate(int year, int month, int day)
{
    unsigned int leap;
    unsigned char mon_day[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

    /* check the rang of the year */
    if ((year < 1) || (year >= 3200))
    {
        return 0;
    }

    if ((month < 1) || (month > 12))
    {
        return 0;
    }

    /* if it's leep year */
    if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
    {
        leap = 1;
    }
    else
    {
        leap = 0;
    }

    mon_day[1] += leap;

    if ((day > mon_day[month - 1]) || (day < 1))
    {
        return 0;
    }

    return 1;
}

For ruler 1, I have wrote this code for check the date before. And I hope this code can help you.

The ruler 2 can easily checked, you can check it by format the valid date and compare it with the input string.

Upvotes: 1

Marian
Marian

Reputation: 7472

I have deleted my previous answer and posting another one. Actually your code is fine, You just have to send the correct parameter to mktime and to check its return value. I.e. change:

mktime(&pvm);
if ((vday != date.tm_mday) || (vmonth != date.tm_mon) || (vyear != date.tm_year)) {
    /**This doesnt seem to work**/
    printf("Invalid date");
}

to something like:

r = mktime(&date);
if (r == -1 || (vday != date.tm_mday) || (vmonth != date.tm_mon) || (vyear != date.tm_year)) {
      printf("Invalid date");
}

and declare the variable r as time_t r;.

Upvotes: 1

Related Questions