How to use bash to get the last day of each month for the current year without using if else or switch or while loop?

my take:

for m in {1..12}; do
  date -d "$m/1 + 1 month - 1 day" "+%b - %d days"; 
done

To explain: for the first iteration when m=1 the -d argument is "1/1 + 1 month - 1 day" and "1/1" is interpreted as Jan 1st. So Jan 1 + 1 month - 1 day is Jan 31. Next iteration "2/1" is Feb 1st, add a month subtract a day to get Feb 28 or 29. And so on.


cat <<EOF
Jan - 31 days
Feb - `date -d "yesterday 3/1" +"%d"` days
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days
EOF

Assuming you allow "for", then the following in bash

for m in {1..12}; do
    echo $(date -d $m/1/1 +%b) - $(date -d "$(($m%12+1))/1 - 1 days" +%d) days
done

produces this

 Jan - 31 days
 Feb - 29 days
 Mar - 31 days
 Apr - 30 days
 May - 31 days
 Jun - 30 days
 Jul - 31 days
 Aug - 31 days
 Sep - 30 days
 Oct - 31 days
 Nov - 30 days
 Dec - 31 days

Note: I removed the need for cal

For those that enjoy trivia:

Number months from 1 to 12 and look at the binary representation in four
bits {b3,b2,b1,b0}.  A month has 31 days if and only if b3 differs from b0.
All other months have 30 days except for February.

So with the exception of February this works:

for m in {1..12}; do
    echo $(date -d $m/1/1 +%b) - $((30+($m>>3^$m&1))) days
done

Result:

Jan - 31 days
Feb - 30 days (wrong)
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days

Tags:

Unix

Bash