gioele
gioele

Reputation: 10205

Finding the Monday before the third Sunday of a month

How can I generate a list of "Monday before the third Sunday of the month" for the next N months in a shell script?

date recognizes a quite extensive set of operations (today + 3 months, for example), but I haven't found anything that fits my needs.

Anything that uses common GNU and BSD commands is OK. A bash-specific answer would be OK as well.

Upvotes: 1

Views: 521

Answers (3)

pacholik
pacholik

Reputation: 8972

It's just 16 - '%u' of the first day of a month.

expr `date -d"$year-$month-1" +'16 - %u'`

%u day of week (1..7); 1 is Monday

Upvotes: 1

Component 10
Component 10

Reputation: 10487

How about this (with apologies for the long variable names though this is more about instruction than efficiency)

#!/bin/bash

function getMonBefore3rdSunInMonth
{
    # Get the date N months from today.
    monthN=$( date --date="+ ${1} month" +"%m/%d/%Y" )
    # The number of days from that date to the first of the month.
    daysSinceFirstofMonth=$(( $( date --date="${monthN}" +"%d" ) - 1 ))
    # The week-day of first of that month (0..6); 0 is Sunday
    weekDayFirstOfMonth=$( date --date="${monthN}- ${daysSinceFirstofMonth} days" +"%w" )
    # The number of days between the given date and the Monday before
    # the third Wednesday of the month (start at the begining of the month
    # add an offset to the first Sunday, add 14 days to get to third and
    # take off 6 days to get back to previous Monday.
    offsetToMonBefore3rdSunInMonth=$(( -${daysSinceFirstofMonth} + ( ( 7 - ${weekDayFirstOfMonth} ) % 7 ) + 14 - 6 ))
    # Use the offset to work out the date.
    monBefore3rdSunInMonth=$( date --date="${monthN} + ${offsetToMonBefore3rdSunInMonth} days" +"%m/%d/%Y" )
    echo ${monBefore3rdSunInMonth}
}

N=${1}
for n in $( seq ${N} )
do
    getMonBefore3rdSunInMonth $n
done

$ ./getMonBefore3rdSunInMonth.sh 12
07/13/2015
08/10/2015
09/14/2015
10/12/2015
11/09/2015
12/14/2015
01/11/2016
02/15/2016
03/14/2016
04/11/2016
05/09/2016
06/13/2016

Upvotes: 1

pynexj
pynexj

Reputation: 20688

Using GNU date:

$ cat mon-before-3rd-sun.sh
mon_before_3rd_sun()
{
    local year=$1
    local mon=$2
    local seconds weekday

    # get the 1st day of the month
    seconds=$(date +%s -d $year-$mon-1)

    # weekday of the 1st day of the month
    weekday=$(date +%u -d @$seconds)

    # 1st Sunday of the month
    ((seconds += (7 - weekday) * 86400))

    # Monday before 3rd Sunday (i.e. after 2nd Sunday)
    ((seconds += 8 * 86400))
    date '+%Y-%m-%d' -d @$seconds
}

for ((mon = 1; mon <= 12; ++mon)); do
    mon_before_3rd_sun 2015 $mon
done
$ bash mon-before-3rd-sun.sh
2015-01-12
2015-02-09
2015-03-09
2015-04-13
2015-05-11
2015-06-15
2015-07-13
2015-08-10
2015-09-14
2015-10-12
2015-11-09
2015-12-14
$

Upvotes: 1

Related Questions