1 /* 2 * Taken from FreeBSD src / lib / libc / stdtime / localtime.c 1.43 revision. 3 * localtime.c 7.78. 4 * tzfile.h 1.8 5 * adapted to be replacement gmtime_r. 6 */ 7 #include "config.h" 8 9 #ifdef HAVE_TIME_H 10 #include <time.h> 11 #endif 12 13 #define MONSPERYEAR 12 14 #define DAYSPERNYEAR 365 15 #define DAYSPERLYEAR 366 16 #define SECSPERMIN 60 17 #define SECSPERHOUR (60*60) 18 #define SECSPERDAY (24*60*60) 19 #define DAYSPERWEEK 7 20 #define TM_SUNDAY 0 21 #define TM_MONDAY 1 22 #define TM_TUESDAY 2 23 #define TM_WEDNESDAY 3 24 #define TM_THURSDAY 4 25 #define TM_FRIDAY 5 26 #define TM_SATURDAY 6 27 28 #define TM_YEAR_BASE 1900 29 30 #define EPOCH_YEAR 1970 31 #define EPOCH_WDAY TM_THURSDAY 32 33 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) 34 35 static const int mon_lengths[2][MONSPERYEAR] = { 36 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 37 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 38 }; 39 40 static const int year_lengths[2] = { 41 DAYSPERNYEAR, DAYSPERLYEAR 42 }; 43 44 static void 45 timesub(timep, offset, tmp) 46 const time_t * const timep; 47 const long offset; 48 struct tm * const tmp; 49 { 50 long days; 51 long rem; 52 long y; 53 int yleap; 54 const int * ip; 55 56 days = *timep / SECSPERDAY; 57 rem = *timep % SECSPERDAY; 58 rem += (offset); 59 while (rem < 0) { 60 rem += SECSPERDAY; 61 --days; 62 } 63 while (rem >= SECSPERDAY) { 64 rem -= SECSPERDAY; 65 ++days; 66 } 67 tmp->tm_hour = (int) (rem / SECSPERHOUR); 68 rem = rem % SECSPERHOUR; 69 tmp->tm_min = (int) (rem / SECSPERMIN); 70 /* 71 ** A positive leap second requires a special 72 ** representation. This uses "... ??:59:60" et seq. 73 */ 74 tmp->tm_sec = (int) (rem % SECSPERMIN) ; 75 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); 76 if (tmp->tm_wday < 0) 77 tmp->tm_wday += DAYSPERWEEK; 78 y = EPOCH_YEAR; 79 #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) 80 while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) { 81 long newy; 82 83 newy = y + days / DAYSPERNYEAR; 84 if (days < 0) 85 --newy; 86 days -= (newy - y) * DAYSPERNYEAR + 87 LEAPS_THRU_END_OF(newy - 1) - 88 LEAPS_THRU_END_OF(y - 1); 89 y = newy; 90 } 91 tmp->tm_year = y - TM_YEAR_BASE; 92 tmp->tm_yday = (int) days; 93 ip = mon_lengths[yleap]; 94 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) 95 days = days - (long) ip[tmp->tm_mon]; 96 tmp->tm_mday = (int) (days + 1); 97 tmp->tm_isdst = 0; 98 } 99 100 /* 101 * Re-entrant version of gmtime. 102 */ 103 struct tm * gmtime_r(const time_t* timep, struct tm *tm) 104 { 105 timesub(timep, 0L, tm); 106 return tm; 107 } 108