2 * misc - data and miscellaneous routines
16 /* Make sure that the strings do not end up in ROM.
17 * These strings probably contain the wrong value, and we cannot obtain the
18 * right value from the system. TZ is the only help.
20 static char ntstr
[TZ_LEN
+ 1] = "GMT"; /* string for normal time */
21 static char dststr
[TZ_LEN
+ 1] = "GDT"; /* string for daylight saving */
24 long _dst_off
= 60 * 60;
31 static struct dsttype
{
32 char ds_type
; /* Unknown, Julian, Zero-based or M */
33 int ds_date
[3]; /* months, weeks, days */
34 long ds_sec
; /* usually 02:00:00 */
35 } dststart
= { 'U', { 0, 0, 0 }, 2 * 60 * 60 }
36 , dstend
= { 'U', { 0, 0, 0 }, 2 * 60 * 60 };
38 const char *_days
[] = {
39 "Sunday", "Monday", "Tuesday", "Wednesday",
40 "Thursday", "Friday", "Saturday"
43 const char *_months
[] = {
44 "January", "February", "March",
45 "April", "May", "June",
46 "July", "August", "September",
47 "October", "November", "December"
50 const int _ytab
[2][12] = {
51 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
52 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
56 parseZoneName(register char *buf
, register const char *p
)
60 if (*p
== ':') return NULL
;
61 while (*p
&& !isdigit(*p
) && *p
!= ',' && *p
!= '-' && *p
!= '+') {
67 if (n
< 3) return NULL
; /* error */
73 parseTime(register long *tm
, const char *p
, register struct dsttype
*dst
)
76 register const char *q
= p
;
77 char ds_type
= (dst
? dst
->ds_type
: '\0');
79 if (dst
) dst
->ds_type
= 'U';
82 while(*p
>= '0' && *p
<= '9') {
83 n
= 10 * n
+ (*p
++ - '0');
85 if (q
== p
) return NULL
; /* "The hour shall be required" */
86 if (n
< 0 || n
>= 24) return NULL
;
91 while(*p
>= '0' && *p
<= '9') {
92 n
= 10 * n
+ (*p
++ - '0');
94 if (q
== p
) return NULL
; /* format error */
95 if (n
< 0 || n
>= 60) return NULL
;
100 while(*p
>= '0' && *p
<= '9') {
101 n
= 10 * n
+ (*p
++ - '0');
103 if (q
== p
) return NULL
; /* format error */
104 if (n
< 0 || n
>= 60) return NULL
;
109 dst
->ds_type
= ds_type
;
116 parseDate(register char *buf
, register const char *p
, struct dsttype
*dstinfo
)
118 register const char *q
;
121 const int bnds
[3][2] = { { 1, 12 },
134 while(*p
>= '0' && *p
<= '9') {
135 n
= 10 * n
+ (*p
- '0');
138 if (q
== p
) return NULL
; /* format error */
139 if (n
< (ds_type
== 'J') || n
> 365) return NULL
;
140 dstinfo
->ds_type
= ds_type
;
141 dstinfo
->ds_date
[0] = n
;
149 while(*p
>= '0' && *p
<= '9') {
150 n
= 10 * n
+ (*p
- '0');
153 if (q
== p
) return NULL
; /* format error */
154 if (n
< bnds
[cnt
][0] || n
> bnds
[cnt
][1]) return NULL
;
155 dstinfo
->ds_date
[cnt
] = n
;
157 } while (cnt
< 3 && *p
== '.');
158 if (cnt
!= 3) return NULL
;
160 dstinfo
->ds_type
= ds_type
;
165 parseRule(register char *buf
, register const char *p
)
168 register const char *q
;
170 if (!(p
= parseDate(buf
, p
, &dststart
))) return NULL
;
174 if (!(p
= parseTime(&time
, p
, &dststart
))) return NULL
;
175 while( p
!= q
) *buf
++ = *q
++;
177 if (*p
!= ',') return NULL
;
179 if (!(p
= parseDate(buf
, p
, &dstend
))) return NULL
;
183 if (!(p
= parseTime(&time
, p
, &dstend
))) return NULL
;
184 while(*buf
++ = *q
++);
191 last_sunday(register int day
, register struct tm
*timep
)
193 int first
= FIRSTSUNDAY(timep
);
195 if (day
>= 58 && LEAPYEAR(YEAR0
+ timep
->tm_year
)) day
++;
196 if (day
< first
) return first
;
197 return day
- (day
- first
) % 7;
201 date_of(register struct dsttype
*dst
, struct tm
*timep
)
203 int leap
= LEAPYEAR(YEAR0
+ timep
->tm_year
);
204 int firstday
, tmpday
;
205 register int day
, month
;
207 if (dst
->ds_type
!= 'M') {
208 return dst
->ds_date
[0] -
211 && dst
->ds_date
[0] < 58);
215 while (month
< dst
->ds_date
[0]) {
216 day
+= _ytab
[leap
][month
- 1];
219 firstday
= (day
+ FIRSTDAYOF(timep
)) % 7;
221 day
+= (dst
->ds_date
[2] - firstday
+ 7) % 7
222 + 7 * (dst
->ds_date
[1] - 1);
223 if (day
>= tmpday
+ _ytab
[leap
][month
-1]) day
-= 7;