\fB\-y\fR, \fB\-\-year\fR
Display a calendar for the whole year.
.TP
-\fB\-w\fR, \fB\-\-week\fR
+\fB\-w\fR, \fB\-\-week\fR [\fInumber\fR]
Display week numbers in the calendar (US or ISO-8601).
.TP
\fB\-\-color\fR [\fIwhen\fR]
#define WEEK_LEN (DAYS_IN_WEEK * DAY_LEN)
#define HEAD_SEP 2
#define MONTH_COLS 3 /* month columns in year view */
+#define WNUM_LEN 3
#define J_DAY_LEN 4 /* 4 spaces per day */
#define J_WEEK_LEN (DAYS_IN_WEEK * J_DAY_LEN)
enum {
WEEK_NUM_DISABLED = 0,
- WEEK_NUM_ISO,
- WEEK_NUM_US
+ WEEK_NUM_MASK=0xff,
+ WEEK_NUM_ISO=0x100,
+ WEEK_NUM_US=0x200,
};
/* utf-8 can have up to 6 bytes per char; and an extra byte for ending \0 */
/* function prototypes */
static int leap_year(long year);
static char * ascii_day(char *, int);
+static char * ascii_wnum(char *, int,int);
static int center_str(const char* src, char* dest, size_t dest_size, size_t width);
static void center(const char *, size_t, int);
static void day_array(int, int, long, int *);
static int day_in_week(int, int, long);
static int day_in_year(int, int, long);
static int week_number(int, int, long, int);
+static int week_to_day(int, long, int);
static void yearly(int, long, int, int);
static int do_monthly(int, int, long, int, struct fmt_st*, int);
static void monthly(int, int, long, int);
int ch, day = 0, month = 0, yflag = 0, wflag = WEEK_NUM_DISABLED;
long year;
int num_months = NUM_MONTHS;
- int colormode = UL_COLORMODE_AUTO;
+ int colormode = UL_COLORMODE_AUTO, wnum = 0;
enum {
OPT_COLOR = CHAR_MAX + 1
{"monday", no_argument, NULL, 'm'},
{"julian", no_argument, NULL, 'j'},
{"year", no_argument, NULL, 'y'},
- {"week", no_argument, NULL, 'w'},
+ {"week", optional_argument, NULL, 'w'},
{"color", optional_argument, NULL, OPT_COLOR},
{"version", no_argument, NULL, 'V'},
{"help", no_argument, NULL, 'h'},
}
#endif
- while ((ch = getopt_long(argc, argv, "13mjsywVh", longopts, NULL)) != -1)
+ while ((ch = getopt_long(argc, argv, "13mjsyw::Vh", longopts, NULL)) != -1)
switch(ch) {
case '1':
num_months = 1; /* default */
yflag = 1;
break;
case 'w':
+ if (optarg) {
+ wnum = strtos32_or_err(optarg,
+ _("invalid week argument"));
+ if (wnum < 1 || wnum > 53)
+ errx(EXIT_FAILURE,_("illegal week value: use 1-53"));
+ }
wflag = WEEK_NUM_US; /* default per weekstart */
break;
case OPT_COLOR:
argc -= optind;
argv += optind;
- if (wflag)
- wflag = (weekstart == MONDAY ? WEEK_NUM_ISO : WEEK_NUM_US);
+ if (wflag) {
+ wflag = wnum & WEEK_NUM_MASK;
+ wflag |= (weekstart == MONDAY ? WEEK_NUM_ISO : WEEK_NUM_US);
+ }
time(&now);
local_time = localtime(&now);
} else if ((long) (local_time->tm_year + 1900) == year) {
day = local_time->tm_yday + 1;
}
- if (!month)
+ if (!month && !wnum)
yflag=1;
break;
case 0:
default:
usage(stderr);
}
+
+ if (wnum>0) {
+ int yday = week_to_day(wnum,year,wflag);
+ if (yday < 1)
+ errx(EXIT_FAILURE, _("illegal week value: year %ld doesn't have week %d"),year,wnum);
+ //day = yday; /* hightlight the first day of the week */
+ month = 1;
+ int leap = leap_year(year);
+ while (month <= 12 && yday > days_in_month[leap][month])
+ yday -= days_in_month[leap][month++];
+ if (month > 12) {
+ /* In some years (e.g. 2010 in ISO mode) it's possible to
+ * have a remnant of week 53 starting the year yet the year
+ * in question ends during 52, in this case we're assuming
+ * that early remnant is being referred to if 53 is given as
+ * argument. */
+ if (wnum == week_number(31,12,year-1,wflag)) {
+ month = 1;
+ } else
+ errx(EXIT_FAILURE, _("illegal week value: year %ld doesn't have week %d"),year,wnum);
+ }
+ //printf("%d %d %ld : %d : %d\n",day,month,year,wflag,wflag&WEEK_NUM_MASK);
+ }
+
headers_init(julian);
- if (!colors_init(colormode))
+ if (!colors_init(colormode)) {
day = 0;
+ wflag &= ~WEEK_NUM_MASK;
+ }
if (yflag)
yearly(day, year, julian, wflag);
{
int col, row, days[MAXDAYS];
char *p, lineout[FMT_ST_CHARS];
- size_t width = (julian ? J_WEEK_LEN : WEEK_LEN) - 1 + (wflag?3:0);
+ size_t width = (julian ? J_WEEK_LEN : WEEK_LEN) - 1 + (wflag?WNUM_LEN:0);
int pos = 0;
day_array(day, month, year, days);
for (col = 0; col < DAYS_IN_WEEK; col++) {
int xd = days[row * DAYS_IN_WEEK + col];
if (xd != SPACE) {
- p += sprintf(p,"%2d ",
- week_number(xd & ~TODAY_FLAG,month,year,wflag));
+ int wnum = week_number(xd&~TODAY_FLAG,month,year,wflag);
+ p = ascii_wnum(p,wnum,(wflag & WEEK_NUM_MASK)==wnum);
break;
+ /*
+ int wnum = week_number(xd & ~TODAY_FLAG,month,year,wflag);
+ int highlight = 0;
+ if ((wflag&WEEK_NUM_MASK)==wnum) {
+ p += sprintf(p, "%s", Senter);
+ highlight = 1;
+ }
+ p += sprintf(p,"%2d",wnum);
+ if (highlight)
+ p += sprintf(p, "%s", Sexit);
+ p += sprintf(p," ");
+ break; */
} else if (col+1 == DAYS_IN_WEEK)
p += sprintf(p," ");
}
int days[MONTHS_IN_YEAR][MAXDAYS];
char *p;
/* three weeks + separators + \0 */
- int wnumlen = (wflag?3:0);
+ int wnumlen = (wflag?WNUM_LEN:0);
char lineout[ wnumlen + sizeof(day_headings) + 2 +
wnumlen + sizeof(day_headings) + 2 +
wnumlen + sizeof(day_headings) + 1 ];
for (col = 0; col < DAYS_IN_WEEK; col++) {
int xd = days[month + which_cal][row * DAYS_IN_WEEK + col];
if (xd != SPACE) {
- p += sprintf(p,"%2d ",
- week_number(xd & ~TODAY_FLAG,month + which_cal + 1,year,wflag));
+ int wnum = week_number(xd&~TODAY_FLAG,month+which_cal+1,year,wflag);
+ p = ascii_wnum(p,wnum,(wflag & WEEK_NUM_MASK)==wnum);
break;
} else if (col+1 == DAYS_IN_WEEK)
p += sprintf(p," ");
static int week_number(int day, int month, long year, int wflag) {
int fday = 0,wday,yday;
wday = day_in_week(1,1,year);
- if (wflag == WEEK_NUM_ISO)
+ if (wflag & WEEK_NUM_ISO)
fday = wday + (wday>=FRIDAY?-2:5);
else /* WEEK_NUM_US */
/* according to gcal, the first Sun is in the first week */
return (yday+fday) / 7;
}
+/*
+ * week_to_day
+ * return the yday of the first day in a given week inside
+ * the given year. This may be something other than Monday
+ * for ISO-8601 modes. For North American numbering this
+ * always returns a Sunday.
+ */
+static int week_to_day(int wnum, long year, int wflag) {
+ int yday, wday;
+ wday = day_in_week(1,1,year);
+ yday = wnum * 7 - wday;
+ if (wflag & WEEK_NUM_ISO)
+ yday -= (wday>=FRIDAY?-2:5);
+ else /* WEEK_NUM_US */
+ yday -= (wday==SUNDAY?6:-1);
+ if (yday<=0)
+ return 1;
+
+ return yday;
+}
+
static char *ascii_day(char *p, int day)
{
int display, val;
return p;
}
+static char * ascii_wnum(char *p, int wnum,int highlight)
+{
+ if (highlight)
+ p += sprintf(p,"%s",Senter);
+ p += sprintf(p,"%2d",wnum);
+ if (highlight)
+ p += sprintf(p,"%s ",Sexit);
+ else
+ p += sprintf(p," ");
+ return p;
+}
+
/*
* Center string, handling multibyte characters appropriately.
* In addition if the string is too large for the width it's truncated.
--- /dev/null
+
+Gregorian - Monday-based, week 40, 3 month
+ August 2013 September 2013 October 2013
+ Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
+31 1 2 3 4 35 1 40 1 2 3 4 5 6
+32 5 6 7 8 9 10 11 36 2 3 4 5 6 7 8 41 7 8 9 10 11 12 13
+33 12 13 14 15 16 17 18 37 9 10 11 12 13 14 15 42 14 15 16 17 18 19 20
+34 19 20 21 22 23 24 25 38 16 17 18 19 20 21 22 43 21 22 23 24 25 26 27
+35 26 27 28 29 30 31 39 23 24 25 26 27 28 29 44 28 29 30 31
+ 40 30
+Gregorian - Sunday-based, week 40, 3 month
+ September 2013 October 2013 November 2013
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+35 1 2 3 4 5 6 7 39 1 2 3 4 5 43 1 2
+36 8 9 10 11 12 13 14 40 6 7 8 9 10 11 12 44 3 4 5 6 7 8 9
+37 15 16 17 18 19 20 21 41 13 14 15 16 17 18 19 45 10 11 12 13 14 15 16
+38 22 23 24 25 26 27 28 42 20 21 22 23 24 25 26 46 17 18 19 20 21 22 23
+39 29 30 43 27 28 29 30 31 47 24 25 26 27 28 29 30
+
+Julian - Monday-based, week 40, 3 month
+ August 2013 September 2013 October 2013
+ Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun
+31 213 214 215 216 35 244 40 274 275 276 277 278 279
+32 217 218 219 220 221 222 223 36 245 246 247 248 249 250 251 41 280 281 282 283 284 285 286
+33 224 225 226 227 228 229 230 37 252 253 254 255 256 257 258 42 287 288 289 290 291 292 293
+34 231 232 233 234 235 236 237 38 259 260 261 262 263 264 265 43 294 295 296 297 298 299 300
+35 238 239 240 241 242 243 39 266 267 268 269 270 271 272 44 301 302 303 304
+ 40 273
+Julian - Sunday-based, week 40, 3 month
+ September 2013 October 2013 November 2013
+ Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat
+35 244 245 246 247 248 249 250 39 274 275 276 277 278 43 305 306
+36 251 252 253 254 255 256 257 40 279 280 281 282 283 284 285 44 307 308 309 310 311 312 313
+37 258 259 260 261 262 263 264 41 286 287 288 289 290 291 292 45 314 315 316 317 318 319 320
+38 265 266 267 268 269 270 271 42 293 294 295 296 297 298 299 46 321 322 323 324 325 326 327
+39 272 273 43 300 301 302 303 304 47 328 329 330 331 332 333 334
+
+Gregorian - Monday-based, week 40, 1 month
+ September 2013
+ Mo Tu We Th Fr Sa Su
+35 1
+36 2 3 4 5 6 7 8
+37 9 10 11 12 13 14 15
+38 16 17 18 19 20 21 22
+39 23 24 25 26 27 28 29
+40 30
+Gregorian - Sunday-based, week 40, 1 month
+ October 2013
+ Su Mo Tu We Th Fr Sa
+39 1 2 3 4 5
+40 6 7 8 9 10 11 12
+41 13 14 15 16 17 18 19
+42 20 21 22 23 24 25 26
+43 27 28 29 30 31
+
+Julian - Monday-based, week 40, 1 month
+ September 2013
+ Mon Tue Wed Thu Fri Sat Sun
+35 244
+36 245 246 247 248 249 250 251
+37 252 253 254 255 256 257 258
+38 259 260 261 262 263 264 265
+39 266 267 268 269 270 271 272
+40 273
+Julian - Sunday-based, week 40, 1 month
+ October 2013
+ Sun Mon Tue Wed Thu Fri Sat
+39 274 275 276 277 278
+40 279 280 281 282 283 284 285
+41 286 287 288 289 290 291 292
+42 293 294 295 296 297 298 299
+43 300 301 302 303 304
+
+Gregorian - Monday-based, week 53, 1 month
+ January 2010
+ Mo Tu We Th Fr Sa Su
+53 1 2 3
+ 1 4 5 6 7 8 9 10
+ 2 11 12 13 14 15 16 17
+ 3 18 19 20 21 22 23 24
+ 4 25 26 27 28 29 30 31
+
+Julian - Monday-based, week 53, 1 month
+ January 2010
+ Mon Tue Wed Thu Fri Sat Sun
+53 1 2 3
+ 1 4 5 6 7 8 9 10
+ 2 11 12 13 14 15 16 17
+ 3 18 19 20 21 22 23 24
+ 4 25 26 27 28 29 30 31
+
+Gregorian - Monday-based, week 53 with colors, 1 month
+ January 2010
+ Mo Tu We Th Fr Sa Su
+\e[7m53\e[27m 1 2 3
+ 1 4 5 6 7 8 9 10
+ 2 11 12 13 14 15 16 17
+ 3 18 19 20 21 22 23 24
+ 4 25 26 27 28 29 30 31
+
+Julian - Monday-based, week 53 with colors, 1 month
+ January 2010
+ Mon Tue Wed Thu Fri Sat Sun
+\e[7m53\e[27m 1 2 3
+ 1 4 5 6 7 8 9 10
+ 2 11 12 13 14 15 16 17
+ 3 18 19 20 21 22 23 24
+ 4 25 26 27 28 29 30 31
+
+Gregorian - Monday-based, week 40 with colors, 3 month
+ August 2013 September 2013 October 2013
+ Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
+31 1 2 3 4 35 1 \e[7m40\e[27m 1 2 3 4 5 6
+32 5 6 7 8 9 10 11 36 2 3 4 5 6 7 8 41 \e[7m 7\e[27m 8 9 10 11 12 13
+33 12 13 14 15 16 17 18 37 9 10 11 12 13 14 15 42 14 15 16 17 18 19 20
+34 19 20 21 22 23 24 25 38 16 17 18 19 20 21 22 43 21 22 23 24 25 26 27
+35 26 27 28 29 30 31 39 23 24 25 26 27 28 29 44 28 29 30 31
+ \e[7m40\e[27m 30
+Julian - Monday-based, week 40 with colors, 3 month
+ August 2013 September 2013 October 2013
+ Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun
+31 213 214 215 216 35 244 \e[7m40\e[27m 274 275 276 277 278 279
+32 217 218 219 220 221 222 223 36 245 246 247 248 249 250 251 41 \e[7m280\e[27m 281 282 283 284 285 286
+33 224 225 226 227 228 229 230 37 252 253 254 255 256 257 258 42 287 288 289 290 291 292 293
+34 231 232 233 234 235 236 237 38 259 260 261 262 263 264 265 43 294 295 296 297 298 299 300
+35 238 239 240 241 242 243 39 266 267 268 269 270 271 272 44 301 302 303 304
+ \e[7m40\e[27m 273
--- /dev/null
+#!/bin/bash
+
+#
+# Copyright (C) 2007 Karel Zak <kzak@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+TS_TOPDIR="$(dirname $0)/../.."
+TS_DESC="week number given as argument"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+set -o pipefail
+
+USETERM=$( ts_has_option "useterm" "$*" )
+
+[ "$USETERM" == "yes" ] && TS_VERBOSE="yes"
+ts_log ""
+
+MYTIME="7 10 2013"
+PWEEK="week 40"
+WEEK="--week=40"
+ts_log "Gregorian - Monday-based, $PWEEK, 3 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -3m $WEEK $MYTIME
+fi
+$TS_CMD_CAL -3m $WEEK $MYTIME >> $TS_OUTPUT
+
+ts_log "Gregorian - Sunday-based, $PWEEK, 3 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -3s $WEEK $MYTIME
+fi
+$TS_CMD_CAL -3s $WEEK $MYTIME >> $TS_OUTPUT
+
+
+ts_log "Julian - Monday-based, $PWEEK, 3 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -3mj $WEEK $MYTIME
+fi
+$TS_CMD_CAL -3mj $WEEK $MYTIME >> $TS_OUTPUT
+
+ts_log "Julian - Sunday-based, $PWEEK, 3 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -3sj $WEEK $MYTIME
+fi
+$TS_CMD_CAL -3sj $WEEK $MYTIME >> $TS_OUTPUT
+
+ts_log "Gregorian - Monday-based, $PWEEK, 1 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -m $WEEK $MYTIME
+fi
+$TS_CMD_CAL -m $WEEK $MYTIME >> $TS_OUTPUT
+
+ts_log "Gregorian - Sunday-based, $PWEEK, 1 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -s $WEEK $MYTIME
+fi
+$TS_CMD_CAL -s $WEEK $MYTIME >> $TS_OUTPUT
+
+
+ts_log "Julian - Monday-based, $PWEEK, 1 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -mj $WEEK $MYTIME
+fi
+$TS_CMD_CAL -mj $WEEK $MYTIME >> $TS_OUTPUT
+
+ts_log "Julian - Sunday-based, $PWEEK, 1 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -sj $WEEK $MYTIME
+fi
+$TS_CMD_CAL -sj $WEEK $MYTIME >> $TS_OUTPUT
+
+# tricky year, starts with a bit of 53 yet ends during 52
+MYTIME="2010"
+PWEEK="week 53"
+WEEK="--week=53"
+ts_log "Gregorian - Monday-based, $PWEEK, 1 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -1m $WEEK $MYTIME
+fi
+$TS_CMD_CAL -1m $WEEK $MYTIME >> $TS_OUTPUT
+
+ts_log "Julian - Monday-based, $PWEEK, 1 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -1mj $WEEK $MYTIME
+fi
+$TS_CMD_CAL -1mj $WEEK $MYTIME >> $TS_OUTPUT
+
+MYTIME="2010"
+PWEEK="week 53 with colors"
+WEEK="--week=53 --color=always"
+ts_log "Gregorian - Monday-based, $PWEEK, 1 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -1m $WEEK $MYTIME
+fi
+$TS_CMD_CAL -1m $WEEK $MYTIME >> $TS_OUTPUT
+
+ts_log "Julian - Monday-based, $PWEEK, 1 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -1mj $WEEK $MYTIME
+fi
+$TS_CMD_CAL -1mj $WEEK $MYTIME >> $TS_OUTPUT
+
+MYTIME="7 10 2013"
+PWEEK="week 40 with colors"
+WEEK="--week=40 --color=always"
+ts_log "Gregorian - Monday-based, $PWEEK, 3 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -3m $WEEK $MYTIME
+fi
+$TS_CMD_CAL -3m $WEEK $MYTIME >> $TS_OUTPUT
+
+ts_log "Julian - Monday-based, $PWEEK, 3 month $x"
+if [ "$USETERM" == "yes" ]; then
+ $TS_CMD_CAL -3mj $WEEK $MYTIME
+fi
+$TS_CMD_CAL -3mj $WEEK $MYTIME >> $TS_OUTPUT
+
+ts_finalize
+