Displaying week's number in certain format using ncal or cal
If neither of these commands suit your needs you can use gcal
to do what you want instead.
Example
$ gcal -K
April 2014
Su Mo Tu We Th Fr Sa CW
1 2 3 4 5 13
6 7 8 9 10 11 12 14
13 14 15 16 17 18 19 15
20 21 22 23 24 25 26 16
27 28 29 30 17
Prints the week number in the last column to the right.
References
- Gcal the ultra-powerful command line GNU calendar
- Gcal user's manual
- The many uses of gcal
This highlights today's date, and can display any month via $1
in the form: YYYY-mm-dd
... It defaults to today's date
It is set up to show ISO week numbers, and the first weekday being Monday.
#!/bin/bash
# Input reference date is expected in 'YYYY-mm-dd' format
#
today=($(date '+%Y %m %d')); Y=0; m=1; d=2 # establish today's date
[[ -z $1 ]] && ref=(${today[@]}) || ref=(${1//-/ }) # get input date
dNbA=$(date --date="$(date +%Y-%m-01)" +'%u') # day-number of 1st day of reference month
today[m]=$((10#${today[m]})); ref[m]=$((10#${ref[m]})) # remove leading zero (octal clash)
today[d]=$((10#${today[d]})); ref[d]=$((10#${ref[d]})) # remove leading zero (octal clash)
nxtm=$(( ref[m]==12 ?1 :ref[m]+1 )) # month-number of next month
nxtY=$(( ref[m]==12 ?ref[Y]+1:ref[Y] )) # year-number of next month
nxtA="$nxtY-$nxtm-1" # date of 1st day of next month
refZ=$(date --date "$(date +$nxtA) yesterday" +%Y-%m-%d) # date of last day of reference month
days=$(date --date="$refZ" '+%d') # days in reference month
h1="$(date --date="${ref[Y]}-${ref[m]}-${ref[d]}" '+%B %Y')" # header 1
h2="Mo Tu We Th Fr Sa Su" # header 2
printf " %$(((${#h2}-${#h1}-1)/2))s%s\n" " " "$h1"
printf " %s\n" "$h2"
# print week rows
printf "%2d " "$((10#$(date -d "$(date +${ref[Y]}-${ref[m]}-01)" +'%V')))" # week-number (of year) with suppressed leading 0
printf "%$(((dNbA-1)*3))s" # lead spaces (before start of month)
dNbW=$dNbA # day-number of week
dNbM=1 # day-number of month
while ((dNbM <= days)) ;do
if (( today[Y]==ref[Y] &&
today[m]==ref[m] &&
today[d]==dNbM )) ;then
printf "\x1b[7m%2d\x1b[0m " "$dNbM" # highlight today's date
else
printf "%2d " "$dNbM"
fi
((dNbM++))
if ((dNbW >=7)) ;then
cdate=$((10#$(date -d "$(date +${ref[Y]}-${ref[m]}-$dNbM)" +'%V'))) # remove leading zero (octal clash)
printf "\n%2d " "$cdate" # week-number of year
dNbW=0
fi
((dNbW++))
done
printf "%$(((8-dNbW)*3))s\n" # trailing spaces (after end of month)
Here is this month's display (with 20
highlighted)
January 2012
Mo Tu We Th Fr Sa Su
52 1
1 2 3 4 5 6 7 8
2 9 10 11 12 13 14 15
3 16 17 18 19 20 21 22
4 23 24 25 26 27 28 29
5 30 31
You can use nl
to number the lines (that's the program purpose :). But you need to extract the first week in the month from somewhere. It can be done from ncal
itself:
$ ncal -w 2 2012 | tail -1 | awk '{print $1}'
5
We insert this as a parameter to nl
's option -v
(starting line number), and tell it to only number lines with numbers or spaces.
$ cal 2 2012 | nl -bp'^[0-9 ]\+$' -w2 -s' ' -v$(ncal -w 2 2012 | tail -1 | awk '{print $1}')
February 2012
Su Mo Tu We Th Fr Sa
5 1 2 3 4
6 5 6 7 8 9 10 11
7 12 13 14 15 16 17 18
8 19 20 21 22 23 24 25
9 26 27 28 29
This is all awfully fragile though. Anyway, if you aren't going to need cal
's more advanced options, it will work. You can put it in a file and replace "$@"
where I put 2 2012
.
EDIT: But this is WRONG! I just noticed that the first week in January can have number 52 or 53! So we just either have to make an exception for January, or just extract all the week numbers from ncal
and apply them to the output of cal
.
This is the solution I thought originally, but I thought (erroneously) I would simplify it using nl
. It uses paste
, which merges files side-by-side. Since there isn't any file, we have to use the bashism <(...)
; that's what I was trying to avoid.
Our first "file" will be a list of the week numbers, with two empty lines at the beginning:
$ printf ' \n \n' && printf '%2d \n' $(ncal -w 1 2011 | tail -1)
52
1
2
3
4
5
The second one, just the output of cal
. All together, as parameters to paste
:
$ paste -d' ' <(printf ' \n \n' && printf '%2d \n' $(ncal -w 1 2011 | tail -1)) <(cal 1 2011)
January 2011
Su Mo Tu We Th Fr Sa
52 1
1 2 3 4 5 6 7 8
2 9 10 11 12 13 14 15
3 16 17 18 19 20 21 22
4 23 24 25 26 27 28 29
5 30 31
Much messier and incompatible that the other one. En fin...