Make date(1) compatible to GNU date(1).

We have variable first day of weeks now! My week starts on Wednesday!
This commit is contained in:
Christoph Lohmann 2013-06-19 22:10:26 +02:00
parent 0f523ec9c6
commit b10b1da57d
2 changed files with 126 additions and 64 deletions

50
cal.1
View File

@ -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)

126
cal.c
View File

@ -7,17 +7,17 @@
#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[] = {
" January", " February", " March",
@ -26,6 +26,7 @@ drawcal(int year, int month, int day, int ncols, int nmons)
" 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) {
last = MIN(nmons, ncols);
@ -40,8 +41,13 @@ 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++) {
@ -51,13 +57,14 @@ drawcal(int year, int month, int day, int ncols, int nmons)
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++)
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;
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);
}