Deleted Added
full compact
day.c (200470) day.c (205821)
1/*
1/*-
2 * Copyright (c) 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.

--- 17 unchanged lines hidden (view full) ---

27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
2 * Copyright (c) 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.

--- 17 unchanged lines hidden (view full) ---

27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/usr.bin/calendar/day.c 200470 2009-12-13 04:50:11Z delphij $");
35__FBSDID("$FreeBSD: head/usr.bin/calendar/day.c 205821 2010-03-29 06:49:20Z edwin $");
36
36
37#include <sys/types.h>
38#include <sys/uio.h>
39#include <ctype.h>
40#include <err.h>
41#include <locale.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <time.h>
46
47#include "calendar.h"
48
37#include <err.h>
38#include <locale.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <time.h>
43
44#include "calendar.h"
45
49struct tm *tp;
50static const struct tm tm0;
51int *cumdays, yrdays;
52char dayname[10];
46time_t time1, time2;
47const struct tm tm0;
48char dayname[100];
49int year1, year2;
53
54
50
51
55/* 1-based month, 0-based days, cumulative */
56int daytab[][14] = {
57 {0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364},
58 {0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
59};
60
61static char const *days[] = {
62 "sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL,
63};
64
65static const char *months[] = {
66 "jan", "feb", "mar", "apr", "may", "jun",
67 "jul", "aug", "sep", "oct", "nov", "dec", NULL,
68};
69
70static struct fixs fndays[8]; /* full national days names */
71static struct fixs ndays[8]; /* short national days names */
72
73static struct fixs fnmonths[13]; /* full national months names */
74static struct fixs nmonths[13]; /* short national month names */
75
76
77void
52void
78setnnames(void)
53settimes(time_t now, int before, int after, int friday, struct tm *tp1, struct tm *tp2)
79{
54{
80 char buf[80];
81 int i, l;
82 struct tm tm;
55 char *oldl, *lbufp;
56 struct tm tp;
83
57
84 for (i = 0; i < 7; i++) {
85 tm.tm_wday = i;
86 strftime(buf, sizeof(buf), "%a", &tm);
87 for (l = strlen(buf);
88 l > 0 && isspace((unsigned char)buf[l - 1]);
89 l--)
90 ;
91 buf[l] = '\0';
92 if (ndays[i].name != NULL)
93 free(ndays[i].name);
94 if ((ndays[i].name = strdup(buf)) == NULL)
95 errx(1, "cannot allocate memory");
96 ndays[i].len = strlen(buf);
58 localtime_r(&now, &tp);
97
59
98 strftime(buf, sizeof(buf), "%A", &tm);
99 for (l = strlen(buf);
100 l > 0 && isspace((unsigned char)buf[l - 1]);
101 l--)
102 ;
103 buf[l] = '\0';
104 if (fndays[i].name != NULL)
105 free(fndays[i].name);
106 if ((fndays[i].name = strdup(buf)) == NULL)
107 errx(1, "cannot allocate memory");
108 fndays[i].len = strlen(buf);
109 }
60 /* Friday displays Monday's events */
61 if (after == 0 && before == 0 && friday != -1)
62 after = tp.tm_wday == friday ? 3 : 1;
110
63
111 for (i = 0; i < 12; i++) {
112 tm.tm_mon = i;
113 strftime(buf, sizeof(buf), "%b", &tm);
114 for (l = strlen(buf);
115 l > 0 && isspace((unsigned char)buf[l - 1]);
116 l--)
117 ;
118 buf[l] = '\0';
119 if (nmonths[i].name != NULL)
120 free(nmonths[i].name);
121 if ((nmonths[i].name = strdup(buf)) == NULL)
122 errx(1, "cannot allocate memory");
123 nmonths[i].len = strlen(buf);
64 time1 = now - SECSPERDAY * before;
65 localtime_r(&time1, tp1);
66 year1 = 1900 + tp1->tm_year;
67 time2 = now + SECSPERDAY * after;
68 localtime_r(&time2, tp2);
69 year2 = 1900 + tp2->tm_year;
124
70
125 strftime(buf, sizeof(buf), "%B", &tm);
126 for (l = strlen(buf);
127 l > 0 && isspace((unsigned char)buf[l - 1]);
128 l--)
129 ;
130 buf[l] = '\0';
131 if (fnmonths[i].name != NULL)
132 free(fnmonths[i].name);
133 if ((fnmonths[i].name = strdup(buf)) == NULL)
134 errx(1, "cannot allocate memory");
135 fnmonths[i].len = strlen(buf);
136 }
137}
71 strftime(dayname, sizeof(dayname) - 1, "%A, %d %B %Y", tp1);
138
72
139void
140settime(time_t now)
141{
142 char *oldl, *lbufp;
143
144 tp = localtime(&now);
145 if (isleap(tp->tm_year + 1900)) {
146 yrdays = 366;
147 cumdays = daytab[1];
148 } else {
149 yrdays = 365;
150 cumdays = daytab[0];
151 }
152 /* Friday displays Monday's events */
153 if (f_dayAfter == 0 && f_dayBefore == 0 && Friday != -1)
154 f_dayAfter = tp->tm_wday == Friday ? 3 : 1;
155 header[5].iov_base = dayname;
156
157 oldl = NULL;
158 lbufp = setlocale(LC_TIME, NULL);
159 if (lbufp != NULL && (oldl = strdup(lbufp)) == NULL)
160 errx(1, "cannot allocate memory");
161 (void)setlocale(LC_TIME, "C");
73 oldl = NULL;
74 lbufp = setlocale(LC_TIME, NULL);
75 if (lbufp != NULL && (oldl = strdup(lbufp)) == NULL)
76 errx(1, "cannot allocate memory");
77 (void)setlocale(LC_TIME, "C");
162 header[5].iov_len = strftime(dayname, sizeof(dayname), "%A", tp);
163 (void)setlocale(LC_TIME, (oldl != NULL ? oldl : ""));
164 if (oldl != NULL)
165 free(oldl);
166
167 setnnames();
168}
169
170/* convert Day[/Month][/Year] into unix time (since 1970)
171 * Day: two digits, Month: two digits, Year: digits
172 */
173time_t
174Mktime(char *dp)
175{
176 time_t t;
177 int d, m, y;
78 (void)setlocale(LC_TIME, (oldl != NULL ? oldl : ""));
79 if (oldl != NULL)
80 free(oldl);
81
82 setnnames();
83}
84
85/* convert Day[/Month][/Year] into unix time (since 1970)
86 * Day: two digits, Month: two digits, Year: digits
87 */
88time_t
89Mktime(char *dp)
90{
91 time_t t;
92 int d, m, y;
178 struct tm tm;
93 struct tm tm, tp;
179
180 (void)time(&t);
94
95 (void)time(&t);
181 tp = localtime(&t);
96 localtime_r(&t, &tp);
182
183 tm = tm0;
97
98 tm = tm0;
184 tm.tm_mday = tp->tm_mday;
185 tm.tm_mon = tp->tm_mon;
186 tm.tm_year = tp->tm_year;
99 tm.tm_mday = tp.tm_mday;
100 tm.tm_mon = tp.tm_mon;
101 tm.tm_year = tp.tm_year;
187
188 switch (sscanf(dp, "%d.%d.%d", &d, &m, &y)) {
189 case 3:
190 if (y > 1900)
191 y -= 1900;
192 tm.tm_year = y;
193 /* FALLTHROUGH */
194 case 2:

--- 4 unchanged lines hidden (view full) ---

199 }
200
201#ifdef DEBUG
202 fprintf(stderr, "Mktime: %d %d %s\n",
203 (int)mktime(&tm), (int)t, asctime(&tm));
204#endif
205 return (mktime(&tm));
206}
102
103 switch (sscanf(dp, "%d.%d.%d", &d, &m, &y)) {
104 case 3:
105 if (y > 1900)
106 y -= 1900;
107 tm.tm_year = y;
108 /* FALLTHROUGH */
109 case 2:

--- 4 unchanged lines hidden (view full) ---

114 }
115
116#ifdef DEBUG
117 fprintf(stderr, "Mktime: %d %d %s\n",
118 (int)mktime(&tm), (int)t, asctime(&tm));
119#endif
120 return (mktime(&tm));
121}
207
208/*
209 * Possible date formats include any combination of:
210 * 3-charmonth (January, Jan, Jan)
211 * 3-charweekday (Friday, Monday, mon.)
212 * numeric month or day (1, 2, 04)
213 *
214 * Any character may separate them, or they may not be separated. Any line,
215 * following a line that is matched, that starts with "whitespace", is shown
216 * along with the matched line.
217 */
218int
219isnow(char *endp, int *monthp, int *dayp, int *varp)
220{
221 int day, flags, month = 0, v1, v2;
222
223 /*
224 * CONVENTION
225 *
226 * Month: 1-12
227 * Monthname: Jan .. Dec
228 * Day: 1-31
229 * Weekday: Mon-Sun
230 *
231 */
232
233 flags = 0;
234
235 /* read first field */
236 /* didn't recognize anything, skip it */
237 if (!(v1 = getfield(endp, &endp, &flags)))
238 return (0);
239
240 /* Easter or Easter depending days */
241 if (flags & F_EASTER)
242 day = v1 - 1; /* days since January 1 [0-365] */
243
244 /*
245 * 1. {Weekday,Day} XYZ ...
246 *
247 * where Day is > 12
248 */
249 else if (flags & F_ISDAY || v1 > 12) {
250
251 /* found a day; day: 1-31 or weekday: 1-7 */
252 day = v1;
253
254 /* {Day,Weekday} {Month,Monthname} ... */
255 /* if no recognizable month, assume just a day alone
256 * in other words, find month or use current month */
257 if (!(month = getfield(endp, &endp, &flags)))
258 month = tp->tm_mon + 1;
259 }
260
261 /* 2. {Monthname} XYZ ... */
262 else if (flags & F_ISMONTH) {
263 month = v1;
264
265 /* Monthname {day,weekday} */
266 /* if no recognizable day, assume the first day in month */
267 if (!(day = getfield(endp, &endp, &flags)))
268 day = 1;
269 }
270
271 /* Hm ... */
272 else {
273 v2 = getfield(endp, &endp, &flags);
274
275 /*
276 * {Day} {Monthname} ...
277 * where Day <= 12
278 */
279 if (flags & F_ISMONTH) {
280 day = v1;
281 month = v2;
282 *varp = 0;
283 }
284
285 /* {Month} {Weekday,Day} ... */
286 else {
287 /* F_ISDAY set, v2 > 12, or no way to tell */
288 month = v1;
289 /* if no recognizable day, assume the first */
290 day = v2 ? v2 : 1;
291 *varp = 0;
292 }
293 }
294
295 /* convert Weekday into *next* Day,
296 * e.g.: 'Sunday' -> 22
297 * 'SundayLast' -> ??
298 */
299 if (flags & F_ISDAY) {
300#ifdef DEBUG
301 fprintf(stderr, "\nday: %d %s month %d\n", day, endp, month);
302#endif
303
304 *varp = 1;
305 /* variable weekday, SundayLast, MondayFirst ... */
306 if (day < 0 || day >= 10) {
307
308 /* negative offset; last, -4 .. -1 */
309 if (day < 0) {
310 v1 = day / 10 - 1; /* offset -4 ... -1 */
311 day = 10 + (day % 10); /* day 1 ... 7 */
312
313 /* day, eg '22nd' */
314 v2 = tp->tm_mday +
315 (((day - 1) - tp->tm_wday + 7) % 7);
316
317 /* (month length - day) / 7 + 1 */
318 if (cumdays[month + 1] - cumdays[month] >= v2
319 && ((int)((cumdays[month + 1] -
320 cumdays[month] - v2) / 7) + 1) == -v1)
321 day = v2; /* bingo ! */
322
323 /* set to yesterday */
324 else {
325 day = tp->tm_mday - 1;
326 if (day == 0)
327 return (0);
328 }
329 }
330
331 /* first, second ... +1 ... +5 */
332 else {
333 /* offset: +1 (first Sunday) ... */
334 v1 = day / 10;
335 day = day % 10;
336
337 /* day, eg '22th' */
338 v2 = tp->tm_mday +
339 (((day - 1) - tp->tm_wday + 7) % 7);
340
341 /* Hurrah! matched */
342 if (((v2 - 1 + 7) / 7) == v1 )
343 day = v2;
344
345 else {
346 /* set to yesterday */
347 day = tp->tm_mday - 1;
348 if (day == 0)
349 return (0);
350 }
351 }
352 } else {
353 /* wired */
354 day = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7);
355 *varp = 1;
356 }
357 }
358
359 if (!(flags & F_EASTER)) {
360 if (day + cumdays[month] > cumdays[month + 1]) {
361 /* off end of month, adjust */
362 day -= (cumdays[month + 1] - cumdays[month]);
363 /* next year */
364 if (++month > 12)
365 month = 1;
366 }
367 *monthp = month;
368 *dayp = day;
369 day = cumdays[month] + day;
370 } else {
371 for (v1 = 0; day > cumdays[v1]; v1++)
372 ;
373 *monthp = v1 - 1;
374 *dayp = day - cumdays[v1 - 1];
375 *varp = 1;
376 }
377
378#ifdef DEBUG
379 fprintf(stderr, "day2: day %d(%d-%d) yday %d\n",
380 *dayp, day, cumdays[month], tp->tm_yday);
381#endif
382
383 /* When days before or days after is specified */
384 /* no year rollover */
385 if (day >= tp->tm_yday - f_dayBefore &&
386 day <= tp->tm_yday + f_dayAfter)
387 return (1);
388
389 /* next year */
390 if (tp->tm_yday + f_dayAfter >= yrdays) {
391 int end = tp->tm_yday + f_dayAfter - yrdays;
392 if (day <= end)
393 return (1);
394 }
395
396 /* previous year */
397 if (tp->tm_yday - f_dayBefore < 0) {
398 int before = yrdays + (tp->tm_yday - f_dayBefore);
399 if (day >= before)
400 return (1);
401 }
402
403 return (0);
404}
405
406
407int
408getmonth(char *s)
409{
410 const char **p;
411 struct fixs *n;
412
413 for (n = fnmonths; n->name; ++n)
414 if (!strncasecmp(s, n->name, n->len))
415 return ((n - fnmonths) + 1);
416 for (n = nmonths; n->name; ++n)
417 if (!strncasecmp(s, n->name, n->len))
418 return ((n - nmonths) + 1);
419 for (p = months; *p; ++p)
420 if (!strncasecmp(s, *p, 3))
421 return ((p - months) + 1);
422 return (0);
423}
424
425
426int
427getday(char *s)
428{
429 const char **p;
430 struct fixs *n;
431
432 for (n = fndays; n->name; ++n)
433 if (!strncasecmp(s, n->name, n->len))
434 return ((n - fndays) + 1);
435 for (n = ndays; n->name; ++n)
436 if (!strncasecmp(s, n->name, n->len))
437 return ((n - ndays) + 1);
438 for (p = days; *p; ++p)
439 if (!strncasecmp(s, *p, 3))
440 return ((p - days) + 1);
441 return (0);
442}
443
444/* return offset for variable weekdays
445 * -1 -> last weekday in month
446 * +1 -> first weekday in month
447 * ... etc ...
448 */
449int
450getdayvar(char *s)
451{
452 int offs;
453
454 offs = strlen(s);
455
456 /* Sun+1 or Wednesday-2
457 * ^ ^ */
458
459 /* fprintf(stderr, "x: %s %s %d\n", s, s + offs - 2, offs); */
460 switch (*(s + offs - 2)) {
461 case '-':
462 return (-(atoi(s + offs - 1)));
463 case '+':
464 return (atoi(s + offs - 1));
465 }
466
467 /*
468 * some aliases: last, first, second, third, fourth
469 */
470
471 /* last */
472 if (offs > 4 && !strcasecmp(s + offs - 4, "last"))
473 return (-1);
474 else if (offs > 5 && !strcasecmp(s + offs - 5, "first"))
475 return (+1);
476 else if (offs > 6 && !strcasecmp(s + offs - 6, "second"))
477 return (+2);
478 else if (offs > 5 && !strcasecmp(s + offs - 5, "third"))
479 return (+3);
480 else if (offs > 6 && !strcasecmp(s + offs - 6, "fourth"))
481 return (+4);
482
483 /* no offset detected */
484 return (0);
485}