0

I have some kind of task to make a C program that compares two dates and returns how many days are in between.

The thing is, identifier for variables should be one from time.h library, so I can't use strings or integers for those 2 dates. I know there is time_t identifier for variables in time.h but how do I go on to ask user input for variable with that type? I don't know % what should I put in printf or scanf for this type. Also, is there some way I could check if user input is valid?

And to compare those two, I guess I should be using difftime() function that is also contained in time.h, but then again, I am not sure. I read somewhere it shows difference in seconds, not sure if that source is legit, but I don't really need that. I need days, since I am working with dates.

There is not much material about this online, that is why I am asking for help. Thanks in advance!

Deja123
  • 99
  • 3
  • 8
  • 1
    You can choose any format you wish for how the user enters dates as long as you can convert those inputs to the time representation the `time.h` functions you plan to use understand. The user shouldn't enter `time_t` values anyway since they are non-intuitive to the user as date representations. By the way, you can just read the `time.h` header to know what the base type of `time_t` is to determine what `scanf` format to use if you still think you want to go that route. – lurker May 18 '16 at 21:09
  • looks like most of the values are `int`s, `scanf(%d)` for those: http://pubs.opengroup.org/onlinepubs/007908775/xsh/time.h.html. `time_t` is not a specified type, so you'll have to find what that is for your system: http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to – yano May 18 '16 at 21:13
  • With a little care, you can use [`mktime()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mktime.html) and perhaps [`strftime()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/strftime.html) — and maybe [`strptime()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/strptime.html) if you have a POSIX-ish system, but `strptime()` is a little tricky to use (but then most things related to dates are a little tricky). – Jonathan Leffler May 19 '16 at 00:03

3 Answers3

0

The type time_t is just a counter of seconds. You want to convert it into a struct tm* calling localtime(time_t*). char *ctime(time_t*) will give you a string representation. For formatted input and output you must work with the individual members of struct tm yourself.

Thomas B Preusser
  • 1,159
  • 5
  • 10
0

I am assuming you only want number of days between two dates (not time). As mentioned in one of the comments, choose any format you want for the user input, and then parse it.

One of the simplest formats to ask for as input for a date, is as an integer in the form of yyyymmdd.

So for example if I wanted to find the number of days from my birthday this year (May 27, 2016) to Independence Day (July 4), I would enter into the program 20160527 and 20160704.

As integers these are relatively easy to convert into month, day and year.

Declare a struct tm and set the month day and year for each of these:

// Lets say the above dates were read into integers indate1 and indate2,
// so indate1 = 20160527 and indate2 = 20160704

#include <time.h>

struct tm dt = {0};
dt.tm_year = (indate1/10000) - 1900;
dt.tm_mon  = (indate1/100)%100;
dt.tm_mday = (indate1%100);

// Now convert to time_t:
time_t dt1 = mktime(&dt);

// Now do the same for indate2:
dt.tm_year = (indate2/10000) - 1900;
dt.tm_mon  = (indate2/100)%100;
dt.tm_mday = (indate2%100);
time_t dt2 = mktime(&dt);

// Now take the difference between the two dates:
double seconds = difftime( dt2, dt1 );

// Now convert to number of days:
unsigned long days = ( seconds / (60*60*24) );
fprintf( stdout, "The number of days between those two dates is %ld\n", days);
Daniel Goldfarb
  • 6,937
  • 5
  • 29
  • 61
0

In addition to manually packing the struct tm based on an integer input, you can work directly with string input using strptime. strptime will convert the character string provided as its first parameter to struct tm according to the provided format string.

You may find this more convenient depending on the type of input you are dealing with. A short example would be:

#define _XOPEN_SOURCE

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

int main (int argc, char **argv) {

    char *dtstr1 = argc > 1 ? argv[1] : "20160527";
    char *dtstr2 = argc > 2 ? argv[2] : "20160704";
    struct tm dt = {0};
    time_t dt1 = 0, dt2 = 0;

    /* convert input strings to struct tm */
    strptime (dtstr2, "%Y%m%d", &dt);    
    dt2 = mktime (&dt);

    strptime (dtstr1, "%Y%m%d", &dt);    
    dt1 = mktime (&dt);

    /* get difference in calendar time */
    double seconds = difftime (dt2, dt1);

    /* convert to number of days */
    long days = (seconds/(60*60*24));

    if (seconds < 0) /* output difference with occurrence orientation */
        printf ("%s occurs %ld days after %s\n", dtstr1, -days, dtstr2);
    else if (seconds > 0)
        printf ("%s occurs %ld days before %s\n", dtstr1, days, dtstr2);
    else
        printf ("%s and %s are contemporaneous\n", dtstr1, dtstr2);

    return 0;
}

(note: while unlikely, you can check for overflow in your days conversion)

Example Use/Output

$ ./bin/time_diff_days
20160527 occurs 38 days before 20160704

$ ./bin/time_diff_days 20160101 20150101
20160101 occurs 365 days after 20150101

$ ./bin/time_diff_days 20150101 20150101
20150101 and 20150101 are contemporaneous

Let me know if you have any questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85