mktime.c (1867B)
1 #include <limits.h> 2 #include <time.h> 3 4 #include "../libc.h" 5 #undef mktime 6 7 static int 8 norm(int *val, int *next, int qty) 9 { 10 int v = *val, n = *next, d; 11 12 if (v < 0) { 13 d = -v / qty + 1; 14 v += d * qty; 15 if (n > INT_MAX - d) 16 return 0; 17 n += d; 18 } 19 if (v >= qty) { 20 d = v / qty; 21 v -= d * qty; 22 if (n < INT_MIN + d) 23 return 0; 24 n -= d; 25 } 26 27 *val = v; 28 *next = n; 29 return 1; 30 } 31 32 static int 33 normalize(struct tm *tm) 34 { 35 int mon, day, year; 36 struct tm aux = *tm; 37 38 if (!norm(&tm->tm_sec, &tm->tm_min, 60) || 39 !norm(&tm->tm_min, &tm->tm_hour, 60) || 40 !norm(&tm->tm_hour, &tm->tm_mday, 24) || 41 !norm(&tm->tm_mon, &tm->tm_year, 12)) { 42 return 0; 43 } 44 45 day = tm->tm_mday; 46 year = EPOCH + tm->tm_year; 47 _daysmon[FEB] = FEBDAYS(year); 48 49 for (mon = tm->tm_mon; day < 1; --mon) { 50 day += _daysmon[mon]; 51 if (mon == JAN) { 52 if (year == EPOCH) 53 return -1; 54 year--; 55 _daysmon[FEB] = FEBDAYS(year); 56 mon = DEC+1; 57 } 58 } 59 60 for (; day > _daysmon[mon]; ++mon) { 61 day -= _daysmon[mon]; 62 if (mon == DEC) { 63 if (year == _MAXYEAR) 64 return -1; 65 year++; 66 _daysmon[FEB] = FEBDAYS(year); 67 mon = JAN-1; 68 } 69 } 70 71 tm->tm_mon = mon; 72 tm->tm_year = year - EPOCH; 73 tm->tm_mday = day; 74 tm->tm_wday = (_newyear(tm->tm_year) + tm->tm_yday) % 7; 75 76 return 1; 77 } 78 79 time_t 80 mktime(struct tm *tm) 81 { 82 int i, year, dst; 83 time_t t; 84 struct tm *aux; 85 86 if (!normalize(tm)) 87 return -1; 88 89 t = 0; 90 year = tm->tm_year + 1900; 91 for (i = EPOCH; i < year; i++) 92 t += _daysyear(i) * SECDAY; 93 94 for (i = 0; i < tm->tm_mon; i++) 95 t += _daysmon[i] * SECDAY; 96 97 t += tm->tm_sec; 98 t += tm->tm_min * SECMIN; 99 t += tm->tm_hour * SECHOUR; 100 t += (tm->tm_mday-1) * SECDAY; 101 102 aux = localtime(&t); 103 104 dst = 0; 105 if (tm->tm_isdst == 0 && aux->tm_isdst == 1) 106 dst = -SECHOUR; 107 else if (tm->tm_isdst == 1 && aux->tm_isdst == 0) 108 dst = +SECHOUR; 109 110 t += aux->tm_gmtoff + dst; 111 112 return t; 113 }