Home > Mobile >  How to find dates in shell script (.sh,.ksh)
How to find dates in shell script (.sh,.ksh)

Time:01-26

i want to take input from user 1. enter weekday(eg. mon,tue..) and number of days 2. enter a range of weekdays (eg. mon-wed) and the number of weeks

if he enters 1 and gives mon and 30 so I want in output, dates of each Monday who came in past 30 days

if he enters mon-wed and the number of weeks 5 then we want dates of Mon, Tue, wed of past 5 weeks

I wrote a script but it's not giving me and expected output can anyone please help me


#!/bin/bash

read -p "Enter 1 to enter a weekday and number of past days or 2 to enter a weekday range and number of weeks: " option

case "$option" in
  1)
    read -p "Enter a weekday (Monday, Tuesday, etc.): " day
    read -p "Enter number of past days: " days
    start_time="00:00:00"
    end_time="24:00:00"
    for (( i=0; i<=$days; i   )); do
      date=$(date --date="$i days ago"  %Y%m%d)
      day_of_week=$(date --date="$i days ago"  %A)
      if [ "$day_of_week" == "$day" ]; then
        echo "Date: $date $start_time, End time: $date $end_time"
      fi
    done
    ;;
  2)
    read -p "Enter a weekday range (e.g. Mon to Wed): " range
    read -p "Enter number of weeks: " weeks
    start_time="00:00:00"
    end_time="24:00:00"
    range_array=($(echo $range | tr '-' ' '))
    start_weekday=${range_array[0]}
    end_weekday=${range_array[-1]}
    for (( i=0; i<=$((weeks*7)); i   )); do
      date=$(date --date="$i days ago"  %Y%m%d)
      day_of_week=$(date --date="$i days ago"  %A)
      if [ "$day_of_week" == "$start_weekday" ]; then
        start_date=$date
      elif [ "$day_of_week" == "$end_weekday" ]; then
        end_date=$date
        echo "Start date: $start_date $start_time, End date: $end_date $end_time"
       
      fi
    done
    ;;
  *)
    echo "Invalid input"
    exit 1
    ;;
esac

CodePudding user response:

Perhaps something like this

read -p "Enter a weekday (Monday, Tuesday, etc.): " day
read -p "Enter number of past days: " days
for n in $(seq 0 7 $days); do
    date -d"last-${day}-${n} days"  %Y%m%d
done

which gives you the list of all the days, like

20230123
20230116
20230109
20230102
20221226
20221219
20221212
20221205
20221128

for (today) and Monday and 60.

CodePudding user response:

The logic of your original script did not capture the essence of your problem definition.

This adaptation of your script offers both command line specification or menu-based selection. NOTE: some values were hard-coded to simplify the testing (you only need to swap the comment between associated pairs of lines in a few places).

#!/bin/bash

DBG=0

error()
{
    echo -e "\n ERROR: missing parameter for '${opt}' option."
    errors
}

error2()
{
    echo -e "\n Invalid options on command line."
    errors
}

errors()
{
    echo -e "\n Only options allowed:\n\t [ --days {day_of_week} {day_range} | --weeks {dow_range} {week_range} ].\n Bye!\n" ; exit 1
}

pSel=1
while [ $# -gt 0 ]
do
    case $1 in
        --days )
            opt=$1
            option=1
            if [ $# -lt 3 ] ; then error ; fi 
            match_DOWn="$2" ; days="$3" ; shift ; shift ; shift
            pSel=0
            ;;
        --weeks )
            opt=$1
            option=2
            if [ $# -lt 3 ] ; then error ; fi 
            range="$2" ; weeks="$3" ; shift ; shift ; shift
            pSel=0
            ;;
        * ) error2 ;;
    esac
done


if [ ${pSel} -eq 1 ]
then
    echo -e " Enter selection:\n\t 1 (to enter a weekday and number of past days) \n or\t 2 (to enter a weekday range and number of weeks)\n => \c" >&2 ; read option <&2
fi

today_DOWi=`date ' %u' `
today_DOWn=`date ' %a' `
today_DATE=$(date ' %Y%m%d' )


if [ ${DBG} -eq 1 ]
then
    echo "About Today:"
    echo ${today_DOWi}
    echo ${today_DOWn}
    echo ${today_DATE}
    echo ""
fi

declare -a weekdays=( "Dummy:0" "Mon:1" "Tue:2" "Wed:3" "Thu:4" "Fri:5" "Sat:6" "Sun:7" )

reportDayOfWeekName()
{
    i=0
    while [ ${i} -lt 8 ]
    do
        #echo ${weekdays[${i}]} >&2
        if [[ ${weekdays[${i}]} =~ ${match_DOWi} ]] ; then break ; fi
        i=$((i =1)) ;
    done
    echo "${weekdays[${i}]}" | cut -f1 -d\:
}

reportDayOfWeekIndex()
{
    i=0
    while [ ${i} -lt 8 ]
    do
        #echo ${weekdays[${i}]} >&2
        if [[ ${weekdays[${i}]} =~ ${match_DOWn} ]] ; then break ; fi
        i=$((i =1)) ;
    done
    echo "${weekdays[${i}]}" | cut -f2 -d\:
}


start_time="00:00:00"
end_time="24:00:00"


