Extract from cal

I was trying to get 1st Sunday in a month. I tried using cal [month] [year] followed by awk NF=1 apparently it would give entire 1st field in that month.

Any suggestions

This isn't pretty, but I think it works...

cal 11 2014 | cut -c1-3 | grep "[0-9]" | head -1
or
foo=`cal 11 2014 | cut -c1-3 | grep "[0-9]" | head -1`
echo ${foo}

Yup it worked. Thanks

try

cal 12 2014 | awk 'NR==4{print $1}'

That will get the first or second sunday depending on the year. It works for 2014.

So, let's look at what we get from cal (either with no operands, or a month operand and a year operand):

    August 2014
Su Mo Tu We Th Fr Sa
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

From this we can see that the 1st number on a line with 7 fields (after the header line showing the days of the week) is the 1st Sunday. So, a simple awk shell script for this is:

#!/bin/ksh
cal $1 $2|awk 'NF == 7 && NR > 2 {print $1; exit}'

If you invoke it with no operands, it will give you the 1st Sunday of the current month:

./sun1

prints:

3

If you invoke it with a month and year as operands, it will give you the 1st Sunday of that month in that year:

./sun1 6 2014

prints:

1

Many of the other scripts suggested would print 8 for this instead of 1 .

As always, if you want to try this on a Solaris/SunOS system, change awk to /usr/xxpg4/bin/awk , /usr/xpg6/bin/awk , or nawk .

2 Likes

Excuse me, i don't understand completely the post.

Look at the output from cal 6 2014 :

     June 2014
Su Mo Tu We Th Fr Sa
 1  2  3  4  5  6  7
 8  9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30

The code you suggested:

cal 6 2014 | awk 'NR==4{print $1}'

will print 8 , but the 1st Sunday in June, 2014 is the 1st; not the 8th.

The code I suggested will print 1 in this case and should print the correct day number for the 1st Sunday no matter what day of the week the 1st day of the month is.

Yes it's true, my answer to the post was so quickly, thx.

Are we looking at this the wrong way? The output from cal will have a header row, then the next line will always have Saturday in it. You can see what the Saturday is by trimming off things you don't need, then work out Sunday from that.

Consider:-

topline=`cal $mm $yyyy | head -3 | tail -1`
Sat1="${topline##* }"
((Sun1=$Sat1+1))
if [ $Sun1 -eq 8 ]
then
   Sun1=1
fi

So, first Saturday of a month is the value of Sat1 and the first Sunday of a month is the value of Sun1

Okay, it's a few lines of code, but it works.

I hope that this helps,
Robin


As does:-
```text
cal $1 $2|awk 'NF == 7 && NR > 2 {print $1; exit}'
```
....posted by Don earlier that I hadn't fully read. :o

I think you're onto something! The fourth line of the calendar is always complete, why not calculate from it?

That's robust/complete enough to work on any day of the week. 1 for Sunday, 7 for Saturday.

$ cal
     August 2014
Su Mo Tu We Th Fr Sa
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

$ for N in 1 2 3 4 5 6 7
do
        cal | awk 'NR==4 { while(($DAY+0) > 7) $DAY -= 7; print $DAY; exit }' DAY=$N
done

3
4
5
6
7
1
2

$

There's probably a smarter way with modulous, but that's tricky and longwinded when numbers count from 1 instead of 0, so maybe not...

Nobody remembers my datecalc script. :frowning:

Well, datecalc provides the primatives needed to handle any date calculation. To find the first Sunday...

#! /bin/ksh
alias datecalc=./datecalc
year=$1
month=$2
day1=$(datecalc -d $year $month 1)
((first_sunday = (8 - day1) % 8 ))
echo $first_sunday
exit 0

Here is a sample run...

$
$ ./first-sunday 2014 8
3
$

My datecalc script is posted here: datecalc