1238106Sdes/* 2238106Sdes * Taken from FreeBSD src / lib / libc / stdtime / localtime.c 1.43 revision. 3238106Sdes * localtime.c 7.78. 4238106Sdes * tzfile.h 1.8 5238106Sdes * adapted to be replacement gmtime_r. 6238106Sdes */ 7238106Sdes#include "config.h" 8238106Sdes 9238106Sdes#ifdef HAVE_TIME_H 10238106Sdes#include <time.h> 11238106Sdes#endif 12238106Sdes 13238106Sdes#define MONSPERYEAR 12 14238106Sdes#define DAYSPERNYEAR 365 15238106Sdes#define DAYSPERLYEAR 366 16238106Sdes#define SECSPERMIN 60 17238106Sdes#define SECSPERHOUR (60*60) 18238106Sdes#define SECSPERDAY (24*60*60) 19238106Sdes#define DAYSPERWEEK 7 20238106Sdes#define TM_SUNDAY 0 21238106Sdes#define TM_MONDAY 1 22238106Sdes#define TM_TUESDAY 2 23238106Sdes#define TM_WEDNESDAY 3 24238106Sdes#define TM_THURSDAY 4 25238106Sdes#define TM_FRIDAY 5 26238106Sdes#define TM_SATURDAY 6 27238106Sdes 28238106Sdes#define TM_YEAR_BASE 1900 29238106Sdes 30238106Sdes#define EPOCH_YEAR 1970 31238106Sdes#define EPOCH_WDAY TM_THURSDAY 32238106Sdes 33238106Sdes#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) 34238106Sdes 35238106Sdesstatic const int mon_lengths[2][MONSPERYEAR] = { 36238106Sdes { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 37238106Sdes { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 38238106Sdes}; 39238106Sdes 40238106Sdesstatic const int year_lengths[2] = { 41238106Sdes DAYSPERNYEAR, DAYSPERLYEAR 42238106Sdes}; 43238106Sdes 44238106Sdesstatic void 45238106Sdestimesub(timep, offset, tmp) 46238106Sdesconst time_t * const timep; 47238106Sdesconst long offset; 48238106Sdesstruct tm * const tmp; 49238106Sdes{ 50238106Sdes long days; 51238106Sdes long rem; 52238106Sdes long y; 53238106Sdes int yleap; 54238106Sdes const int * ip; 55238106Sdes 56238106Sdes days = *timep / SECSPERDAY; 57238106Sdes rem = *timep % SECSPERDAY; 58238106Sdes rem += (offset); 59238106Sdes while (rem < 0) { 60238106Sdes rem += SECSPERDAY; 61238106Sdes --days; 62238106Sdes } 63238106Sdes while (rem >= SECSPERDAY) { 64238106Sdes rem -= SECSPERDAY; 65238106Sdes ++days; 66238106Sdes } 67238106Sdes tmp->tm_hour = (int) (rem / SECSPERHOUR); 68238106Sdes rem = rem % SECSPERHOUR; 69238106Sdes tmp->tm_min = (int) (rem / SECSPERMIN); 70238106Sdes /* 71238106Sdes ** A positive leap second requires a special 72238106Sdes ** representation. This uses "... ??:59:60" et seq. 73238106Sdes */ 74238106Sdes tmp->tm_sec = (int) (rem % SECSPERMIN) ; 75238106Sdes tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); 76238106Sdes if (tmp->tm_wday < 0) 77238106Sdes tmp->tm_wday += DAYSPERWEEK; 78238106Sdes y = EPOCH_YEAR; 79238106Sdes#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) 80238106Sdes while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) { 81238106Sdes long newy; 82238106Sdes 83238106Sdes newy = y + days / DAYSPERNYEAR; 84238106Sdes if (days < 0) 85238106Sdes --newy; 86238106Sdes days -= (newy - y) * DAYSPERNYEAR + 87238106Sdes LEAPS_THRU_END_OF(newy - 1) - 88238106Sdes LEAPS_THRU_END_OF(y - 1); 89238106Sdes y = newy; 90238106Sdes } 91238106Sdes tmp->tm_year = y - TM_YEAR_BASE; 92238106Sdes tmp->tm_yday = (int) days; 93238106Sdes ip = mon_lengths[yleap]; 94238106Sdes for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) 95238106Sdes days = days - (long) ip[tmp->tm_mon]; 96238106Sdes tmp->tm_mday = (int) (days + 1); 97238106Sdes tmp->tm_isdst = 0; 98238106Sdes} 99238106Sdes 100238106Sdes/* 101238106Sdes* Re-entrant version of gmtime. 102238106Sdes*/ 103238106Sdesstruct tm * gmtime_r(const time_t* timep, struct tm *tm) 104238106Sdes{ 105238106Sdes timesub(timep, 0L, tm); 106238106Sdes return tm; 107238106Sdes} 108