Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 456
  • Last Modified:

Shell or Perl Script to split date accoridng to Month

I need the perl or shell scipt to split the dates.

Below are the conditions:

1. Calculate the day of the week (Mon - Sunday) 9/26/2011 - 10/3/2011
    (Example in Oracle
      select trunc(to_date('2011-10-05', 'yyyy-mm-dd')-6, 'IW') as sdate,
                trunc(to_date('2011-10-05', 'yyyy-mm-dd')+1,'IW') as edate
                from dual)

2. Since the date falls in 2 months 09-2011 and 10-2011, the script needs to split the date like
    9/26/2011  -  9/30/2011
    10/01/2011 - 10/3/2011
     and execute another  2 shell scripts like
                   ./test.sh --from  9/26/2011 --to 9/30/2011
                  ./test.sh --from   10/01/2011 --to 10/3/2011

3. In the case where date range is in the same month, the script needs to split the date like
    10/3/2011 - 10/10/2011
    and execute only  1 shell script like
                   ./test.sh --from  10/3/2011 --to 10/10/2011
   
  (Example in Oracle
      select trunc(to_date('2011-10-15', 'yyyy-mm-dd')-6, 'IW') as sdate,
       trunc(to_date('2011-10-15', 'yyyy-mm-dd')+1,'IW') as edate
       from dual)

Any help would be highly appreciated. !!

   
0
losforword
Asked:
losforword
  • 7
  • 6
  • 3
1 Solution
 
xtermCommented:
What is the input to this script - two dates?  And in what format will they be fed to the script?  I can't understand from your description how day of the week fits in and/or is relevant.
0
 
losforwordAuthor Commented:
Hi xterm,

To be more clear, let me describe the situation.

