6

I am trying to get the difference between two date by using below C code.

but code always giving difference 0. Help me to where i am making mistake.

I am using gcc compiler under linux.

#include <stdio.h>  
#include <time.h>       
int main ()
{
  struct tm start_date;
  struct tm end_date;
  time_t start_time, end_time;
  double seconds;

  start_date.tm_hour = 0;  start_date.tm_min = 0;  start_date.tm_sec = 0;
  start_date.tm_mon = 10; start_date.tm_mday = 15; start_date.tm_year = 2013;

  end_date.tm_hour = 0;  end_date.tm_min = 0;  end_date.tm_sec = 0;
  end_date.tm_mon = 10; end_date.tm_mday = 20; end_date.tm_year = 2013;

  start_time = mktime(&start_date);
  end_time = mktime(&end_date);

  seconds = difftime(end_time, start_time);

  printf ("%.f seconds difference\n", seconds);

  return 0;
}

EDIT : @qchen answer helped lot to solve my problem. one more doubt is there. Below was my update. From the answer

  start_date.tm_hour = 0;  start_date.tm_min = 0;  start_date.tm_sec = 0;
  start_date.tm_mon = 10-1; start_date.tm_mday = 18; start_date.tm_year = 2013-1876;

  end_date.tm_hour = 0;  end_date.tm_min = 0;  end_date.tm_sec = 0;
  end_date.tm_mon = 10-1; end_date.tm_mday = 20; end_date.tm_year = 2013-1876;

tm_year is the year since 1900, then why i getting correct output if i replace 1876 with year between 1876 to 2012.

sujin
  • 2,813
  • 2
  • 21
  • 33
  • 1
    I would zero out those structs just be sure the fields are all zeros. Probably not your problem though. – Charlie Burns Sep 26 '13 at 18:25
  • When I run it on a macbook, I get '428400 seconds difference'. gcc and clang. – Charlie Burns Sep 26 '13 at 18:27
  • I get 432000 seconds difference when I bzero out those structs. So there are some fields in play there. – Charlie Burns Sep 26 '13 at 18:30
  • Running the original code under valgrind you get a bunch of warnings about uninitialized values being used in `mktime`. You definitely have to zero out the structs. – Joni Sep 26 '13 at 18:32
  • See chux's answer below. It's the only explanation for the 0 difference that you saw. You need to check the return value of mktime() for errors. – Charlie Burns Sep 26 '13 at 20:27

3 Answers3

3

The problem is that tm_year is the year since 1900, so 2013 would be 113 http://en.cppreference.com/w/cpp/chrono/c/tm

  start_date.tm_hour = 0;  start_date.tm_min = 0;  start_date.tm_sec = 0;
  start_date.tm_mon = 10; start_date.tm_mday = 15; start_date.tm_year = 113;

  end_date.tm_hour = 0;  end_date.tm_min = 0;  end_date.tm_sec = 0;
  end_date.tm_mon = 10; end_date.tm_mday = 20; end_date.tm_year = 113;

Given 2013, mktime will return -1 as the calendar time cannot be represented. You would think that the year 3913 would be a valid calendar time and the reason is related to the year 2038 problem, as pointed out by Joni

qxixp
  • 131
  • 1
  • 7
  • As others have suggested,it is always a good practice to memset the struct to 0/initialize it before using it – qxixp Sep 26 '13 at 18:42
  • 1
    Well spotted... If `time_t` is a 32-bit value the last date that can be represented is in [January 2038](http://en.wikipedia.org/wiki/Year_2038_problem). – Joni Sep 26 '13 at 18:50
  • please help me to understand new *EDIT* of the question. – sujin Sep 26 '13 at 19:11
  • Since you are calculating the difference between two dates during the same year (except leap year when the range includes February). As long as your tm_year is between 0 to 138, your results should be the same. I hope i understand your question correctly – qxixp Sep 26 '13 at 19:40
1

OP did not check mktime()` result.

As @Joni mentions, set the tm_isdst field. Use 0 or 1 if you know if how DST is applied, else use '-1' and let the OS make the determination.

@qchen mentioned the year 1900 offset as you likely want .tm_year = 2013-1900.

I assert the underlying issue is using mktime() without checcking if it is (time_t) -1. With robust code, this return value should be tested and missing that opened OP code to unexpected results.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

In addition to not specifying the year correctly, you are leaving the tm_isdst field unset. mktime uses this field to determine if the date has or doesn't have daylight-savings time in effect, or if the DST setting should be looked up from timezone databases. This can make the result off by one hour. Add these lines:

/* lookup if DST or not */
start_date.tm_isdst = -1;
end_date.tm_isdst = -1;
Joni
  • 108,737
  • 14
  • 143
  • 193