1 /* 2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /* This code placed in the public domain by Mark W. Eichin */ 9 10 #include <stdio.h> 11 #include <k5-int.h> 12 13 #ifdef HAVE_SYS_TYPES_H 14 #include <sys/types.h> 15 #endif 16 #ifdef HAVE_SYS_TIME_H 17 #include <sys/time.h> 18 #ifdef TIME_WITH_SYS_TIME 19 #include <time.h> 20 #endif 21 #else 22 #include <time.h> 23 #endif 24 25 /* take a struct tm, return seconds from GMT epoch */ 26 /* like mktime, this ignores tm_wday and tm_yday. */ 27 /* unlike mktime, this does not set them... it only passes a return value. */ 28 29 static const int days_in_month[12] = { 30 0, /* jan 31 */ 31 31, /* feb 28 */ 32 59, /* mar 31 */ 33 90, /* apr 30 */ 34 120, /* may 31 */ 35 151, /* jun 30 */ 36 181, /* jul 31 */ 37 212, /* aug 31 */ 38 243, /* sep 30 */ 39 273, /* oct 31 */ 40 304, /* nov 30 */ 41 334 /* dec 31 */ 42 }; 43 44 #define hasleapday(year) (year%400?(year%100?(year%4?0:1):0):1) 45 46 time_t gmt_mktime(struct tm *t) 47 { 48 time_t accum; 49 50 #define assert_time(cnd) if(!(cnd)) return (time_t) -1 51 52 /* 53 * For 32-bit signed time_t centered on 1/1/1970, the range is: 54 * time 0x80000000 -> Fri Dec 13 16:45:52 1901 55 * time 0x7fffffff -> Mon Jan 18 22:14:07 2038 56 * 57 * So years 1901 and 2038 are allowable, but we can't encode all 58 * dates in those years, and we're not doing overflow/underflow 59 * checking for such cases. 60 */ 61 assert_time(t->tm_year>=1); 62 assert_time(t->tm_year<=138); 63 assert_time(t->tm_mon>=0); 64 assert_time(t->tm_mon<=11); 65 assert_time(t->tm_mday>=1); 66 assert_time(t->tm_mday<=31); 67 assert_time(t->tm_hour>=0); 68 assert_time(t->tm_hour<=23); 69 assert_time(t->tm_min>=0); 70 assert_time(t->tm_min<=59); 71 assert_time(t->tm_sec>=0); 72 assert_time(t->tm_sec<=62); 73 74 #undef assert_time 75 76 77 accum = t->tm_year - 70; 78 accum *= 365; /* 365 days/normal year */ 79 80 /* add in leap day for all previous years */ 81 if (t->tm_year >= 70) 82 accum += (t->tm_year - 69) / 4; 83 else 84 accum -= (72 - t->tm_year) / 4; 85 /* add in leap day for this year */ 86 if(t->tm_mon >= 2) /* march or later */ 87 if(hasleapday((t->tm_year + 1900))) accum += 1; 88 89 accum += days_in_month[t->tm_mon]; 90 accum += t->tm_mday-1; /* days of month are the only 1-based field */ 91 accum *= 24; /* 24 hour/day */ 92 accum += t->tm_hour; 93 accum *= 60; /* 60 minute/hour */ 94 accum += t->tm_min; 95 accum *= 60; /* 60 seconds/minute */ 96 accum += t->tm_sec; 97 98 return accum; 99 } 100