case "${option}" in
    1)
        if [ -z "${match_DOWn}" ]
        then
            #read -p "Enter a weekday (Monday, Tuesday, etc.): " match_DOWn
            match_DOWn=Mon

            #read -p "Enter number of past days: " days
            days=28
        fi

        #-----------------------------------------------------
        adjust=$(( $(reportDayOfWeekIndex) - ${today_DOWi} ))
        if [ ${adjust} -gt 0 ]
        then
            adjust=$((adjust-=7))
        fi

        first=$(date --date "${today_DATE}   ${adjust} days" ' %Y%m%d' )
        test ${DBG} -eq 1 && echo "First = " ${first} >&2
        #-----------------------------------------------------

        first=$(date --date "${today_DATE}   ${adjust} days" ' %Y%m%d' )
        date=${first}

        test ${DBG} -eq 1 && echo "LAST = " $((days   ${adjust})) >&2

        i=0
        while [ ${i} -le $((days   ${adjust})) ]
        do
            echo "Date: ${date} ${start_time}, End time: ${date} ${end_time}"
            date=$(date --date "${date} - 7 days" ' %Y%m%d' )
            i=$((i =7))
        done
        ;;
    2)
        if [ -z "${range}" ]
        then
            #read -p "Enter a weekday range (e.g. Mon to Wed): " range
            range="Mon-Tue"

            #read -p "Enter number of weeks: " weeks
            weeks=3
        fi

        match_DOW_F=`echo "${range}" | cut -f1 -d\- `
        test ${DBG} -eq 1 && echo "match_DOW_F = ${match_DOW_F}" >&2

        match_DOW_L=`echo "${range}" | cut -f2 -d\- `
        test ${DBG} -eq 1 && echo "match_DOW_L = ${match_DOW_L}" >&2

        #-----------------------------------------------------
        match_DOWn=${match_DOW_F}

        dowF=$(reportDayOfWeekIndex)
        test ${DBG} -eq 1 && echo "dowF = ${dowF}" >&2

        adjustFST=$((${dowF} - ${today_DOWi} ))
        if [ ${adjustFST} -gt 0 ]
        then
            adjustFST=$((adjustFST-=7))
        fi

        first=$(date --date "${today_DATE}   ${adjustFST} days" ' %Y%m%d' )
        test ${DBG} -eq 1 && echo "First = " ${first} >&2

        #-----------------------------------------------------
        match_DOWn=${match_DOW_L}

        dowL=$(reportDayOfWeekIndex)
        test ${DBG} -eq 1 && echo "dowL = ${dowL}" >&2

        #-----------------------------------------------------
        date=${first}
        j=1
        while [ ${j} -le ${weeks} ]
        do
            test ${DBG} -eq 1 && echo "j = " ${j} >&2
            dateHOLD=${date}

            i=$((dowF))
            while [ ${i} -le $((dowL)) ]
            do
                test ${DBG} -eq 1 && echo "i = " ${i} >&2
                echo "Date: ${date} ${start_time}, End time: ${date} ${end_time}"
                date=$(date --date "${date}   1 day" ' %Y%m%d' )
                i=$((i =1))
            done
            date=$(date --date "${dateHOLD} - 1 week" ' %Y%m%d' )
            echo ""
            j=$((j =1))
        done
        ;;
    "" )
        echo -e "\n No selection. Bye!\n"
        exit 0
        ;;
    *)
        echo -e "\n Invalid selection."
        errors
        exit 1
        ;;
esac

The output for option 1 is as follows:

 Enter selection:
     1 (to enter a weekday and number of past days) 
 or  2 (to enter a weekday range and number of weeks)
 => 1
Date: 20230123 00:00:00, End time: 20230123 24:00:00
Date: 20230116 00:00:00, End time: 20230116 24:00:00
Date: 20230109 00:00:00, End time: 20230109 24:00:00
Date: 20230102 00:00:00, End time: 20230102 24:00:00

The output for option 2 is as follows:

 Enter selection:
     1 (to enter a weekday and number of past days) 
 or  2 (to enter a weekday range and number of weeks)
 => 2
Date: 20230123 00:00:00, End time: 20230123 24:00:00
Date: 20230124 00:00:00, End time: 20230124 24:00:00

Date: 20230116 00:00:00, End time: 20230116 24:00:00
Date: 20230117 00:00:00, End time: 20230117 24:00:00

Date: 20230109 00:00:00, End time: 20230109 24:00:00
Date: 20230110 00:00:00, End time: 20230110 24:00:00

Also note: This script does not incorporate the logic to "normalize" random format of the input (i.e. mon or MON vs expected Mon). You would likely need to incorporate an awk function to do that.

I suggest you consider the following guidance.

If you start by writing the code logic

  • in pseudo-code,
  • fine-grained for each task that you are trying to accomplish,
  • in the correct sequence and
  • in the correct context,

then having that worded so that it does exactly what you want it to do ... will, almost explicitly, tell you WHAT you need to code for each of those, not the HOW. The HOW is the nitty gritty of coding.

What you have provided above in your question does not reflect the necessary separation of logical elements or details to address the required task breakdown.

If you give that a try, the solution will almost pop out of the page at you.

  • Related