ashkang / jcal

Jalali Calendar Library
http://nongnu.org/jcal
139 stars 24 forks source link

mktime() and problem 2038 #14

Closed mpahlevanzadeh closed 9 years ago

mpahlevanzadeh commented 9 years ago

1278/10/11 solar equivalent 1900/1/1 AD (Of course in tm struct, months start from 0 ) I compiled the following code in two architectures i386 and amd64: ////////////////////////////////////////////////////////////////////////////////////////////

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

   int
   main(int argc, char ** argv)
   {
       struct tm tm = {0};
       struct jtm jtm = {0};
       time_t t;

       jtm.tm_year = 1278;
       jtm.tm_mon = 10;
       jtm.tm_mday = 11;

       t = jmktime(&jtm);
       localtime_r(&t, &tm);
       printf("%d/%d/%d \n", tm.tm_year+1900, tm.tm_mon, tm.tm_mday);
       exit(EXIT_SUCCESS);
   }

///////////////////////////////////////////////////////////////////////////////////////// Result in amd64: 1900/0/30 Result in i386: 2036/2/8 It's related to problem 2038 at : http://en.wikipedia.org/wiki/Year_2038_problem Solution: At first we need to define two typedef: //////////////////////////////////////

#ifdef i386
     typedef unsigned int time_t;
#elif defined(x86_64) || defined(_M_AMD64) || defined (_M_X64) 
     typedef time_t time_t;
#endif

//////////////////////////// Then anywhere we need variable from time_t , we can do such as : ////////////////////

 time_t   t;

/////////////////////////////// In Total: jcal project has problem for programmer in i386.

ashkang commented 9 years ago

Thanks for the feedback. As you mentioned, Y2038 is a known issue and I'll try to explain why your proposed patch will only shift the problem's interval and is not a good way to deal with it in our special case. It might work in an isolated situation where you know you don't deal with times prior to 1970/1/1 by shifting the scope to 2106. But that still makes sense when you're dealing with an isolated system that has special functionality where system upgrade costs matter. In our case, we have to stick with favoring compatibility over handling Y2038. In general, doing a workaround (And not a fix) for Y2038 only makes sense from an application standpoint, that is when you have a very specific time and data constraints and have no other choice. It absolutely has no meaning from a portable library's standpoint. Computing date and times after the aforementioned time on a 32 bit machine doesn't fit in this criteria in my view and we shouldn't really concern ourselves with it. All standard C library implementations have the same issue as well.

On almost every implementation of the standard C library, time_t is equal to a 32 bit signed integer and therefore any change to time_t definition would break compatibility across 32 bit architectures when there is a comparison involved. As a library, it's vital for jcal to keep this compatibility, because we're never going to know where jcal is going to be used. A comparison between this new internal type that is unsigned and a normal time_t defined by any implementation of standard C library will result in an unexpected behavior. Now if we had an isolated system in for example a bank, we could have done this to buy our self some time. But this will not work on our side. What we can do is to wait for 32 bit systems to abide and fade all together.