1 /*******************************************************************************
5 ** $XConsortium: getdate.y /main/3 1995/11/03 10:38:01 rswiston $
7 ** RESTRICTED CONFIDENTIAL INFORMATION:
9 ** The information in this document is subject to special
10 ** restrictions in a confidential disclosure agreement between
11 ** HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
12 ** document outside HP, IBM, Sun, USL, SCO, or Univel without
13 ** Sun's specific written approval. This document and all copies
14 ** and derivative works thereof must be returned or destroyed at
17 ** Copyright 1993 Sun Microsystems, Inc. All rights reserved.
19 *******************************************************************************/
22 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
23 * (c) Copyright 1993, 1994 International Business Machines Corp. *
24 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
25 * (c) Copyright 1993, 1994 Novell, Inc. *
31 __attribute__((unused))
32 static char sccsid[] = "@(#)getdate.y 1.10 94/11/07 Copyr 1993 Sun Microsystems, Inc.";
36 %token ID MONTH DAY MERIDIAN NUMBER UNIT MUNIT SUNIT ZONE DAYZONE AGO
38 /* Steven M. Bellovin (unc!smb) */
39 /* Dept. of Computer Science */
40 /* University of North Carolina at Chapel Hill */
41 /* @(#)getdate.y 2.6 4/20/84 */
43 #include <EUSCompat.h>
56 #define daysec (24L*60L*60L)
57 static int timeflag, zoneflag, dateflag, dayflag, relflag;
58 static time_t relsec, relmonth;
59 static int hh, mm, ss, merid, daylightsavings;
60 static int dayord, dayreq;
61 static int month, day, year;
93 {if (timeflag && dateflag && !relflag) year = $1;
94 else {timeflag++;hh = $1/100;mm = $1%100;ss = 0;merid = 24;}};
96 tspec: NUMBER MERIDIAN
97 {hh = $1; mm = 0; ss = 0; merid = $2;}
99 {hh = $1; mm = $3; merid = 24;}
100 | NUMBER ':' NUMBER MERIDIAN
101 {hh = $1; mm = $3; merid = $4;}
102 | NUMBER ':' NUMBER ':' NUMBER
103 {hh = $1; mm = $3; ss = $5; merid = 24;}
104 | NUMBER ':' NUMBER ':' NUMBER MERIDIAN
105 {hh = $1; mm = $3; ss = $5; merid = $6;};
108 {ourzone = $1; daylightsavings = STANDARD;}
110 {ourzone = $1; daylightsavings = DAYLIGHT;};
113 {dayord = 1; dayreq = $1;}
115 {dayord = 1; dayreq = $1;}
117 {dayord = $1; dayreq = $3;};
119 dtspec: NUMBER '/' NUMBER
120 {month = $1; day = $3; noyear = 1;}
121 | NUMBER '/' NUMBER '/' NUMBER
122 {month = $1; day = $3; year = $5;}
124 {month = $1; day = $3; noyear = 1;}
125 | NUMBER '-' NUMBER '-' NUMBER
126 {month = $1; day = $3; year = $5;}
128 {month = $1; day = $2; noyear = 1;}
129 | MONTH NUMBER ',' NUMBER
130 {month = $1; day = $2; year = $4;}
132 {month = $3; day = $1; noyear = 1;}
133 | NUMBER ' ' MONTH ' ' NUMBER
134 {month = $3; day = $1; year = $5;};
137 rspec: NUMBER ' ' UNIT
138 {relsec += 60L * $1 * $3;}
140 {relmonth += $1 * $3;}
144 {relsec += 60L * $1;}
150 {relsec = -relsec; relmonth = -relmonth;};
153 static int mdays[12] =
154 {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
155 #define epoch BOT_YEAR
157 extern struct tm *localtime();
158 time_t dateconv(int mm,
171 if (yy < 0) yy = -yy;
178 mdays[1] = 28 + (yy%4 == 0);
186 if (mm < 1 || mm > 12)
189 if (dd < 1 || dd > mdays[--mm])
193 for (i=0; i<mm; i++) jdate += mdays[i];
194 for (i = epoch; i < yy; i++) jdate += 365 + (i%4 == 0);
197 if ((tod = timeconv(h, m, s, mer)) < 0) return (tod);
199 if (dayflag==DAYLIGHT || (dayflag==MAYBE&&localtime(&jdate)->tm_isdst))
204 time_t dayconv(int ord, int day, time_t now)
210 loctime = localtime(&tod);
211 tod += daysec * ((day - loctime->tm_wday + 7) % 7);
212 tod += 7*daysec*(ord<=0?ord:ord-1);
213 return daylcorr(tod, now);
216 time_t timeconv(int hh, int mm, int ss, int mer)
218 if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (DATE_BMIN);
220 case AM: if (hh < 1 || hh > 12) return(DATE_BHOUR);
221 return (60L * ((hh%12)*60L + mm)+ss);
222 case PM: if (hh < 1 || hh > 12) return(DATE_BHOUR);
223 return (60L * ((hh%12 +12)*60L + mm)+ss);
224 case 24: if (hh < 0 || hh > 23) return (DATE_BHOUR);
225 return (60L * (hh*60L + mm)+ss);
226 default: return (DATE_CONV);
229 time_t monthadd(time_t sdate, time_t relmonth)
234 if (relmonth == 0) return 0;
235 ltime = localtime(&sdate);
236 mm = 12*ltime->tm_year + ltime->tm_mon + relmonth;
239 return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour,
240 ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate);
243 time_t daylcorr(time_t future, time_t now)
247 nowdayl = (localtime(&now)->tm_hour+1) % 24;
248 fdayl = (localtime(&future)->tm_hour+1) % 24;
249 return (future-now) + 60L*60L*(nowdayl-fdayl);
257 struct table mdtab[] = {
258 {"January", MONTH, 1},
259 {"February", MONTH, 2},
265 {"August", MONTH, 8},
266 {"September", MONTH, 9},
268 {"October", MONTH, 10},
269 {"November", MONTH, 11},
270 {"December", MONTH, 12},
276 {"Wednesday", DAY, 3},
278 {"Thursday", DAY, 4},
282 {"Saturday", DAY, 6},
287 struct table mztab[] = {
288 {"a.m.", MERIDIAN, AM},
289 {"am", MERIDIAN, AM},
290 {"p.m.", MERIDIAN, PM},
291 {"pm", MERIDIAN, PM},
292 {"nst", ZONE, 3 HRS + HALFHR}, /* Newfoundland */
293 {"n.s.t.", ZONE, 3 HRS + HALFHR},
294 {"ast", ZONE, 4 HRS}, /* Atlantic */
295 {"a.s.t.", ZONE, 4 HRS},
296 {"adt", DAYZONE, 4 HRS},
297 {"a.d.t.", DAYZONE, 4 HRS},
298 {"est", ZONE, 5 HRS}, /* Eastern */
299 {"e.s.t.", ZONE, 5 HRS},
300 {"edt", DAYZONE, 5 HRS},
301 {"e.d.t.", DAYZONE, 5 HRS},
302 {"cst", ZONE, 6 HRS}, /* Central */
303 {"c.s.t.", ZONE, 6 HRS},
304 {"cdt", DAYZONE, 6 HRS},
305 {"c.d.t.", DAYZONE, 6 HRS},
306 {"mst", ZONE, 7 HRS}, /* Mountain */
307 {"m.s.t.", ZONE, 7 HRS},
308 {"mdt", DAYZONE, 7 HRS},
309 {"m.d.t.", DAYZONE, 7 HRS},
310 {"pst", ZONE, 8 HRS}, /* Pacific */
311 {"p.s.t.", ZONE, 8 HRS},
312 {"pdt", DAYZONE, 8 HRS},
313 {"p.d.t.", DAYZONE, 8 HRS},
314 {"yst", ZONE, 9 HRS}, /* Yukon */
315 {"y.s.t.", ZONE, 9 HRS},
316 {"ydt", DAYZONE, 9 HRS},
317 {"y.d.t.", DAYZONE, 9 HRS},
318 {"hst", ZONE, 10 HRS}, /* Hawaii */
319 {"h.s.t.", ZONE, 10 HRS},
320 {"hdt", DAYZONE, 10 HRS},
321 {"h.d.t.", DAYZONE, 10 HRS},
322 {"bst", ZONE, 11 HRS}, /* Bering */
323 {"b.s.t.", ZONE, 11 HRS},
324 {"bdt", DAYZONE, 11 HRS},
325 {"b.d.t.", DAYZONE, 11 HRS},
327 {"gmt", ZONE, 0 HRS},
328 {"g.m.t.", ZONE, 0 HRS},
330 {"aest", ZONE, -10 HRS}, /* Australian Eastern Time */
331 {"a.e.s.t.", ZONE, -10 HRS},
332 {"aesst", DAYZONE, -10 HRS}, /* Australian Eastern Summer Time */
333 {"a.e.s.s.t.", DAYZONE, -10 HRS},
334 {"acst", ZONE, -(9 HRS + HALFHR)}, /* Australian Central Time */
335 {"a.c.s.t.", ZONE, -(9 HRS + HALFHR)},
336 {"acsst", DAYZONE, -(9 HRS + HALFHR)}, /* Australian Central Summer */
337 {"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)},
338 {"awst", ZONE, -8 HRS}, /* Australian Western Time */
339 {"a.w.s.t.", ZONE, -8 HRS}, /* (no daylightsavings time there, I'm told */
342 struct table unittb[] = {
345 {"fortnight", UNIT, 14*24*60},
346 {"week", UNIT, 7*24*60},
347 {"day", UNIT, 1*24*60},
351 {"second", SUNIT, 1},
355 struct table othertb[] = {
356 {"tomorrow", UNIT, 1*24*60},
357 {"yesterday", UNIT, -1*24*60},
360 {"last", NUMBER, -1},
363 {"first", NUMBER, 1},
364 /* {"second", NUMBER, 2}, */
365 {"third", NUMBER, 3},
366 {"fourth", NUMBER, 4},
367 {"fifth", NUMBER, 5},
368 {"sixth", NUMBER, 6},
369 {"seventh", NUMBER, 7},
370 {"eighth", NUMBER, 8},
371 {"ninth", NUMBER, 9},
372 {"tenth", NUMBER, 10},
373 {"eleventh", NUMBER, 11},
374 {"twelfth", NUMBER, 12},
378 struct table milzone[] = {
400 {"w", ZONE, -10 HRS},
401 {"x", ZONE, -11 HRS},
402 {"y", ZONE, -12 HRS},
409 #define gotit (yylval=i->value, i->type)
410 #define getid for(j=idvar, k=id; (*j++ = *k++); )
418 if (strlen(idvar) == 3) abbrev = 1;
419 else if (strlen(idvar) == 4 && idvar[3] == '.') {
425 if (islower(*idvar)) *idvar = toupper(*idvar);
427 for (i = mdtab; i->name; i++) {
429 for (j = i->name; *j++ == *k++;) {
430 if (abbrev && j==i->name+3) return gotit;
431 if (j[-1] == 0) return gotit;
436 for (i = mztab; i->name; i++)
437 if (strcmp(i->name, idvar) == 0) return gotit;
439 for (j = idvar; *j; j++) if (isupper(*j)) *j = tolower(*j);
440 for (i=mztab; i->name; i++)
441 if (strcmp(i->name, idvar) == 0) return gotit;
444 for (i=unittb; i->name; i++)
445 if (strcmp(i->name, idvar) == 0) return gotit;
447 if (idvar[strlen(idvar)-1] == 's') idvar[strlen(idvar)-1] = '\0';
448 for (i=unittb; i->name; i++)
449 if (strcmp(i->name, idvar) == 0) return gotit;
452 for (i = othertb; i->name; i++)
453 if (strcmp(i->name, idvar) == 0) return gotit;
456 if (strlen(idvar) == 1 && isalpha(*idvar)) {
457 if (isupper(*idvar)) *idvar = tolower(*idvar);
458 for (i = milzone; i->name; i++)
459 if (strcmp(i->name, idvar) == 0) return gotit;
477 while (isspace(*lptr)) lptr++;
479 if (isdigit(c = *lptr) || c == '-' || c == '+') {
480 if (c== '-' || c == '+') {
481 if (c=='-') sign = -1;
483 if (!isdigit(*++lptr)) {
484 /* yylval = sign; return (NUMBER); */
485 return yylex(); /* skip the '-' sign */
489 while (isdigit(c = *lptr++)) yylval = 10*yylval + c - '0';
494 } else if (isalpha(c)) {
496 while (isalpha(c = *lptr++) || c=='.')
500 return (lookup(idbuf));
507 if (c == '\0') return(c);
508 else if (c == '(') pcnt++;
509 else if (c == ')') pcnt--;
513 else return (*lptr++);
518 time_t cm_getdate(char *p, struct timeb *now)
520 #define mcheck(f) if (f>1) err++
527 if (now == ((struct timeb *) NULL)) {
529 #if defined(SVR4) || defined(__OpenBSD__)
531 lt = localtime(&tod);
532 now->time = lt->tm_sec;
534 now->timezone = lt->tm_gmtoff / 60;
536 now->timezone = timezone/60;
543 lt = localtime(&now->time);
545 month = lt->tm_mon+1;
547 relsec = 0; relmonth = 0;
548 timeflag=zoneflag=dateflag=dayflag=relflag=0;
549 ourzone = now->timezone;
550 daylightsavings = MAYBE;
554 if ((err = yyparse())) return (-1);
561 if (err) return (-1);
563 /* Relflag also needs to set the sdate variable */
564 /* This fixes QAR 28447 */
565 if (dateflag || timeflag || dayflag || relflag) {
566 sdate = dateconv(month, day, year, hh, mm, ss, merid, ourzone,
568 if (sdate < 0) return(sdate);
570 if more than 6 months ago, then probably means
573 if (noyear && sdate < now->time - daysec*(365/2)) {
575 sdate = dateconv(month, day, year, hh, mm, ss,
576 merid, ourzone, daylightsavings);
582 sdate -= (lt->tm_sec + lt->tm_min*60 +
583 lt->tm_hour*(60L*60L));
587 sdate += monthadd(sdate, relmonth);
589 if (dayflag && !dateflag) {
590 tod = dayconv(dayord, dayreq, sdate);