12 char *__tzname[2] = { 0, 0 };
15 weak_alias(__timezone, timezone);
16 weak_alias(__daylight, daylight);
17 weak_alias(__tzname, tzname);
18 weak_alias(__dst_offset, dst_offset);
20 static char std_name[TZNAME_MAX+1];
21 static char dst_name[TZNAME_MAX+1];
23 /* all elements are zero-based */
29 } __dst_start, __dst_end;
31 static void zname(char *d, char **s)
34 for (i=0; i<TZNAME_MAX && isalpha(d[i]=**s); i++, (*s)++);
38 static int hhmmss(char **s)
40 int ofs = strtol(*s, s, 10)*3600;
42 if (**s == ':') ofs += strtol(*s+1, s, 10)*60;
43 if (**s == ':') ofs += strtol(*s+1, s, 10);
45 if (**s == ':') ofs -= strtol(*s+1, s, 10)*60;
46 if (**s == ':') ofs -= strtol(*s+1, s, 10);
51 static int dstrule(struct rule *rule, char **s)
53 if (**s != ',') return -1;
57 rule->day = strtol(*s+1, s, 10)-1;
60 rule->month = strtol(*s+1, s, 10)-1;
61 if (**s != '.' || rule->month < 0 || rule->month > 11)
63 rule->week = strtol(*s+1, s, 10)-1;
64 if (**s != '.' || rule->week < 0 || rule->week > 4)
66 rule->day = strtol(*s+1, s, 10);
67 if (rule->day < 0 || rule->day > 6)
72 rule->day = strtol(*s+1, s, 10);
77 rule->time = hhmmss(s);
78 } else rule->time = 7200;
86 strcpy(std_name, "GMT");
87 strcpy(dst_name, "GMT");
88 __tzname[0] = std_name;
89 __tzname[1] = dst_name;
93 if (!(z = getenv("TZ")) || !isalpha(*z)) return;
96 __timezone = hhmmss(&z);
99 if (dst_name[0]) __daylight=1;
101 __dst_offset = hhmmss(&z) - __timezone;
102 if (z==a) __dst_offset = -3600;
104 if (dstrule(&__dst_start, &z) || dstrule(&__dst_end, &z))
110 static int lock, init;
118 static int is_leap(int year)
121 return !(year&3) && ((year%100) || !(year%400));
124 static int cutoff_yday(struct tm *tm, struct rule *rule)
126 static const char days_in_month[] = {31,28,31,30,31,30,31,31,30,31,30,31};
127 static const int first_day[] = {0,31,59,90,120,151,181,212,243,273,304,335};
128 int yday, mday, leap;
130 switch (rule->month) {
132 return rule->day + (tm->tm_mon > 1 && is_leap(tm->tm_year));
136 yday = first_day[rule->month];
137 leap = is_leap(tm->tm_year);
138 if (rule->month > 1 && leap) yday++;
139 mday = (rule->day - (yday + tm->tm_wday - tm->tm_yday) + 1400)%7 + 7*rule->week;
140 if (mday >= days_in_month[rule->month] + (leap && rule->month == 1))
146 struct tm *__dst_adjust(struct tm *tm)
149 int start, end, secs;
150 int after_start, before_end;
152 if (tm->tm_isdst >= 0) return tm;
158 secs = tm->tm_hour*3600 + tm->tm_min*60 + tm->tm_sec;
159 start = cutoff_yday(tm, &__dst_start);
160 end = cutoff_yday(tm, &__dst_end);
162 after_start = (tm->tm_yday > start || (tm->tm_yday == start && secs >= __dst_start.time));
163 before_end = (tm->tm_yday < end || (tm->tm_yday == end && secs < __dst_end.time));
165 if ((after_start && before_end) || ((end < start) && (after_start || before_end))) {
166 tm->tm_sec -= __dst_offset;
168 t = __tm_to_time(tm);
169 return __time_to_tm(t, tm);
170 } else tm->tm_isdst = 0;