day.c revision 15066
113840Swosch/* 213840Swosch * Copyright (c) 1989, 1993, 1994 313840Swosch * The Regents of the University of California. All rights reserved. 413840Swosch * 513840Swosch * Redistribution and use in source and binary forms, with or without 613840Swosch * modification, are permitted provided that the following conditions 713840Swosch * are met: 813840Swosch * 1. Redistributions of source code must retain the above copyright 913840Swosch * notice, this list of conditions and the following disclaimer. 1013840Swosch * 2. Redistributions in binary form must reproduce the above copyright 1113840Swosch * notice, this list of conditions and the following disclaimer in the 1213840Swosch * documentation and/or other materials provided with the distribution. 1313840Swosch * 3. All advertising materials mentioning features or use of this software 1413840Swosch * must display the following acknowledgement: 1513840Swosch * This product includes software developed by the University of 1613840Swosch * California, Berkeley and its contributors. 1713840Swosch * 4. Neither the name of the University nor the names of its contributors 1813840Swosch * may be used to endorse or promote products derived from this software 1913840Swosch * without specific prior written permission. 2013840Swosch * 2113840Swosch * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2213840Swosch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2313840Swosch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2413840Swosch * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2513840Swosch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2613840Swosch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2713840Swosch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2813840Swosch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2913840Swosch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3013840Swosch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3113840Swosch * SUCH DAMAGE. 3213840Swosch */ 3313840Swosch 3413840Swosch 3513840Swosch#include <stdio.h> 3613840Swosch#include <sys/types.h> 3713840Swosch#include <time.h> 3813840Swosch#include <sys/uio.h> 3913840Swosch#include <string.h> 4013840Swosch#include <stdlib.h> 4113840Swosch 4213840Swosch#include "pathnames.h" 4313840Swosch#include "calendar.h" 4413840Swosch 4513840Swoschstruct tm *tp; 4613840Swoschint *cumdays, offset, yrdays; 4713840Swoschchar dayname[10]; 4813840Swosch 4913840Swosch 5013840Swosch/* 1-based month, 0-based days, cumulative */ 5113840Swoschint daytab[][14] = { 5213840Swosch { 0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 }, 5313840Swosch { 0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, 5413840Swosch}; 5513840Swosch 5613840Swoschstatic char *days[] = { 5713840Swosch "sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL, 5813840Swosch}; 5913840Swosch 6013840Swoschstatic char *months[] = { 6113840Swosch "jan", "feb", "mar", "apr", "may", "jun", 6213840Swosch "jul", "aug", "sep", "oct", "nov", "dec", NULL, 6313840Swosch}; 6413840Swosch 6513840Swosch 6613840Swosch 6713840Swosch 6813840Swoschvoid 6913840Swoschsettime(now) 7013840Swosch time_t now; 7113840Swosch{ 7213840Swosch 7313840Swosch tp = localtime(&now); 7413840Swosch if ( isleap(tp->tm_year + 1900) ) { 7513840Swosch yrdays = 366; 7613840Swosch cumdays = daytab[1]; 7713840Swosch } else { 7813840Swosch yrdays = 365; 7913840Swosch cumdays = daytab[0]; 8013840Swosch } 8113840Swosch /* Friday displays Monday's events */ 8213840Swosch offset = tp->tm_wday == 5 ? 3 : 1; 8313840Swosch header[5].iov_base = dayname; 8413840Swosch header[5].iov_len = strftime(dayname, sizeof(dayname), "%A", tp); 8513840Swosch} 8613840Swosch 8713840Swosch/* convert Day[/Month][/Year] into unix time (since 1970) 8815066Smpp * Day: two digits, Month: two digits, Year: digits 8913840Swosch */ 9013840Swoschtime_t Mktime (date) 9113840Swosch char *date; 9213840Swosch{ 9313840Swosch time_t t; 9413840Swosch int len; 9513840Swosch struct tm tm; 9613840Swosch 9713840Swosch (void)time(&t); 9813840Swosch tp = localtime(&t); 9913840Swosch 10013840Swosch len = strlen(date); 10113840Swosch tm.tm_sec = 0; 10213840Swosch tm.tm_min = 0; 10313840Swosch tm.tm_hour = 0; 10413840Swosch tm.tm_mday = tp->tm_mday; 10513840Swosch tm.tm_mon = tp->tm_mon; 10613840Swosch tm.tm_year = tp->tm_year; 10713840Swosch 10813840Swosch 10913840Swosch /* day */ 11013840Swosch *(date+2) = NULL; 11113840Swosch tm.tm_mday = atoi(date); 11213840Swosch 11313840Swosch /* month */ 11413840Swosch if (len >= 4) { 11513840Swosch *(date+5) = NULL; 11613840Swosch tm.tm_mon = atoi(date+3) - 1; 11713840Swosch } 11813840Swosch 11913840Swosch /* Year */ 12013840Swosch if (len >= 7) { 12113840Swosch tm.tm_year = atoi(date+6); 12213840Swosch 12313840Swosch /* tm_year up 1900 ... */ 12413840Swosch if (tm.tm_year > 1900) 12513840Swosch tm.tm_year -= 1900; 12613840Swosch } 12713840Swosch 12813840Swosch#if DEBUG 12913840Swosch printf("Mktime: %d %d %d %s\n", (int)mktime(&tm), (int)t, len, 13013840Swosch asctime(&tm)); 13113840Swosch#endif 13213840Swosch return(mktime(&tm)); 13313840Swosch} 13413840Swosch 13513840Swosch/* 13613840Swosch * Possible date formats include any combination of: 13713840Swosch * 3-charmonth (January, Jan, Jan) 13813840Swosch * 3-charweekday (Friday, Monday, mon.) 13913840Swosch * numeric month or day (1, 2, 04) 14013840Swosch * 14113840Swosch * Any character may separate them, or they may not be separated. Any line, 14213840Swosch * following a line that is matched, that starts with "whitespace", is shown 14313840Swosch * along with the matched line. 14413840Swosch */ 14513840Swoschint 14615066Smppisnow(endp, monthp, dayp, varp) 14713840Swosch char *endp; 14815066Smpp int *monthp; 14915066Smpp int *dayp; 15015066Smpp int *varp; 15113840Swosch{ 15213840Swosch int day, flags, month, v1, v2; 15313840Swosch 15413840Swosch /* 15513840Swosch * CONVENTION 15613840Swosch * 15713840Swosch * Month: 1-12 15813840Swosch * Monthname: Jan .. Dec 15913840Swosch * Day: 1-31 16013840Swosch * Weekday: Mon-Sun 16113840Swosch * 16213840Swosch */ 16313840Swosch 16413840Swosch flags = 0; 16513840Swosch 16613840Swosch /* read first field */ 16713840Swosch /* didn't recognize anything, skip it */ 16813840Swosch if (!(v1 = getfield(endp, &endp, &flags))) 16913840Swosch return (0); 17013840Swosch 17113840Swosch /* Easter or Easter depending days */ 17213840Swosch if (flags & F_EASTER) 17313840Swosch day = v1; 17413840Swosch 17513840Swosch /* 17613840Swosch * 1. {Weekday,Day} XYZ ... 17713840Swosch * 17813840Swosch * where Day is > 12 17913840Swosch */ 18013840Swosch else if (flags & F_ISDAY || v1 > 12) { 18113840Swosch 18213840Swosch /* found a day; day: 1-31 or weekday: 1-7 */ 18313840Swosch day = v1; 18413840Swosch 18513840Swosch /* {Day,Weekday} {Month,Monthname} ... */ 18613840Swosch /* if no recognizable month, assume just a day alone 18713840Swosch * in other words, find month or use current month */ 18813840Swosch if (!(month = getfield(endp, &endp, &flags))) 18913840Swosch month = tp->tm_mon + 1; 19013840Swosch } 19113840Swosch 19213840Swosch /* 2. {Monthname} XYZ ... */ 19313840Swosch else if (flags & F_ISMONTH) { 19413840Swosch month = v1; 19513840Swosch 19613840Swosch /* Monthname {day,weekday} */ 19713840Swosch /* if no recognizable day, assume the first day in month */ 19813840Swosch if (!(day = getfield(endp, &endp, &flags))) 19913840Swosch day = 1; 20013840Swosch } 20113840Swosch 20213840Swosch /* Hm ... */ 20313840Swosch else { 20413840Swosch v2 = getfield(endp, &endp, &flags); 20513840Swosch 20613840Swosch /* 20713840Swosch * {Day} {Monthname} ... 20813840Swosch * where Day <= 12 20913840Swosch */ 21013840Swosch if (flags & F_ISMONTH) { 21113840Swosch day = v1; 21213840Swosch month = v2; 21315066Smpp *varp = 0; 21413840Swosch } 21513840Swosch 21613840Swosch /* {Month} {Weekday,Day} ... */ 21713840Swosch else { 21813840Swosch /* F_ISDAY set, v2 > 12, or no way to tell */ 21913840Swosch month = v1; 22013840Swosch /* if no recognizable day, assume the first */ 22113840Swosch day = v2 ? v2 : 1; 22215066Smpp *varp = 0; 22313840Swosch } 22413840Swosch } 22513840Swosch 22613840Swosch /* convert Weekday into *next* Day, 22713840Swosch * e.g.: 'Sunday' -> 22 22813840Swosch * 'SunayLast' -> ?? 22913840Swosch */ 23013840Swosch if (flags & F_ISDAY) { 23113840Swosch#if DEBUG 23213840Swosch fprintf(stderr, "\nday: %d %s month %d\n", day, endp, month); 23313840Swosch#endif 23413840Swosch 23515066Smpp *varp = 1; 23613840Swosch /* variable weekday, SundayLast, MondayFirst ... */ 23713840Swosch if (day < 0 || day >= 10) { 23813840Swosch 23913840Swosch /* negative offset; last, -4 .. -1 */ 24013840Swosch if (day < 0) { 24113840Swosch v1 = day/10 - 1; /* offset -4 ... -1 */ 24213840Swosch day = 10 + (day % 10); /* day 1 ... 7 */ 24313840Swosch 24413840Swosch /* day, eg '22th' */ 24513840Swosch v2 = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7); 24613840Swosch 24713840Swosch /* (month length - day) / 7 + 1 */ 24813840Swosch if (((int)((cumdays[month+1] - 24913840Swosch cumdays[month] - v2) / 7) + 1) == -v1) 25013840Swosch /* bingo ! */ 25113840Swosch day = v2; 25213840Swosch 25313840Swosch /* set to yesterday */ 25413840Swosch else 25513840Swosch day = tp->tm_mday - 1; 25613840Swosch } 25713840Swosch 25813840Swosch /* first, second ... +1 ... +5 */ 25913840Swosch else { 26013840Swosch v1 = day/10; /* offset: +1 (first Sunday) ... */ 26113840Swosch day = day % 10; 26213840Swosch 26313840Swosch /* day, eg '22th' */ 26413840Swosch v2 = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7); 26513840Swosch 26613840Swosch /* Hurrah! matched */ 26713840Swosch if ( ((v2 - 1 + 7) / 7) == v1 ) 26813840Swosch day = v2; 26913840Swosch 27013840Swosch /* set to yesterday */ 27113840Swosch else 27213840Swosch day = tp->tm_mday - 1; 27313840Swosch } 27413840Swosch } 27513840Swosch 27613840Swosch /* wired */ 27713840Swosch else { 27813840Swosch day = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7); 27915066Smpp *varp = 1; 28013840Swosch } 28113840Swosch } 28213840Swosch 28313840Swosch#if DEBUG 28413840Swosch fprintf(stderr, "day2: yday %d %d\n", day, tp->tm_yday); 28513840Swosch#endif 28615066Smpp if (!(flags & F_EASTER)) { 28715066Smpp *monthp = month; 28815066Smpp *dayp = day; 28913840Swosch day = cumdays[month] + day; 29015066Smpp } 29115066Smpp else { 29215066Smpp for (v1 = 0; day > cumdays[v1]; v1++) 29315066Smpp ; 29415066Smpp *monthp = v1 - 1; 29515066Smpp *dayp = day - cumdays[v1 - 1] - 1; 29615066Smpp *varp = 1; 29715066Smpp } 29813840Swosch 29913840Swosch /* if today or today + offset days */ 30013840Swosch if (day >= tp->tm_yday - f_dayBefore && 30113840Swosch day <= tp->tm_yday + offset + f_dayAfter) 30213840Swosch return (1); 30313840Swosch 30413840Swosch /* if number of days left in this year + days to event in next year */ 30513840Swosch if (yrdays - tp->tm_yday + day <= offset + f_dayAfter || 30613840Swosch /* a year backward, eg. 6 Jan and 10 days before -> 27. Dec */ 30713840Swosch tp->tm_yday + day - f_dayBefore < 0 30813840Swosch ) 30913840Swosch return (1); 31013840Swosch return (0); 31113840Swosch} 31213840Swosch 31313840Swosch 31413840Swoschint 31513840Swoschgetmonth(s) 31613840Swosch register char *s; 31713840Swosch{ 31813840Swosch register char **p; 31913840Swosch 32013840Swosch for (p = months; *p; ++p) 32113840Swosch if (!strncasecmp(s, *p, 3)) 32213840Swosch return ((p - months) + 1); 32313840Swosch return (0); 32413840Swosch} 32513840Swosch 32613840Swosch 32713840Swoschint 32813840Swoschgetday(s) 32913840Swosch register char *s; 33013840Swosch{ 33113840Swosch register char **p; 33213840Swosch 33313840Swosch for (p = days; *p; ++p) 33413840Swosch if (!strncasecmp(s, *p, 3)) 33513840Swosch return ((p - days) + 1); 33613840Swosch return (0); 33713840Swosch} 33813840Swosch 33913840Swosch/* return offset for variable weekdays 34013840Swosch * -1 -> last weekday in month 34113840Swosch * +1 -> first weekday in month 34213840Swosch * ... etc ... 34313840Swosch */ 34413840Swoschint 34513840Swoschgetdayvar(s) 34613840Swosch register char *s; 34713840Swosch{ 34813840Swosch register int offset; 34913840Swosch 35013840Swosch 35113840Swosch offset = strlen(s); 35213840Swosch 35313840Swosch 35413840Swosch /* Sun+1 or Wednesday-2 35513840Swosch * ^ ^ */ 35613840Swosch 35713840Swosch /* printf ("x: %s %s %d\n", s, s + offset - 2, offset); */ 35813840Swosch switch(*(s + offset - 2)) { 35913840Swosch case '-': 36013840Swosch return(-(atoi(s + offset - 1))); 36113840Swosch break; 36213840Swosch case '+': 36313840Swosch return(atoi(s + offset - 1)); 36413840Swosch break; 36513840Swosch } 36613840Swosch 36713840Swosch 36813840Swosch /* 36913840Swosch * some aliases: last, first, second, third, fourth 37013840Swosch */ 37113840Swosch 37213840Swosch /* last */ 37313840Swosch if (offset > 4 && !strcasecmp(s + offset - 4, "last")) 37413840Swosch return(-1); 37513840Swosch else if (offset > 5 && !strcasecmp(s + offset - 5, "first")) 37613840Swosch return(+1); 37713840Swosch else if (offset > 6 && !strcasecmp(s + offset - 6, "second")) 37813840Swosch return(+2); 37913840Swosch else if (offset > 5 && !strcasecmp(s + offset - 5, "third")) 38013840Swosch return(+3); 38113840Swosch else if (offset > 6 && !strcasecmp(s + offset - 6, "fourth")) 38213840Swosch return(+4); 38313840Swosch 38413840Swosch 38513840Swosch /* no offset detected */ 38613840Swosch return(0); 38713840Swosch} 388