#define IS_LEAP(n) ((!(((n) + 1900) % 400) || (!(((n) + 1900) % 4) && (((n) + 1900) % 100))) != 0)
#define WRAP(a,b,m) ((a) = ((a) < 0 ) ? ((b)--, (a) + (m)) : (a))
+#define SHOULD_USE_SYSTEM_LOCALTIME(a) ( USE_SYSTEM_LOCALTIME && (a) <= SYSTEM_LOCALTIME_MAX )
+#define SHOULD_USE_SYSTEM_GMTIME(a) ( USE_SYSTEM_GMTIME && (a) <= SYSTEM_GMTIME_MAX )
+
+
int _is_exception_century(Int64 year)
{
int is_exception = ((year % 100 == 0) && !(year % 400 == 0));
}
+#ifdef NDEBUG
+#define CHECK_TM(a)
+#else
+#define CHECK_TM(a) _check_tm(a);
+
void _check_tm(struct tm *tm)
{
int is_leap = IS_LEAP(tm->tm_year);
assert(tm->tm_gmtoff <= 24 * 60 * 60);
#endif
}
+#endif
+
/* The exceptional centuries without leap years cause the cycle to
shift by 16
Time64_T time = *in_time;
Int64 year = 70;
+ /* Use the system gmtime() if time_t is small enough */
+ if( SHOULD_USE_SYSTEM_GMTIME(*in_time) ) {
+ time_t safe_time = *in_time;
+ localtime_r(&safe_time, p);
+ CHECK_TM(p)
+ return p;
+ }
+
#ifdef HAS_TM_TM_GMTOFF
p->tm_gmtoff = 0;
#endif
p->tm_sec = v_tm_sec, p->tm_min = v_tm_min, p->tm_hour = v_tm_hour,
p->tm_mon = v_tm_mon, p->tm_wday = v_tm_wday;
- _check_tm(p);
+ CHECK_TM(p)
return p;
}
Int64 orig_year;
int month_diff;
+ /* Use the system localtime() if time_t is small enough */
+ if( SHOULD_USE_SYSTEM_LOCALTIME(*time) ) {
+ safe_time = *time;
+ localtime_r(&safe_time, local_tm);
+ CHECK_TM(local_tm)
+ return local_tm;
+ }
+
gmtime64_r(time, &gm_tm);
orig_year = gm_tm.tm_year;
if( !IS_LEAP(local_tm->tm_year) && local_tm->tm_yday == 365 )
local_tm->tm_yday--;
- _check_tm(local_tm);
+ CHECK_TM(local_tm)
return local_tm;
}
HAS_TM_TM_ZONE
Defined if your tm struct has a "tm_zone" element.
+
+ SYSTEM_LOCALTIME_MAX
+ SYSTEM_LOCALTIME_MIN
+ SYSTEM_GMTIME_MAX
+ SYSTEM_GMTIME_MIN
+ Maximum and minimum values your system's gmtime() and localtime()
+ can handle.
+
+ USE_SYSTEM_LOCALTIME
+ USE_SYSTEM_GMTIME
+ Should we use the system functions if the time is inside their range?
*/
+#define SYSTEM_LOCALTIME_MAX 2147483647 /* XXX Replace with LOCALTIME_MAX */
+#define SYSTEM_LOCALTIME_MIN -2147483648 /* XXX Replace with LOCALTIME_MIN */
+#define SYSTEM_GMTIME_MAX GMTIME_MAX
+#define SYSTEM_GMTIME_MIN GMTIME_MIN
+
+/* It'll be faster */
+#define USE_SYSTEM_LOCALTIME 1
+
+/* No point risking system bugs, ours works fine */
+#define USE_SYSTEM_GMTIME 0
/* 64 bit types. Set as appropriate for your system. */