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 static char sccsid[] = "@(#)getdate.y 1.10 94/11/07 Copyr 1993 Sun Microsystems, Inc.";
35 %token ID MONTH DAY MERIDIAN NUMBER UNIT MUNIT SUNIT ZONE DAYZONE AGO
37 /* Steven M. Bellovin (unc!smb) */
38 /* Dept. of Computer Science */
39 /* University of North Carolina at Chapel Hill */
40 /* @(#)getdate.y 2.6 4/20/84 */
42 #include <EUSCompat.h>
54 #define daysec (24L*60L*60L)
55 static int timeflag, zoneflag, dateflag, dayflag, relflag;
56 static time_t relsec, relmonth;
57 static int hh, mm, ss, merid, daylightsavings;
58 static int dayord, dayreq;
59 static int month, day, year;
91 {if (timeflag && dateflag && !relflag) year = $1;
92 else {timeflag++;hh = $1/100;mm = $1%100;ss = 0;merid = 24;}};
94 tspec: NUMBER MERIDIAN
95 {hh = $1; mm = 0; ss = 0; merid = $2;}
97 {hh = $1; mm = $3; merid = 24;}
98 | NUMBER ':' NUMBER MERIDIAN
99 {hh = $1; mm = $3; merid = $4;}
100 | NUMBER ':' NUMBER ':' NUMBER
101 {hh = $1; mm = $3; ss = $5; merid = 24;}
102 | NUMBER ':' NUMBER ':' NUMBER MERIDIAN
103 {hh = $1; mm = $3; ss = $5; merid = $6;};
106 {ourzone = $1; daylightsavings = STANDARD;}
108 {ourzone = $1; daylightsavings = DAYLIGHT;};
111 {dayord = 1; dayreq = $1;}
113 {dayord = 1; dayreq = $1;}
115 {dayord = $1; dayreq = $2;};
117 dtspec: NUMBER '/' NUMBER
118 {month = $1; day = $3; noyear = 1;}
119 | NUMBER '/' NUMBER '/' NUMBER
120 {month = $1; day = $3; year = $5;}
122 {month = $1; day = $3; noyear = 1;}
123 | NUMBER '-' NUMBER '-' NUMBER
124 {month = $1; day = $3; year = $5;}
126 {month = $1; day = $2; noyear = 1;}
127 | MONTH NUMBER ',' NUMBER
128 {month = $1; day = $2; year = $4;}
130 {month = $2; day = $1; noyear = 1;}
131 | NUMBER MONTH NUMBER
132 {month = $2; day = $1; year = $3;};
136 {relsec += 60L * $1 * $2;}
138 {relmonth += $1 * $2;}
142 {relsec += 60L * $1;}
148 {relsec = -relsec; relmonth = -relmonth;};
151 static int mdays[12] =
152 {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
153 #define epoch BOT_YEAR
155 extern struct tm *localtime();
156 time_t dateconv(int mm,
169 if (yy < 0) yy = -yy;
176 mdays[1] = 28 + (yy%4 == 0);
184 if (mm < 1 || mm > 12)
187 if (dd < 1 || dd > mdays[--mm])
191 for (i=0; i<mm; i++) jdate += mdays[i];
192 for (i = epoch; i < yy; i++) jdate += 365 + (i%4 == 0);
195 if ((tod = timeconv(h, m, s, mer)) < 0) return (tod);
197 if (dayflag==DAYLIGHT || (dayflag==MAYBE&&localtime(&jdate)->tm_isdst))
202 time_t dayconv(int ord, int day, time_t now)
204 register struct tm *loctime;
208 loctime = localtime(&tod);
209 tod += daysec * ((day - loctime->tm_wday + 7) % 7);
210 tod += 7*daysec*(ord<=0?ord:ord-1);
211 return daylcorr(tod, now);
214 time_t timeconv(register int hh, int mm, int ss, int mer)
216 if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (DATE_BMIN);
218 case AM: if (hh < 1 || hh > 12) return(DATE_BHOUR);
219 return (60L * ((hh%12)*60L + mm)+ss);
220 case PM: if (hh < 1 || hh > 12) return(DATE_BHOUR);
221 return (60L * ((hh%12 +12)*60L + mm)+ss);
222 case 24: if (hh < 0 || hh > 23) return (DATE_BHOUR);
223 return (60L * (hh*60L + mm)+ss);
224 default: return (DATE_CONV);
227 time_t monthadd(time_t sdate, time_t relmonth)
232 if (relmonth == 0) return 0;
233 ltime = localtime(&sdate);
234 mm = 12*ltime->tm_year + ltime->tm_mon + relmonth;
237 return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour,
238 ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate);
241 time_t daylcorr(time_t future, time_t now)
245 nowdayl = (localtime(&now)->tm_hour+1) % 24;
246 fdayl = (localtime(&future)->tm_hour+1) % 24;
247 return (future-now) + 60L*60L*(nowdayl-fdayl);
255 struct table mdtab[] = {
256 {"January", MONTH, 1},
257 {"February", MONTH, 2},
263 {"August", MONTH, 8},
264 {"September", MONTH, 9},
266 {"October", MONTH, 10},
267 {"November", MONTH, 11},
268 {"December", MONTH, 12},
274 {"Wednesday", DAY, 3},
276 {"Thursday", DAY, 4},
280 {"Saturday", DAY, 6},
285 struct table mztab[] = {
286 {"a.m.", MERIDIAN, AM},
287 {"am", MERIDIAN, AM},
288 {"p.m.", MERIDIAN, PM},
289 {"pm", MERIDIAN, PM},
290 {"nst", ZONE, 3 HRS + HALFHR}, /* Newfoundland */
291 {"n.s.t.", ZONE, 3 HRS + HALFHR},
292 {"ast", ZONE, 4 HRS}, /* Atlantic */
293 {"a.s.t.", ZONE, 4 HRS},
294 {"adt", DAYZONE, 4 HRS},
295 {"a.d.t.", DAYZONE, 4 HRS},
296 {"est", ZONE, 5 HRS}, /* Eastern */
297 {"e.s.t.", ZONE, 5 HRS},
298 {"edt", DAYZONE, 5 HRS},
299 {"e.d.t.", DAYZONE, 5 HRS},
300 {"cst", ZONE, 6 HRS}, /* Central */
301 {"c.s.t.", ZONE, 6 HRS},
302 {"cdt", DAYZONE, 6 HRS},
303 {"c.d.t.", DAYZONE, 6 HRS},
304 {"mst", ZONE, 7 HRS}, /* Mountain */
305 {"m.s.t.", ZONE, 7 HRS},
306 {"mdt", DAYZONE, 7 HRS},
307 {"m.d.t.", DAYZONE, 7 HRS},
308 {"pst", ZONE, 8 HRS}, /* Pacific */
309 {"p.s.t.", ZONE, 8 HRS},
310 {"pdt", DAYZONE, 8 HRS},
311 {"p.d.t.", DAYZONE, 8 HRS},
312 {"yst", ZONE, 9 HRS}, /* Yukon */
313 {"y.s.t.", ZONE, 9 HRS},
314 {"ydt", DAYZONE, 9 HRS},
315 {"y.d.t.", DAYZONE, 9 HRS},
316 {"hst", ZONE, 10 HRS}, /* Hawaii */
317 {"h.s.t.", ZONE, 10 HRS},
318 {"hdt", DAYZONE, 10 HRS},
319 {"h.d.t.", DAYZONE, 10 HRS},
320 {"bst", ZONE, 11 HRS}, /* Bering */
321 {"b.s.t.", ZONE, 11 HRS},
322 {"bdt", DAYZONE, 11 HRS},
323 {"b.d.t.", DAYZONE, 11 HRS},
325 {"gmt", ZONE, 0 HRS},
326 {"g.m.t.", ZONE, 0 HRS},
328 {"aest", ZONE, -10 HRS}, /* Australian Eastern Time */
329 {"a.e.s.t.", ZONE, -10 HRS},
330 {"aesst", DAYZONE, -10 HRS}, /* Australian Eastern Summer Time */
331 {"a.e.s.s.t.", DAYZONE, -10 HRS},
332 {"acst", ZONE, -(9 HRS + HALFHR)}, /* Australian Central Time */
333 {"a.c.s.t.", ZONE, -(9 HRS + HALFHR)},
334 {"acsst", DAYZONE, -(9 HRS + HALFHR)}, /* Australian Central Summer */
335 {"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)},
336 {"awst", ZONE, -8 HRS}, /* Australian Western Time */
337 {"a.w.s.t.", ZONE, -8 HRS}, /* (no daylightsavings time there, I'm told */
340 struct table unittb[] = {
343 {"fortnight", UNIT, 14*24*60},
344 {"week", UNIT, 7*24*60},
345 {"day", UNIT, 1*24*60},
349 {"second", SUNIT, 1},
353 struct table othertb[] = {
354 {"tomorrow", UNIT, 1*24*60},
355 {"yesterday", UNIT, -1*24*60},
358 {"last", NUMBER, -1},
361 {"first", NUMBER, 1},
362 /* {"second", NUMBER, 2}, */
363 {"third", NUMBER, 3},
364 {"fourth", NUMBER, 4},
365 {"fifth", NUMBER, 5},
366 {"sixth", NUMBER, 6},
367 {"seventh", NUMBER, 7},
368 {"eighth", NUMBER, 8},
369 {"ninth", NUMBER, 9},
370 {"tenth", NUMBER, 10},
371 {"eleventh", NUMBER, 11},
372 {"twelfth", NUMBER, 12},
376 struct table milzone[] = {
398 {"w", ZONE, -10 HRS},
399 {"x", ZONE, -11 HRS},
400 {"y", ZONE, -12 HRS},
407 #define gotit (yylval=i->value, i->type)
408 #define getid for(j=idvar, k=id; *j++ = *k++; )
411 register char *j, *k;
412 register struct table *i;
416 if (strlen(idvar) == 3) abbrev = 1;
417 else if (strlen(idvar) == 4 && idvar[3] == '.') {
423 if (islower(*idvar)) *idvar = toupper(*idvar);
425 for (i = mdtab; i->name; i++) {
427 for (j = i->name; *j++ == *k++;) {
428 if (abbrev && j==i->name+3) return gotit;
429 if (j[-1] == 0) return gotit;
434 for (i = mztab; i->name; i++)
435 if (strcmp(i->name, idvar) == 0) return gotit;
437 for (j = idvar; *j; j++) if (isupper(*j)) *j = tolower(*j);
438 for (i=mztab; i->name; i++)
439 if (strcmp(i->name, idvar) == 0) return gotit;
442 for (i=unittb; i->name; i++)
443 if (strcmp(i->name, idvar) == 0) return gotit;
445 if (idvar[strlen(idvar)-1] == 's') idvar[strlen(idvar)-1] = '\0';
446 for (i=unittb; i->name; i++)
447 if (strcmp(i->name, idvar) == 0) return gotit;
450 for (i = othertb; i->name; i++)
451 if (strcmp(i->name, idvar) == 0) return gotit;
454 if (strlen(idvar) == 1 && isalpha(*idvar)) {
455 if (isupper(*idvar)) *idvar = tolower(*idvar);
456 for (i = milzone; i->name; i++)
457 if (strcmp(i->name, idvar) == 0) return gotit;
479 while (isspace(*lptr)) lptr++;
481 if (isdigit(c = *lptr) || c == '-' || c == '+') {
482 if (c== '-' || c == '+') {
483 if (c=='-') sign = -1;
485 if (!isdigit(*++lptr)) {
486 /* yylval = sign; return (NUMBER); */
487 return yylex(); /* skip the '-' sign */
491 while (isdigit(c = *lptr++)) yylval = 10*yylval + c - '0';
496 } else if (isalpha(c)) {
498 while (isalpha(c = *lptr++) || c=='.')
502 return (lookup(idbuf));
509 if (c == '\0') return(c);
510 else if (c == '(') pcnt++;
511 else if (c == ')') pcnt--;
515 else return (*lptr++);
520 time_t cm_getdate(char *p, struct timeb *now)
522 #define mcheck(f) if (f>1) err++
529 if (now == ((struct timeb *) NULL)) {
531 #if defined(SVR4) || defined(__OpenBSD__)
533 lt = localtime(&tod);
534 now->time = lt->tm_sec;
536 now->timezone = lt->tm_gmtoff / 60;
538 now->timezone = timezone/60;
545 lt = localtime(&now->time);
547 month = lt->tm_mon+1;
549 relsec = 0; relmonth = 0;
550 timeflag=zoneflag=dateflag=dayflag=relflag=0;
551 ourzone = now->timezone;
552 daylightsavings = MAYBE;
556 if (err = yyparse()) return (-1);
563 if (err) return (-1);
565 /* Relflag also needs to set the sdate variable */
566 /* This fixes QAR 28447 */
567 if (dateflag || timeflag || dayflag || relflag) {
568 sdate = dateconv(month, day, year, hh, mm, ss, merid, ourzone,
570 if (sdate < 0) return(sdate);
572 if more than 6 months ago, then probably means
575 if (noyear && sdate < now->time - daysec*(365/2)) {
577 sdate = dateconv(month, day, year, hh, mm, ss,
578 merid, ourzone, daylightsavings);
584 sdate -= (lt->tm_sec + lt->tm_min*60 +
585 lt->tm_hour*(60L*60L));
589 sdate += monthadd(sdate, relmonth);
591 if (dayflag && !dateflag) {
592 tod = dayconv(dayord, dayreq, sdate);