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>
55 #define daysec (24L*60L*60L)
56 static int timeflag, zoneflag, dateflag, dayflag, relflag;
57 static time_t relsec, relmonth;
58 static int hh, mm, ss, merid, daylightsavings;
59 static int dayord, dayreq;
60 static int month, day, year;
92 {if (timeflag && dateflag && !relflag) year = $1;
93 else {timeflag++;hh = $1/100;mm = $1%100;ss = 0;merid = 24;}};
95 tspec: NUMBER MERIDIAN
96 {hh = $1; mm = 0; ss = 0; merid = $2;}
98 {hh = $1; mm = $3; merid = 24;}
99 | NUMBER ':' NUMBER MERIDIAN
100 {hh = $1; mm = $3; merid = $4;}
101 | NUMBER ':' NUMBER ':' NUMBER
102 {hh = $1; mm = $3; ss = $5; merid = 24;}
103 | NUMBER ':' NUMBER ':' NUMBER MERIDIAN
104 {hh = $1; mm = $3; ss = $5; merid = $6;};
107 {ourzone = $1; daylightsavings = STANDARD;}
109 {ourzone = $1; daylightsavings = DAYLIGHT;};
112 {dayord = 1; dayreq = $1;}
114 {dayord = 1; dayreq = $1;}
116 {dayord = $1; dayreq = $2;};
118 dtspec: NUMBER '/' NUMBER
119 {month = $1; day = $3; noyear = 1;}
120 | NUMBER '/' NUMBER '/' NUMBER
121 {month = $1; day = $3; year = $5;}
123 {month = $1; day = $3; noyear = 1;}
124 | NUMBER '-' NUMBER '-' NUMBER
125 {month = $1; day = $3; year = $5;}
127 {month = $1; day = $2; noyear = 1;}
128 | MONTH NUMBER ',' NUMBER
129 {month = $1; day = $2; year = $4;}
131 {month = $2; day = $1; noyear = 1;}
132 | NUMBER MONTH NUMBER
133 {month = $2; day = $1; year = $3;};
137 {relsec += 60L * $1 * $2;}
139 {relmonth += $1 * $2;}
143 {relsec += 60L * $1;}
149 {relsec = -relsec; relmonth = -relmonth;};
152 static int mdays[12] =
153 {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
154 #define epoch BOT_YEAR
156 extern struct tm *localtime();
157 time_t dateconv(int mm,
170 if (yy < 0) yy = -yy;
177 mdays[1] = 28 + (yy%4 == 0);
185 if (mm < 1 || mm > 12)
188 if (dd < 1 || dd > mdays[--mm])
192 for (i=0; i<mm; i++) jdate += mdays[i];
193 for (i = epoch; i < yy; i++) jdate += 365 + (i%4 == 0);
196 if ((tod = timeconv(h, m, s, mer)) < 0) return (tod);
198 if (dayflag==DAYLIGHT || (dayflag==MAYBE&&localtime(&jdate)->tm_isdst))
203 time_t dayconv(int ord, int day, time_t now)
205 register struct tm *loctime;
209 loctime = localtime(&tod);
210 tod += daysec * ((day - loctime->tm_wday + 7) % 7);
211 tod += 7*daysec*(ord<=0?ord:ord-1);
212 return daylcorr(tod, now);
215 time_t timeconv(register int hh, int mm, int ss, int mer)
217 if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (DATE_BMIN);
219 case AM: if (hh < 1 || hh > 12) return(DATE_BHOUR);
220 return (60L * ((hh%12)*60L + mm)+ss);
221 case PM: if (hh < 1 || hh > 12) return(DATE_BHOUR);
222 return (60L * ((hh%12 +12)*60L + mm)+ss);
223 case 24: if (hh < 0 || hh > 23) return (DATE_BHOUR);
224 return (60L * (hh*60L + mm)+ss);
225 default: return (DATE_CONV);
228 time_t monthadd(time_t sdate, time_t relmonth)
233 if (relmonth == 0) return 0;
234 ltime = localtime(&sdate);
235 mm = 12*ltime->tm_year + ltime->tm_mon + relmonth;
238 return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour,
239 ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate);
242 time_t daylcorr(time_t future, time_t now)
246 nowdayl = (localtime(&now)->tm_hour+1) % 24;
247 fdayl = (localtime(&future)->tm_hour+1) % 24;
248 return (future-now) + 60L*60L*(nowdayl-fdayl);
256 struct table mdtab[] = {
257 {"January", MONTH, 1},
258 {"February", MONTH, 2},
264 {"August", MONTH, 8},
265 {"September", MONTH, 9},
267 {"October", MONTH, 10},
268 {"November", MONTH, 11},
269 {"December", MONTH, 12},
275 {"Wednesday", DAY, 3},
277 {"Thursday", DAY, 4},
281 {"Saturday", DAY, 6},
286 struct table mztab[] = {
287 {"a.m.", MERIDIAN, AM},
288 {"am", MERIDIAN, AM},
289 {"p.m.", MERIDIAN, PM},
290 {"pm", MERIDIAN, PM},
291 {"nst", ZONE, 3 HRS + HALFHR}, /* Newfoundland */
292 {"n.s.t.", ZONE, 3 HRS + HALFHR},
293 {"ast", ZONE, 4 HRS}, /* Atlantic */
294 {"a.s.t.", ZONE, 4 HRS},
295 {"adt", DAYZONE, 4 HRS},
296 {"a.d.t.", DAYZONE, 4 HRS},
297 {"est", ZONE, 5 HRS}, /* Eastern */
298 {"e.s.t.", ZONE, 5 HRS},
299 {"edt", DAYZONE, 5 HRS},
300 {"e.d.t.", DAYZONE, 5 HRS},
301 {"cst", ZONE, 6 HRS}, /* Central */
302 {"c.s.t.", ZONE, 6 HRS},
303 {"cdt", DAYZONE, 6 HRS},
304 {"c.d.t.", DAYZONE, 6 HRS},
305 {"mst", ZONE, 7 HRS}, /* Mountain */
306 {"m.s.t.", ZONE, 7 HRS},
307 {"mdt", DAYZONE, 7 HRS},
308 {"m.d.t.", DAYZONE, 7 HRS},
309 {"pst", ZONE, 8 HRS}, /* Pacific */
310 {"p.s.t.", ZONE, 8 HRS},
311 {"pdt", DAYZONE, 8 HRS},
312 {"p.d.t.", DAYZONE, 8 HRS},
313 {"yst", ZONE, 9 HRS}, /* Yukon */
314 {"y.s.t.", ZONE, 9 HRS},
315 {"ydt", DAYZONE, 9 HRS},
316 {"y.d.t.", DAYZONE, 9 HRS},
317 {"hst", ZONE, 10 HRS}, /* Hawaii */
318 {"h.s.t.", ZONE, 10 HRS},
319 {"hdt", DAYZONE, 10 HRS},
320 {"h.d.t.", DAYZONE, 10 HRS},
321 {"bst", ZONE, 11 HRS}, /* Bering */
322 {"b.s.t.", ZONE, 11 HRS},
323 {"bdt", DAYZONE, 11 HRS},
324 {"b.d.t.", DAYZONE, 11 HRS},
326 {"gmt", ZONE, 0 HRS},
327 {"g.m.t.", ZONE, 0 HRS},
329 {"aest", ZONE, -10 HRS}, /* Australian Eastern Time */
330 {"a.e.s.t.", ZONE, -10 HRS},
331 {"aesst", DAYZONE, -10 HRS}, /* Australian Eastern Summer Time */
332 {"a.e.s.s.t.", DAYZONE, -10 HRS},
333 {"acst", ZONE, -(9 HRS + HALFHR)}, /* Australian Central Time */
334 {"a.c.s.t.", ZONE, -(9 HRS + HALFHR)},
335 {"acsst", DAYZONE, -(9 HRS + HALFHR)}, /* Australian Central Summer */
336 {"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)},
337 {"awst", ZONE, -8 HRS}, /* Australian Western Time */
338 {"a.w.s.t.", ZONE, -8 HRS}, /* (no daylightsavings time there, I'm told */
341 struct table unittb[] = {
344 {"fortnight", UNIT, 14*24*60},
345 {"week", UNIT, 7*24*60},
346 {"day", UNIT, 1*24*60},
350 {"second", SUNIT, 1},
354 struct table othertb[] = {
355 {"tomorrow", UNIT, 1*24*60},
356 {"yesterday", UNIT, -1*24*60},
359 {"last", NUMBER, -1},
362 {"first", NUMBER, 1},
363 /* {"second", NUMBER, 2}, */
364 {"third", NUMBER, 3},
365 {"fourth", NUMBER, 4},
366 {"fifth", NUMBER, 5},
367 {"sixth", NUMBER, 6},
368 {"seventh", NUMBER, 7},
369 {"eighth", NUMBER, 8},
370 {"ninth", NUMBER, 9},
371 {"tenth", NUMBER, 10},
372 {"eleventh", NUMBER, 11},
373 {"twelfth", NUMBER, 12},
377 struct table milzone[] = {
399 {"w", ZONE, -10 HRS},
400 {"x", ZONE, -11 HRS},
401 {"y", ZONE, -12 HRS},
408 #define gotit (yylval=i->value, i->type)
409 #define getid for(j=idvar, k=id; *j++ = *k++; )
412 register char *j, *k;
413 register struct table *i;
417 if (strlen(idvar) == 3) abbrev = 1;
418 else if (strlen(idvar) == 4 && idvar[3] == '.') {
424 if (islower(*idvar)) *idvar = toupper(*idvar);
426 for (i = mdtab; i->name; i++) {
428 for (j = i->name; *j++ == *k++;) {
429 if (abbrev && j==i->name+3) return gotit;
430 if (j[-1] == 0) return gotit;
435 for (i = mztab; i->name; i++)
436 if (strcmp(i->name, idvar) == 0) return gotit;
438 for (j = idvar; *j; j++) if (isupper(*j)) *j = tolower(*j);
439 for (i=mztab; i->name; i++)
440 if (strcmp(i->name, idvar) == 0) return gotit;
443 for (i=unittb; i->name; i++)
444 if (strcmp(i->name, idvar) == 0) return gotit;
446 if (idvar[strlen(idvar)-1] == 's') idvar[strlen(idvar)-1] = '\0';
447 for (i=unittb; i->name; i++)
448 if (strcmp(i->name, idvar) == 0) return gotit;
451 for (i = othertb; i->name; i++)
452 if (strcmp(i->name, idvar) == 0) return gotit;
455 if (strlen(idvar) == 1 && isalpha(*idvar)) {
456 if (isupper(*idvar)) *idvar = tolower(*idvar);
457 for (i = milzone; i->name; i++)
458 if (strcmp(i->name, idvar) == 0) return gotit;
480 while (isspace(*lptr)) lptr++;
482 if (isdigit(c = *lptr) || c == '-' || c == '+') {
483 if (c== '-' || c == '+') {
484 if (c=='-') sign = -1;
486 if (!isdigit(*++lptr)) {
487 /* yylval = sign; return (NUMBER); */
488 return yylex(); /* skip the '-' sign */
492 while (isdigit(c = *lptr++)) yylval = 10*yylval + c - '0';
497 } else if (isalpha(c)) {
499 while (isalpha(c = *lptr++) || c=='.')
503 return (lookup(idbuf));
510 if (c == '\0') return(c);
511 else if (c == '(') pcnt++;
512 else if (c == ')') pcnt--;
516 else return (*lptr++);
521 time_t cm_getdate(char *p, struct timeb *now)
523 #define mcheck(f) if (f>1) err++
530 if (now == ((struct timeb *) NULL)) {
532 #if defined(SVR4) || defined(__OpenBSD__)
534 lt = localtime(&tod);
535 now->time = lt->tm_sec;
537 now->timezone = lt->tm_gmtoff / 60;
539 now->timezone = timezone/60;
546 lt = localtime(&now->time);
548 month = lt->tm_mon+1;
550 relsec = 0; relmonth = 0;
551 timeflag=zoneflag=dateflag=dayflag=relflag=0;
552 ourzone = now->timezone;
553 daylightsavings = MAYBE;
557 if (err = yyparse()) return (-1);
564 if (err) return (-1);
566 /* Relflag also needs to set the sdate variable */
567 /* This fixes QAR 28447 */
568 if (dateflag || timeflag || dayflag || relflag) {
569 sdate = dateconv(month, day, year, hh, mm, ss, merid, ourzone,
571 if (sdate < 0) return(sdate);
573 if more than 6 months ago, then probably means
576 if (noyear && sdate < now->time - daysec*(365/2)) {
578 sdate = dateconv(month, day, year, hh, mm, ss,
579 merid, ourzone, daylightsavings);
585 sdate -= (lt->tm_sec + lt->tm_min*60 +
586 lt->tm_hour*(60L*60L));
590 sdate += monthadd(sdate, relmonth);
592 if (dayflag && !dateflag) {
593 tod = dayconv(dayord, dayreq, sdate);