1 /* Copyright (c) 2002 Arthur David Olson */ 2 /* 3 * tzcalc_limits.c 4 * Original Author: Adapted from tzcode maintained by Arthur David Olson. 5 * Modifications: 6 * - Changed to mktm_r and added __tzcalc_limits - 04/10/02, Jeff Johnston 7 * - Fixed bug in mday computations - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru> 8 * - Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru> 9 * - Moved __tzcalc_limits() to separate file - 05/09/14, Freddie Chopin <freddie_chopin@op.pl> 10 */ 11 12 #include "local.h" 13 14 int __tzcalc_limits(int year)15__tzcalc_limits (int year) 16 { 17 int days, year_days, years; 18 int i, j; 19 __tzinfo_type *const tz = __gettzinfo (); 20 21 if (year < EPOCH_YEAR) 22 return 0; 23 24 tz->__tzyear = year; 25 26 years = (year - EPOCH_YEAR); 27 28 year_days = years * 365 + 29 (years - 1 + EPOCH_YEARS_SINCE_LEAP) / 4 - 30 (years - 1 + EPOCH_YEARS_SINCE_CENTURY) / 100 + 31 (years - 1 + EPOCH_YEARS_SINCE_LEAP_CENTURY) / 400; 32 33 for (i = 0; i < 2; ++i) 34 { 35 if (tz->__tzrule[i].ch == 'J') 36 { 37 /* The Julian day n (1 <= n <= 365). */ 38 days = year_days + tz->__tzrule[i].d + 39 (isleap(year) && tz->__tzrule[i].d >= 60); 40 /* Convert to yday */ 41 --days; 42 } 43 else if (tz->__tzrule[i].ch == 'D') 44 days = year_days + tz->__tzrule[i].d; 45 else 46 { 47 const int yleap = isleap(year); 48 int m_day, m_wday, wday_diff; 49 const uint8_t *const ip = __month_lengths[yleap]; 50 51 days = year_days; 52 53 for (j = 1; j < tz->__tzrule[i].m; ++j) 54 days += ip[j-1]; 55 56 m_wday = (EPOCH_WDAY + days) % DAYSPERWEEK; 57 58 wday_diff = tz->__tzrule[i].d - m_wday; 59 if (wday_diff < 0) 60 wday_diff += DAYSPERWEEK; 61 m_day = (tz->__tzrule[i].n - 1) * DAYSPERWEEK + wday_diff; 62 63 while (m_day >= ip[j-1]) 64 m_day -= DAYSPERWEEK; 65 66 days += m_day; 67 } 68 69 /* store the change-over time in GMT form by adding offset */ 70 tz->__tzrule[i].change = (time_t) days * SECSPERDAY + 71 tz->__tzrule[i].s + tz->__tzrule[i].offset; 72 } 73 74 tz->__tznorth = (tz->__tzrule[0].change < tz->__tzrule[1].change); 75 76 return 1; 77 } 78