9 date 96.02.09.17.38.07; author jromine; state Exp;
14 date 96.02.09.17.32.07; author jromine; state Exp;
29 static char Id[] = "$Id:$";
38 ** prompt user for a date specification which can be quite minimal
39 ** and print it in a form suitable for parsing by MH
45 "Jan","Feb","Mar","Apr","May","Jun",
46 "Jul","Aug","Sep","Oct","Nov","Dec"};
48 "Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
51 int monthlen[2][12] ={
52 31,28,31,30,31,30,31,31,30,31,30,31,
53 31,29,31,30,31,30,31,31,30,31,30,31};
54 char *defaultformat = "%d %N %y 00:00";
62 extern int optind; /* defined in getopt */
63 extern char *optarg; /* defined in getopt */
67 while ((c = getopt (argc, argv, "f:")) != EOF)
72 defaultformat = optarg;
75 fprintf(stderr, "usage: %s [-f format] [datespec]\n", argv[0]);
82 finddate(&now, dayspast = (int)(secsfr70()/86400L));
84 if (argc <= 0) /* get from user */
86 if (!promptdate(&then))
88 printdate(&then, defaultformat);
90 else /* get from command line */
92 if (!decodedate(argv[0], &then))
94 printdate(&then, defaultformat);
108 fprintf(stderr, "When? ");
109 if (fgets(line, sizeof(line), stdin) == NULL)
111 fprintf(stderr, "\n");
114 p = line + strlen (line) - 1;
117 if (decodedate(line, when))
123 int decodedate(line, when)
127 ** accept spec for date in several forms
128 ** legal are: sun,mon,tue,wed,thu,fri,sat,today,tomorrow,
129 ** <date><month>,+<relative number of days>
130 ** <month> should be alpha
131 ** upper case accepted too
135 register int i,targetdate;
139 when->tm_year = now.tm_year;
140 when->tm_mon = now.tm_mon;
141 targetdate = dayspast;
142 for (lptr = line; isspace(*lptr); lptr++)
146 i = sscanf(lptr, "%d%3s%d", &when->tm_mday, s, &tem);
153 when->tm_mon = monthofyear(s);
156 if (when->tm_mday != 0 && when->tm_mon != 0 && daysfr70(when) < dayspast)
160 if (when->tm_mday != 0 && when->tm_mday < now.tm_mday)
162 if (++when->tm_mon > 12)
169 return (validate(when));
173 sscanf(lptr, "%3s", s);
175 if ((tem = dayofweek(s)) >= 0)
176 targetdate += (tem -= now.tm_wday) <= 0 ? tem + 7 : tem;
177 else if (strcmp(s, "Tom") == 0)
179 else if (strcmp(s, "Tod") == 0)
184 else if (*lptr == '+')
186 if (sscanf(++lptr, "%d", &tem) == 0 || tem < 0) /* mistake */
190 else /* mistake by default */
192 finddate(when, targetdate);
193 return (when->tm_mday != 0);
198 ** check that a given date and month combination is legal
199 ** datetm->tm_year must hold the year in question
201 register struct tm *datetm;
204 return (datetm->tm_mday <= monthlen[leapyear(datetm->tm_year)]
205 [datetm->tm_mon] && datetm->tm_mday > 0);
208 finddate(datetm, df70)
210 ** convert days from 1 jan 1970 to a date in struct datetm
213 register struct tm *datetm;
215 register struct tm *tdtm;
219 longtime = df70 * 86400L;
220 tdtm = gmtime(&longtime);
221 datetm->tm_yday = tdtm->tm_yday;
222 datetm->tm_wday = tdtm->tm_wday;
223 datetm->tm_year = tdtm->tm_year + 1900;
224 datetm->tm_mon = tdtm->tm_mon;
225 datetm->tm_mday = tdtm->tm_mday;
226 datetm->tm_hour = tdtm->tm_hour;
227 datetm->tm_min = tdtm->tm_min;
228 datetm->tm_sec = tdtm->tm_sec;
233 ** convert first character to uppercase
234 ** convert rest of string from uppercase to lower case
240 if ((c = *s) != '\0')
241 *s++ += islower(c) ? 'A' - 'a' : 0;
242 while ((c = *s) != '\0')
243 *s++ += isupper(c) ? 'a' - 'A' : 0;
248 ** returns 1 if leapyear 0 otherwise
253 return (((y % 4) == 0 && (y % 100) != 0) || (y % 400) == 0);
258 ** returns the number of days from 1 Jan 1970
259 ** no checking for illegal date at all
261 register struct tm *datetm;
263 register int i, totdays;
267 for (i = 1970; i <= 2050 && i < datetm->tm_year; i++) /* prevent overflow */
268 totdays += 365 + leapyear(i);
269 for (i = 0; i < 12 && i < datetm->tm_mon; i++)
270 totdays += monthlen[leapyear(datetm->tm_year)][i];
271 totdays += datetm->tm_mday - 1;
277 ** returns month of year in numeric form when given
278 ** the first three letters
285 for (i = 12; i-- && strcmp(s,mname[i]); )
292 ** sunday = 0,...,saturday = 6, nomatch = -1
299 for (i = 7; i-- && strcmp(s,dname[i]); )
304 printdate(date, format)
306 ** print date in MH acceptable format
307 ** kludge - general formats are not implemented
312 printf("%d %s %d 00:00\n",
313 date->tm_mday, mname[date->tm_mon], date->tm_year);
318 ** This is system dependent
324 struct tm *localtime();
326 gettimeofday(&tv, &tz);
327 dst = localtime(&tv.tv_sec)->tm_isdst;
328 return (tv.tv_sec - tz.tz_minuteswest * 60 + (dst ? 3600 : 0));
344 if (gets(line) == NULL)