I want to find some information between two dates (Last Friday of Month and it's successive Sunday).
For now, I'm adding all the dates(formatted as mm/dd/yy) in a file dates_file.in like this:
05/29/20,05/31/20
06/26/20,06/28/20
07/31/20,08/02/20
and running a for loop like this
for dates in `cat dates_file.in`
do
date1=`echo $dates | cut -d',' -f1`
date2=`echo $dates | cut -d',' -f2`
xyz_cmd -start="$date1" -end="$date2" -report_parms
done
Is there a way I can use calendar to fetch the dates or export the dates to dates_file.in
file?
OS is RHEL 6.5
Using bash and GNU date:
# a function to return a positive number for "x % y"
# e.g. `floorMod -1 7` outputs: 6
floorMod() { local num=$1 div=$2; echo $(( ((num % div) + div) % div )); }
formatDate() { local y=$1 m=$2 d=$3 delta=$4; date -d "$y-$m-$d $delta" "+%m/%d/%y"; }
year=2020
for month in {1..12}; do
# get the last day of this month, and its day of the week
read -r day dow < <(date -d "$year-$month-01 + 1 month - 1 day" "+%d %w")
# decrement until we find Friday
until ((dow == 5)); do
((day--))
dow=$(floorMod $((dow - 1)) 7)
done
start=$(formatDate $year $month $day)
end=$(formatDate $year $month $day "+2 days")
echo "$start $end"
done
01/31/20 02/02/20
02/28/20 03/01/20
03/27/20 03/29/20
04/24/20 04/26/20
05/29/20 05/31/20
06/26/20 06/28/20
07/31/20 08/02/20
08/28/20 08/30/20
09/25/20 09/27/20
10/30/20 11/01/20
11/27/20 11/29/20
12/25/20 12/27/20
Could you please try following, using cal here.
cat script.ksh
month="$1"
year="$2"
####To get current month's Friday.
cal "$month" "$year" 2>/dev/null |
tac |
awk '
NF>=6{
print "current month last Friday is:"$(NF-1)" and Sunday is:"$NF
exit
}
'
Related
I'm creating a condition that checks the actual date in epoch format and compares another string in epoch format; if the strings are more than 10 days old, do something...
i tried something like this:
#!/bin/bash
timeago='10 days ago'
actual_date=$(date --date "now" +'%s')
last_seen_filter=$(date --date "$timeago" +'%s')
echo "INFO: actual_date=$actual_date, last_seen_filter=$last_seen_filter" >&2
if [ "$actual_date" -lt "$last_seen_filter" ]; then
echo "something"
else
echo "do something"
fi
or
#!/bin/bash
cutoff=$(date -d '10 days ago' +%s)
key="1624684050 1624688000"
while read -r "$key"
do
age=$(date -d "now" +%s)
if (($age < $cutoff))
then
printf "Warning! key %s is older than 10 days\n" "$key" >&2
fi
done < input
That's not enough for what I need, I have epoch dates in a file called converted_data, i need to include this strings on if comparision.
1624684050
1634015250
1614661650
1622005650
It's not clear what you're trying to do but maybe this with GNU awk will get you started:
$ awk '
BEGIN { today=strftime("%F") }
{
secs = $0
days = 0
date = strftime("%F",secs)
while ( strftime("%F",secs+=(24*60*60)) < today ) {
++days
}
print $0":", date, "->", today, "=", days
}
' file
1624684050: 2021-06-26 -> 2021-06-13 = 0
1634015250: 2021-10-12 -> 2021-06-13 = 0
1614661650: 2021-03-01 -> 2021-06-13 = 102
1622005650: 2021-05-26 -> 2021-06-13 = 17
The 0s for future dates are because you only asked about 10-days past dates so I don't care to adapt for both past and future deltas. I also didn't put much thought into it so check the logic and the math!
Hi I have written down some bash to generate the date in format YYYYDDMM.
I know that is not perfect but the final thing will be:
Generate a range of 2 dates that are 31 days apart from each other and start with a minimum of today + one day and the older ones end at the end of this year. In format YYYYMMDD
month="$(awk -v min=1 -v max=12 'BEGIN{srand(); print int(min+rand()*(max-min+1))}')"
day="$(awk -v min=1 -v max=31 'BEGIN{srand(); print int(min+rand()*(max-min+1))}')"
year="$(date +%Y)"
if (( "${month}" < 10 )); then
month_proper="$(echo 0"${month}")"
else
month_proper="$(echo "${month}")"
fi
if (( "${day}" < 10 )); then
day_proper="$(echo 0"${day}")"
else
day_proper="$(echo "${day}")"
fi
echo month "${month}"
echo month with 0 if smaller than 10 : "${month_proper}"
echo day "${day}"
echo day with 0 smaller than 10 : "${day_proper}"
ok="$(date -d ""$year""${month_proper}""${day_proper}"" +"%Y%m%d")"
echo date with proper format "${ok}"
date -d "$year""${month_proper}""${day_proper}"
In which direction would I have to expand this script to get the final result? I already have the date generation, but there is no checking if there is one day ahead of today.
Requirements specify range nearly exactly (it is Dec-31 till Jan-31 next year), so you can write
a_fmt=`date -d "tomorrow" +%Y1231`
a_num=`date -d "$a_fmt" +%s`
b_num=$(( a_num + 31 * 24 * 3600 ))
b_fmt=`date -d #$b_num +%Y%m%d`
echo "Range is '$a_fmt'..'$b_fmt'"
hi I want to get the week number of the current month in bash, has someone an idea on how to do this? I search the date option, there is noting for week number only absolute week number.
WEEK => current week of month eg. today 22.05 WEEK=4
I found a few options, but there is no option, which works for every month and every date some give error if leading 0 some if month is even.
Here is a solution:
this_month=$(ncal -w | tail -1 | awk '{print NF}')
total_this_month=$(ncal -w | tail -1 | awk '{print $NF}')
this_week=$(date +%W)
this_monthweek=$(($this_week - $total_this_month + $this_month))
echo -e "today $(date +%d.%m) WEEK=$this_monthweek"
Hope, this is what you are looking for.
Edit:
A solution without ncal
this_month=$(date -d "20170501" +%V)
end_this_month=$(date -d "20170531" +%V)
total_this_month=$(($end_this_month - $this_month + 1))
this_week=$(date +%W)
this_monthweek=$(($this_week - $end_this_month + $total_this_month))
echo -e "today $(date +%d.%m) WEEK=$this_monthweek"
I found this solution working with AIX, but it works on any Unix
#!/bin/bash
year=$(date +'%Y')
month=$(date +'%m')
day=$(date +'%e' | tr -d '[:blank:]')
WEEKNUM=$(cal ${month} ${year} | grep -v "[[:alpha:]]" | grep -nw ${day} | cut -f1 -d':')
echo "WEEKNUM ${WEEKNUM}"
On Linux you can switch first day of the week to fit your needs
On AIX, first day of the week is inherited by locale
I figured something out, but I am not sure if it works for every month and week of the year, and I have not idea on how to manipulate the date to test it
current_week="$(date +%V)"
last_of_month="$(date --date "-"$(date +%d)" days +1 month" +%Y-%m-%d)"
last_of_month_week="$(date --date="${last_of_month}" +%V)"
week_number="$((${current_week} - ${last_of_month_week} + 5))"
I need to sort data on a weekly base and all i have are dates in a logfile.
Therefore to sort out data per week i would like to create a list with the dates of all mondays for a given year. I have tried to work something out and the only idea i currently have is to use ncal with year and month as argument looping over all months and extracting all mondays. Isn't there a more efficient way?
To get all mondays, by getting all dates and filtering by Mondays:
for i in `seq 0 365`
do date -d "+$i day"
done | grep Mon
Of course, you could also take a monday and keep incrementing by 7 days.
hope that's what you mean. Below can be changed to vary the output formats of the dates.
date command can be used for that, dunno if ncal is any more/less efficient.
I know you went for "binning" now, but here is a more readable v.
$ cat /tmp/1.sh
#!/bin/bash
test -z "$year" && {
echo "I expect you to set \$year environment variable"
echo "In return I will display you the Mondays of this year"
exit 1
}
# change me if you would like the date format to be different
# man date would tell you all the combinations you can use here
DATE_FORMAT="+%Y-%m-%d"
# change me if you change the date format above. I need to be
# able to extract the year from the date I'm shoing you
GET_YEAR="s/-.*//"
# this value is a week, in milliseconds. Changing it would change
# what I'm doing.
WEEK_INC=604800
# Use another 3-digit week day name here, to see dates for other week days
DAY_OF_WEEK=Mon
# stage 1, let's find us the first day of the week in this year
d=1
# is it DAY_OF_WEEK yet?
while test "$(date -d ${year}-1-${d} +%a)" != "$DAY_OF_WEEK"; do
# no, so let's look at the next day
d=$((d+1));
done;
# let's ask for the milliseconds for that DAY_OF_WEEK that I found above
umon=$(date -d ${year}-1-${d} +%s)
# let's loop until we break from inside
while true; do
# ndate is the date that we testing right now
ndate=$(date -d #$umon "$DATE_FORMAT");
# let's extract year
ny=$(echo $ndate|sed "$GET_YEAR");
# did we go over this year? If yes, then break out
test $ny -ne $year && { break; }
# move on to next week
umon=$((umon+WEEK_INC))
# display the date so far
echo "$ndate"
done
No need to iterate over all 365 or 366 days in the year. The following executes date at most 71 times.
#!/bin/bash
y=2011
for d in {0..6}
do
if (( $(date -d "$y-1-1 + $d day" '+%u') == 1)) # +%w: Mon == 1 also
then
break
fi
done
for ((w = d; w <= $(date -d "$y-12-31" '+%j') - 1; w += 7))
do
date -d "$y-1-1 + $w day" '+%Y-%m-%d'
done
Output:
2011-01-03
2011-01-10
2011-01-17
2011-01-24
2011-01-31
2011-02-07
2011-02-14
2011-02-21
2011-02-28
2011-03-07
. . .
2011-11-28
2011-12-05
2011-12-12
2011-12-19
2011-12-26
Another option that I've come up based on the above answers. The start and end date can now be specified.
#!/bin/bash
datestart=20110101
dateend=20111231
for tmpd in {0..6}
do
date -d "$datestart $tmpd day" | grep -q Mon
if [ $? = 0 ];
then
break
fi
done
for ((tmpw = $tmpd; $(date -d "$datestart $tmpw day" +%s) <= $(date -d "$dateend" +%s); tmpw += 7))
do
echo `date -d "$datestart $tmpw day" +%d-%b-%Y`
done
You can get the current week number using date. Maybe you can sort on that:
$ date +%W -d '2011-02-18'
07
I need to know the first monday of the current month using Cygwin bash.
One Liner:
d=$(date -d "today 1300" '+%Y%m01'); w=$(date -d $d '+%w'); i=$(( (8 - $w) % 7)); answer=$(( $d + $i ));
The result is stored in $answer. It uses working variables $d, $w, and $i.
Proof (assuming you just ran the one liner above):
echo $answer; echo $(date -d $answer '+%w')
Expected Result: Monday of current month in YYYYMMDD. On the next line, a 1 for the day of the week.
Expanded Proof (checks the next 100 month's Mondays):
for x in {1..100}; do d=$(date -d "+$x months 1300" '+%Y%m01'); w=$(date -d $d '+%w'); i=$(( (8 - $w) % 7)); answer=$(( $d + $i )); echo $answer; echo $(date -d $answer '+%w'); done | egrep -B1 '^[^1]$'
Expected Result: NOTHING
(If there are results, something is broken)
Breaking it down
The first statement gets the first day of the current month, and stores that in $d, formatted as YYYYMMDD.
The second statement gets the day of the week number of the date $d, and stores that in $w.
The third statement computes the increment of days to add and stores it in $i. Zero is perfectly valid here, because...
The last statement computes the sum of the date $d (as an integer) and the increment $i (as an integer). This works because the domain of the $i is 0 to 6, and we will always start at the first day of the month. This can quickly be converted back to a date variable (see Proof for example of this).
This has been tested on BASH v4.1 (CentOS 6), v4.4 (Ubuntu), and v5 (Archlinux)
A one-liner--I hope it's correct
d=$(date -d date +%Y%m"01" +%u);date -d date +%Y%m"0"$(((9-$d)%7))
the variable d contains the day of week (1..7) where 1 is Monday
then I print the current year and month changing the day with $((9-$d))
This should do it, but I have no Cygwin here to test:
#!/bin/bash
# get current year and month:
year=$( date +"%Y" )
month=$( date +"%m" )
# for the first 7 days in current month :
for i in {1..7}
do
# get day of week (dow) for that date:
dow=$( date -d "${year}-${month}-${i}" +"%u" )" "
# if dow is 1 (Monday):
if [ "$dow" -eq 1 ]
then
# print date of that Monday in default formatting:
date -d "${year}-${month}-${i}"
break
fi
done
See manpage date(1) for more information.