day.c revision 13840
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. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 35#include <stdio.h> 36#include <sys/types.h> 37#include <time.h> 38#include <sys/uio.h> 39#include <string.h> 40#include <stdlib.h> 41 42#include "pathnames.h" 43#include "calendar.h" 44 45struct tm *tp; 46int *cumdays, offset, yrdays; 47char dayname[10]; 48 49 50/* 1-based month, 0-based days, cumulative */ 51int daytab[][14] = { 52 { 0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 }, 53 { 0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, 54}; 55 56static char *days[] = { 57 "sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL, 58}; 59 60static char *months[] = { 61 "jan", "feb", "mar", "apr", "may", "jun", 62 "jul", "aug", "sep", "oct", "nov", "dec", NULL, 63}; 64 65 66 67 68void 69settime(now) 70 time_t now; 71{ 72 73 tp = localtime(&now); 74 if ( isleap(tp->tm_year + 1900) ) { 75 yrdays = 366; 76 cumdays = daytab[1]; 77 } else { 78 yrdays = 365; 79 cumdays = daytab[0]; 80 } 81 /* Friday displays Monday's events */ 82 offset = tp->tm_wday == 5 ? 3 : 1; 83 header[5].iov_base = dayname; 84 header[5].iov_len = strftime(dayname, sizeof(dayname), "%A", tp); 85} 86 87/* convert Day[/Month][/Year] into unix time (since 1970) 88 * Day: tow digits, Month: two digits, Year: digits 89 */ 90time_t Mktime (date) 91 char *date; 92{ 93 time_t t; 94 int len; 95 struct tm tm; 96 97 (void)time(&t); 98 tp = localtime(&t); 99 100 len = strlen(date); 101 tm.tm_sec = 0; 102 tm.tm_min = 0; 103 tm.tm_hour = 0; 104 tm.tm_mday = tp->tm_mday; 105 tm.tm_mon = tp->tm_mon; 106 tm.tm_year = tp->tm_year; 107 108 109 /* day */ 110 *(date+2) = NULL; 111 tm.tm_mday = atoi(date); 112 113 /* month */ 114 if (len >= 4) { 115 *(date+5) = NULL; 116 tm.tm_mon = atoi(date+3) - 1; 117 } 118 119 /* Year */ 120 if (len >= 7) { 121 tm.tm_year = atoi(date+6); 122 123 /* tm_year up 1900 ... */ 124 if (tm.tm_year > 1900) 125 tm.tm_year -= 1900; 126 } 127 128#if DEBUG 129 printf("Mktime: %d %d %d %s\n", (int)mktime(&tm), (int)t, len, 130 asctime(&tm)); 131#endif 132 return(mktime(&tm)); 133} 134 135/* 136 * Possible date formats include any combination of: 137 * 3-charmonth (January, Jan, Jan) 138 * 3-charweekday (Friday, Monday, mon.) 139 * numeric month or day (1, 2, 04) 140 * 141 * Any character may separate them, or they may not be separated. Any line, 142 * following a line that is matched, that starts with "whitespace", is shown 143 * along with the matched line. 144 */ 145int 146isnow(endp) 147 char *endp; 148{ 149 int day, flags, month, v1, v2; 150 151 /* 152 * CONVENTION 153 * 154 * Month: 1-12 155 * Monthname: Jan .. Dec 156 * Day: 1-31 157 * Weekday: Mon-Sun 158 * 159 */ 160 161 flags = 0; 162 163 /* read first field */ 164 /* didn't recognize anything, skip it */ 165 if (!(v1 = getfield(endp, &endp, &flags))) 166 return (0); 167 168 /* Easter or Easter depending days */ 169 if (flags & F_EASTER) 170 day = v1; 171 172 /* 173 * 1. {Weekday,Day} XYZ ... 174 * 175 * where Day is > 12 176 */ 177 else if (flags & F_ISDAY || v1 > 12) { 178 179 /* found a day; day: 1-31 or weekday: 1-7 */ 180 day = v1; 181 182 /* {Day,Weekday} {Month,Monthname} ... */ 183 /* if no recognizable month, assume just a day alone 184 * in other words, find month or use current month */ 185 if (!(month = getfield(endp, &endp, &flags))) 186 month = tp->tm_mon + 1; 187 } 188 189 /* 2. {Monthname} XYZ ... */ 190 else if (flags & F_ISMONTH) { 191 month = v1; 192 193 /* Monthname {day,weekday} */ 194 /* if no recognizable day, assume the first day in month */ 195 if (!(day = getfield(endp, &endp, &flags))) 196 day = 1; 197 } 198 199 /* Hm ... */ 200 else { 201 v2 = getfield(endp, &endp, &flags); 202 203 /* 204 * {Day} {Monthname} ... 205 * where Day <= 12 206 */ 207 if (flags & F_ISMONTH) { 208 day = v1; 209 month = v2; 210 } 211 212 /* {Month} {Weekday,Day} ... */ 213 else { 214 /* F_ISDAY set, v2 > 12, or no way to tell */ 215 month = v1; 216 /* if no recognizable day, assume the first */ 217 day = v2 ? v2 : 1; 218 } 219 } 220 221 /* convert Weekday into *next* Day, 222 * e.g.: 'Sunday' -> 22 223 * 'SunayLast' -> ?? 224 */ 225 if (flags & F_ISDAY) { 226#if DEBUG 227 fprintf(stderr, "\nday: %d %s month %d\n", day, endp, month); 228#endif 229 230 /* variable weekday, SundayLast, MondayFirst ... */ 231 if (day < 0 || day >= 10) { 232 233 /* negative offset; last, -4 .. -1 */ 234 if (day < 0) { 235 v1 = day/10 - 1; /* offset -4 ... -1 */ 236 day = 10 + (day % 10); /* day 1 ... 7 */ 237 238 /* day, eg '22th' */ 239 v2 = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7); 240 241 /* (month length - day) / 7 + 1 */ 242 if (((int)((cumdays[month+1] - 243 cumdays[month] - v2) / 7) + 1) == -v1) 244 /* bingo ! */ 245 day = v2; 246 247 /* set to yesterday */ 248 else 249 day = tp->tm_mday - 1; 250 } 251 252 /* first, second ... +1 ... +5 */ 253 else { 254 v1 = day/10; /* offset: +1 (first Sunday) ... */ 255 day = day % 10; 256 257 /* day, eg '22th' */ 258 v2 = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7); 259 260 /* Hurrah! matched */ 261 if ( ((v2 - 1 + 7) / 7) == v1 ) 262 day = v2; 263 264 /* set to yesterday */ 265 else 266 day = tp->tm_mday - 1; 267 } 268 } 269 270 /* wired */ 271 else { 272 day = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7); 273 } 274 } 275 276#if DEBUG 277 fprintf(stderr, "day2: yday %d %d\n", day, tp->tm_yday); 278#endif 279 if (!(flags & F_EASTER)) 280 day = cumdays[month] + day; 281 282 /* if today or today + offset days */ 283 if (day >= tp->tm_yday - f_dayBefore && 284 day <= tp->tm_yday + offset + f_dayAfter) 285 return (1); 286 287 /* if number of days left in this year + days to event in next year */ 288 if (yrdays - tp->tm_yday + day <= offset + f_dayAfter || 289 /* a year backward, eg. 6 Jan and 10 days before -> 27. Dec */ 290 tp->tm_yday + day - f_dayBefore < 0 291 ) 292 return (1); 293 return (0); 294} 295 296 297int 298getmonth(s) 299 register char *s; 300{ 301 register char **p; 302 303 for (p = months; *p; ++p) 304 if (!strncasecmp(s, *p, 3)) 305 return ((p - months) + 1); 306 return (0); 307} 308 309 310int 311getday(s) 312 register char *s; 313{ 314 register char **p; 315 316 for (p = days; *p; ++p) 317 if (!strncasecmp(s, *p, 3)) 318 return ((p - days) + 1); 319 return (0); 320} 321 322/* return offset for variable weekdays 323 * -1 -> last weekday in month 324 * +1 -> first weekday in month 325 * ... etc ... 326 */ 327int 328getdayvar(s) 329 register char *s; 330{ 331 register int offset; 332 333 334 offset = strlen(s); 335 336 337 /* Sun+1 or Wednesday-2 338 * ^ ^ */ 339 340 /* printf ("x: %s %s %d\n", s, s + offset - 2, offset); */ 341 switch(*(s + offset - 2)) { 342 case '-': 343 return(-(atoi(s + offset - 1))); 344 break; 345 case '+': 346 return(atoi(s + offset - 1)); 347 break; 348 } 349 350 351 /* 352 * some aliases: last, first, second, third, fourth 353 */ 354 355 /* last */ 356 if (offset > 4 && !strcasecmp(s + offset - 4, "last")) 357 return(-1); 358 else if (offset > 5 && !strcasecmp(s + offset - 5, "first")) 359 return(+1); 360 else if (offset > 6 && !strcasecmp(s + offset - 6, "second")) 361 return(+2); 362 else if (offset > 5 && !strcasecmp(s + offset - 5, "third")) 363 return(+3); 364 else if (offset > 6 && !strcasecmp(s + offset - 6, "fourth")) 365 return(+4); 366 367 368 /* no offset detected */ 369 return(0); 370} 371