From b10b1da57d4d573647d1a528efaecfc54dea8073 Mon Sep 17 00:00:00 2001 From: Christoph Lohmann <20h@r-36.net> Date: Wed, 19 Jun 2013 22:10:26 +0200 Subject: [PATCH] Make date(1) compatible to GNU date(1). We have variable first day of weeks now! My week starts on Wednesday! --- cal.1 | 50 ++++++++++++++------- cal.c | 140 ++++++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 126 insertions(+), 64 deletions(-) diff --git a/cal.1 b/cal.1 index 2ac26ce..a679350 100644 --- a/cal.1 +++ b/cal.1 @@ -3,13 +3,20 @@ cal \- print calendar .SH SYNOPSIS .B cal +.RB [ \-1 ] +.RB [ \-3 ] +.RB [ \-m ] +.RB [ \-s ] +.RB [ \-y ] .RB [ \-c .IR columns ] -.RB [ \-m -.IR month ] +.RB [ \-f +.IR firstday ] .RB [ \-n -.IR number ] -.RB [ \-y +.IR nmonths ] +.RB [ [ [ +.IR day ] +.IR month ] .IR year ] .SH DESCRIPTION Beginning with @@ -20,23 +27,34 @@ print .IR number of calendars side by side. Each row of calendars contains at most .IR columns -number of calendars. +number of calendars. The defaults are obtained using +.IR localtime (3). .SH OPTIONS .TP +.B \-1 +Print one single month. +.TP +.B \-3 +Print prev/current/nexth month. +.TP +.B \-m +Print Monday as first day of week. +.TP +.B \-s +Print Sunday as first day of week. +.TP +.B \-y +Print a calendar of the current year. +.TP .BI \-c " columns" -print +Print .IR columns -number of calendars in a row. default is 3 +number of calendars in a row. The default is 3. .TP -.BI \-m " month" -starting month. default is obtained from -.IR localtime (3) +.BI \-f " firstday" +Specify the first day of the week. 0 is Sunday and 6 is Saturday. .TP -.BI \-n " number" -number of calendars to print. default is 1 -.TP -.BI \-y " year" -starting year. default is obtained from -.IR localtime (3) +.BI \-n " nmonths" +Specify the number months to print. The default is 1. .SH SEE ALSO .IR localtime (3) diff --git a/cal.c b/cal.c index 84da106..b32caf3 100644 --- a/cal.c +++ b/cal.c @@ -7,29 +7,30 @@ #define MONTHMAX 100 -static void drawcal(int, int, int, int, int); -static int dayofweek(int, int, int); +static void drawcal(int, int, int, int, int, int); +static int dayofweek(int, int, int, int); static bool isleap(int); static void usage(void); static void -drawcal(int year, int month, int day, int ncols, int nmons) +drawcal(int year, int month, int day, int ncols, int nmons, int fday) { char str[21]; int count[MONTHMAX]; - int d, i, r; + int d, i, r, j; int moff, yoff, cur, last, ndays, day1; - char *smon[]= { + char *smon[] = { " January", " February", " March", " April", " May", " June", " July", " August", " September", " October", " November", " December" }; int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int row = 0; + char *days[] = { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", }; - while (nmons > 0) { + while(nmons > 0) { last = MIN(nmons, ncols); - for (i = 0; i < last; i++) { + for(i = 0; i < last; i++) { moff = month + ncols * row + i - 1; cur = moff % 12; yoff = year + moff / 12; @@ -40,24 +41,30 @@ drawcal(int year, int month, int day, int ncols, int nmons) } printf("\n"); - for (i = 0; i < last; i++) - printf("Su M Tu W Th F Sa "); + for(i = 0; i < last; i++) { + for(j = fday; j < LEN(days); j++) + printf("%s ", days[j]); + for(j = 0; j < fday; j++) + printf("%s ", days[j]); + printf(" "); + } printf("\n"); - for (r = 0; r < 6; r++) { - for (i = 0; i < last; i++) { + for(r = 0; r < 6; r++) { + for(i = 0; i < last; i++) { moff = month + ncols * row + i - 1; cur = moff % 12; yoff = year + moff / 12; ndays = mdays[cur] + ((cur == 1) & isleap(yoff)); - day1 = dayofweek(year, cur, 1); + day1 = dayofweek(year, cur, 1, fday); - for (d = 0; d < 7; d++) - if ((r || d >= day1) && count[i] <= ndays) + for(d = 0; d < 7; d++) { + if((r || d >= day1) && count[i] <= ndays) printf("%2d ", count[i]++); else printf(" "); + } printf(" "); } printf("\n"); @@ -67,32 +74,19 @@ drawcal(int year, int month, int day, int ncols, int nmons) } } -static void -defaults(int *year, int *month, int *day, int *ncols, int *nmons) -{ - time_t now; - struct tm *ltime; - - now = time(NULL); - ltime = localtime(&now); - *year = ltime->tm_year + 1900; - *month = ltime->tm_mon + 1; - *day = ltime->tm_mday; - - *ncols = 3; - *nmons = 1; -} static int -dayofweek(int year, int month, int day) +dayofweek(int year, int month, int day, int fday) { - int a, y, m; + int a, y, m, d; month++; a = (14 - month) / 12; y = year + 4800 - a; - m = month + 12 * a -3; - return (day + (153 * m + 2) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 32045 + 1) % 7; + m = month + 12 * a - 3; + d = (day + (153 * m + 2) / 5 + 365 * y + y / 4 - y / 100 + y \ + / 400 - 32045 + 1) % 7; + return (fday > d)? (7 - d) : (d - fday); } static bool @@ -100,9 +94,12 @@ isleap(int year) { bool leap = false; - if (year % 4 == 0) leap = true; - if (year % 100 == 0) leap = false; - if (year % 400 == 0) leap = true; + if(year % 4 == 0) + leap = true; + if(year % 100 == 0) + leap = false; + if(year % 400 == 0) + leap = true; return leap; } @@ -110,38 +107,85 @@ isleap(int year) static void usage(void) { - eprintf("usage: %s [-c columns] [-m month] [-n number] [-y year]\n", argv0); - exit(1); + eprintf("usage: %s [-c columns] [-m month] [-n number] [-y year]\n", + argv0); } int main(int argc, char *argv[]) { - int year, month, day, ncols, nmons; + int year, month, day, ncols, nmons, fday; + struct tm *ltime; + time_t now; - defaults(&year, &month, &day, &ncols, &nmons); + now = time(NULL); + ltime = localtime(&now); + year = ltime->tm_year + 1900; + month = ltime->tm_mon + 1; + day = ltime->tm_mday; + fday = 0; + + ncols = 3; + nmons = 1; ARGBEGIN { - case 'c': - ncols = (int) estrtol(EARGF(usage()), 0); + case '1': + nmons = 1; break; - case 'm': - month = (int) estrtol(EARGF(usage()), 0); + case '3': + nmons = 3; + month -= 1; + if(month == 0) { + month = 12; + year--; + } + break; + case 'c': + ncols = estrtol(EARGF(usage()), 0); + break; + case 'f': + fday = estrtol(EARGF(usage()), 0); + break; + case 'm': /* Monday */ + fday = 1; break; case 'n': - nmons = (int) estrtol(EARGF(usage()), 0); + nmons = estrtol(EARGF(usage()), 0); + break; + case 's': /* Sunday */ + fday = 0; break; case 'y': - year = (int) estrtol(EARGF(usage()), 0); + month = 1; + nmons = 12; break; default: usage(); } ARGEND; - if (ncols < 0 || ncols > MONTHMAX || month < 1 || month > 12 || nmons < 1 || year > 9999) + switch(argc) { + case 3: + day = estrtol(argv[0], 0); + argv++; + case 2: + month = estrtol(argv[0], 0); + argv++; + case 1: + year = estrtol(argv[0], 0); + break; + case 0: + break; + default: usage(); + } + + if(ncols < 0 || ncols > MONTHMAX || month < 1 || month > 12 \ + || nmons < 1 || fday < 0 || fday > 6) { + usage(); + } + + drawcal(year, month, day, ncols, nmons, fday); - drawcal(year, month, day, ncols, nmons); exit(0); }