1. The main script (let's name is main.sh )should get one date input in yyyy-mm-dd format.
     ./main.sh 2011-10-05
      
2. calculate previous week date range
    case 1 when input date parameter 2011-10-05 (YYYY-MM-DD)
    Then Previous week range  = 2011-09-26 (YYYY-MM-DD)  - 2011-10-03 (YYYY-MM-DD)
    Now the script should spit out 2 date sets since the start and end lies in 2 different month
            2011-09-26 to 2011-09-30  -- month of September
            2011-10-03  to  2011-10-03   --month of october
     Then script triggers another 2 parametrized scripts
            e.g.  ~/test.sh --from  2011-09-26 --to 2011-09-30
                  ~/test.sh --from   2011-10-03  --to 2011-10-03  
 
      ELSE
      
    case 2 when input date parameter 2011-10-15 (YYYY-MM-DD)
    Then Previous week range  = 2011-10-03  - 2011-10-10
    Now since the both start and end is in the same month (October)
            2011-10-03 to 2011-10-10  -- month of October
           
     Then script triggers only 1 parametrized script
            e.g.  ~/test.sh --from  2011-10-03 --to 2011-10-10

                  Hope this helps !
                  
Thanks !
0
 
xtermCommented:
What constiutes the "previous week"?  Your example takes Wed 10/5 and then calculates Mon 09/26 to Mon 10/03 which is 8 days, not 7.

Do you mean to say that it should be Mon 09/26 -> Sun 10/02?
0
Visualize your virtual and backup environments

Create well-organized and polished visualizations of your virtual and backup environments when planning VMware vSphere, Microsoft Hyper-V or Veeam deployments. It helps you to gain better visibility and valuable business insights.

 
losforwordAuthor Commented:
Hi xterm,

you are right it should be Mon 09/26 -> Sun 10/02.

 So case when input date parameter 2011-10-05 the date split should be
                                                     2011-09-26 to 2011-09-30
                                                     2011-10-01 to 2011-10-02

           then  execute 2 shell script.

In the case when the date imput parameter is 2011-10-15. Date range is in the same month, the script needs to split the date like
                     2011-10-03 to 2011-10-09  -- month of October
           
     Then script triggers only 1 parametrized script
            e.g.  ~/test.sh --from  2011-10-03 --to 2011-10-09

Sorry for the confusion.
0
 
xtermCommented:
No worries, I got it and will have you a script momentarily.
0
 
losforwordAuthor Commented:
also note that test.sh is the another shell scipts paramerized by date

usage --to <YYYY-MM-DD> --from  <YYYY-MM-DD>
0
 
xtermCommented:
This was crazy hard, but I think I got it.   Here are some sample outputs, and attached is the bash script.  As you can see it takes into account leap years, and also year boundaries:


[xterm@home ee]$ ./calc.sh 2009-10-05
~/test.sh --to 2009-09-28 --from 2009-09-30
~/test.sh --to  2009-10-01 --from 2009-10-04

[xterm@home ee]$ ./calc.sh 2009-01-07
~/test.sh --to 2008:12:31 --from 2008-12-31
~/test.sh --to  2009-01-01 --from 2009-01-04

[xterm@home ee]$ ./calc.sh 2008-03-07
~/test.sh --to 2008-02-25 --from 2008-02-29
~/test.sh --to  2008-03-01 --from 2008-03-02

#!/bin/sh

# MAKE SURE ARGUMENT WAS PASSED
if [ -z $1 ]; then
        echo "Usage: `basename $0` [YYYY-MM-DD]"
        exit 1
fi

# CHECK FOR 2 DASHES
if [ `echo $1 | tr "-" "\n" | wc -l` -ne 3 ]; then
        echo "`basename $0`:  Incorrect format '$1'"
        exit 1
fi

# FIND HOW MANY DAYS AGO THIS HAPPENED
EPOCHTHEN=`date --date "$1" +%s`
EPOCHNOW=`date +%s`
SECONDS=`expr $EPOCHNOW - $EPOCHTHEN`
DAYS=`echo "$SECONDS / 86400" | bc -l | cut -d. -f1`
DECDAYS=`echo "$SECONDS / 86400" | bc -l`
FOO=`echo $DECDAYS | cut -d. -f2 | cut -c1`
# ROUND DOWN FRACTIONS
if [ $FOO -ge 5 ]; then DAYS=`expr $DAYS - 1`; fi

# FIND MOST RECENT SUNDAY, AND THE MONDAY BEFORE IT
SUN_DAYS_AGO=`date --date "$1" +%u`
MON_DAYS_AGO=`expr $SUN_DAYS_AGO + 7 + $DAYS`
SUN_DAYS_AGO=`expr $SUN_DAYS_AGO + 1 + $DAYS`
START_DATE=`date --date "$MON_DAYS_AGO days ago" +%Y-%m-%d`
END_DATE=`date --date "$SUN_DAYS_AGO days ago" +%Y-%m-%d`

# FIND IF THE END YEAR IS A LEAP YEAR
YEAR=`echo $END_DATE | cut -d- -f1`
if [ $[$YEAR % 400] -eq "0" ]; then
        LEGEND="01:31,02:29,03:31,04:30,05:31,06:30,07:31,08:31,09:30,10:31,11:30,12:31"
elif [ $[$YEAR % 4] -eq 0 ]; then
        if [ $[$YEAR % 100] -ne 0 ]; then
                LEGEND="01:31,02:29,03:31,04:30,05:31,06:30,07:31,08:31,09:30,10:31,11:30,12:31"
        else
                LEGEND="01:31,02:28,03:31,04:30,05:31,06:30,07:31,08:31,09:30,10:31,11:30,12:31"
        fi
else
        LEGEND="01:31,02:28,03:31,04:30,05:31,06:30,07:31,08:31,09:30,10:31,11:30,12:31"
fi

# SEE IF THEY'RE IN DIFFERENT MONTHS
MON1=`echo $START_DATE | cut -d- -f2`
MON2=`echo $END_DATE | cut -d- -f2`
if [ $MON2 -ne $MON1 ]; then
        # SEE IF THEY'RE IN DIFFERENT YEARS TOO
        YEAR1=`echo $START_DATE | cut -d- -f1`
        YEAR2=$YEAR
        # RANGE ENCOMPASSES TWO MONTHS
        END_DAY1=`echo $LEGEND | tr "," "\n" | grep ^$MON1: | cut -d: -f2`
        END_DATE1="$YEAR-$MON1-$END_DAY1"
        if [ $YEAR2 -gt $YEAR1 ]; then
                START_DATE="$YEAR1:$MON1:$END_DAY1"
                END_DATE1="$YEAR1-$MON1-$END_DAY1"
        fi
        START_DATE2="$YEAR-$MON2-01"
        echo "~/test.sh --to $START_DATE --from $END_DATE1"
        echo "~/test.sh --to  $START_DATE2 --from $END_DATE"
else
        # WE ARE IN THE SAME MONTH
        echo "~/test.sh --to $START_DATE --from $END_DATE "
fi

Open in new window

0
 
xtermCommented:
BTW, to make it actually execute your commands instead of just echo'ing them, change lines 61-62, and 65 by removing the echo and the double quote up front, and the double quote on the end of the line.
0
 
TintinCommented:
Whoa xterm.  That's really complicating it.

Here's a compact solution.

#!/bin/bash
start=$1
TS=%Y-%m-%d

sw=$(date -d "$start - 1 week"  +$TS)
sd=$(date -d "$start - 1 week"  +%w)
let sd--

sdate=$(date --date "$sw - $sd days" +$TS)
edate=$(date -d "$sdate +6 days" +$TS)

if [[ ${sdate:5:2} == ${edate:5:2} ]]
then
   echo test.sh --from $sdate --to $edate
else
   echo test.sh --from $sdate --to $(date --date "${sdate%-*}-01 +1 month -1 day" +%Y-%m-%d)
   echo test.sh --from ${edate%-*}-10 --to $edate
fi

Open in new window



Output

./main.sh 2011-10-05
test.sh --from 2011-09-26 --to 2011-09-30
test.sh --from 2011-10-10 --to 2011-10-02

./main.sh 2011-10-15
test.sh --from 2011-10-03 --to 2011-10-09

0
 
losforwordAuthor Commented:
Named the script as main.sh and ran it
$ ./main.sh 2011-01-03
Ok Period lies in 2 months
First trigger date is 2010:12:31 to 2010-12-31  --(NOTE THE FORMATTING ISSUE)
Second trigger date is 2011-01-01 --from 2011-01-01

Also the calculation is incorrect.

The correct calculation should be
2010-12-27 --from 2010-12-31
2011-01-01 --from 2011-01-02




0
 
losforwordAuthor Commented:
This is meant of xterm solution.

Named the script as main.sh and ran it
$ ./main.sh 2011-01-03
Ok Period lies in 2 months
First trigger date is 2010:12:31 to 2010-12-31  --(NOTE THE FORMATTING ISSUE)
Second trigger date is 2011-01-01 --from 2011-01-01

Also the calculation is incorrect.

The correct calculation should be
2010-12-27 --from 2010-12-31
2011-01-01 --from 2011-01-02
0
 
xtermCommented:
whoops, okay, let me fix that.
0
 
TintinCommented:
Using my solution produces the correct output

./main.sh 2011-01-03
test.sh --from 2010-12-27 --to 2010-12-31
test.sh --from 2011-01-10 --to 2011-01-02
0
 
losforwordAuthor Commented:
Hi Tintin,

your output seems to be wrong:

Your Output:
Output

./main.sh 2011-10-05
test.sh --from 2011-09-26 --to 2011-09-30
test.sh --from 2011-10-10 --to 2011-10-02

./main.sh 2011-10-15
test.sh --from 2011-10-03 --to 2011-10-09


Correct Output should be
Output

./main.sh 2011-10-05
test.sh --from 2011-09-26 --to 2011-09-30
test.sh --from 2011-10-01 --to 2011-10-02

But this one is correct in your case
./main.sh 2011-10-15
test.sh --from 2011-10-03 --to 2011-10-09
0
 
TintinCommented:
whoops.  minor typo.

echo test.sh --from ${edate%-*}-10 --to $edate

Open in new window


should be
echo test.sh --from ${edate%-*}-01 --to $edate

Open in new window

0
 
losforwordAuthor Commented:
Thanks Tintin
0

Featured Post

Transaction-level recovery for Oracle database

Veeam Explore for Oracle delivers low RTOs and RPOs with agentless transaction log backup and transaction-level recovery of Oracle databases. You can restore the database to a precise point in time, even to a specific transaction.

  • 7
  • 6
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now