how to expand date by week and by month in shell? - bash

In short, I want something works like this:
When I input a date like 2012-12-27 and want to expand the date by
week(start with Monday), it
outputs:2012-12-24,2012-12-25,2012-12-26,2012-12-27,2012-12-28,2012-12-29,2012-12-30
When I input a date like 2012-12-27 and want to expand the date by month, it outputs:2012-12-01,2012-12-02 ... 2012-12-31
or, how can I group a bunch of dates by week? e.g. when I input2012-12-01,2012-12-02 ... 2012-12-31. It outputs:2012-12-01,2012-12-02|2012-12-03 ... 2012-12-09|2012-12-10 ... 2012-12-16|...|2012-12-31
I have no idea how to complete this, any clue may be helpful!

DAYSECS=86400 # seconds in a day
WEEKSECS=604800
echo "Expand on week:"
g_epoch=$(date +"%s" -d $1) # given date as seconds from epoch
g_dayno=$(date +"%u" -d $1) # given date as day of week
g_month=$(date +"%m" -d $1) # given month
g_year=$(date +"%Y" -d $1) # given year
s_epoch=$(($g_epoch - $DAYSECS * ($g_dayno - 1)))
e_epoch=$(($s_epoch + $WEEKSECS))
for etime in $(seq $s_epoch $DAYSECS $e_epoch); do
date +"%Y-%m-%d" -d "#$etime"
done
echo "Expand on month:"
s_epoch=$(date +"%s" -d "$g_year-$g_month-01")
e_epoch=$(($s_epoch + 4 * $WEEKSECS))
for etime in $(seq $s_epoch $DAYSECS $e_epoch); do
if [ $(date +"%m" -d "#$etime") -ne "$g_month" ]; then
break;
fi
date +"%Y-%m-%d" -d "#$etime"
done

The script below work out from #perreal, I leave it here because:
It shows the power of GNU date.
It makes #perreal 's idea more clear and more universal.
Thank you, perreal!
Here it is
dd="2012-12-27" # test date
DAYSECS=86400 # seconds in a day
echo "expand by week:"
s_epoch=$(date +%s -d "$dd -$(($(date +%u -d $dd) - 1)) day") # start date of the week
e_epoch=$(date +%s -d "1970-01-01 00:00:00 +0000 +${s_epoch} seconds +6 days") # end date of the week
for etime in $(seq $s_epoch $DAYSECS $e_epoch); do
date +"%Y-%m-%d" -d "#$etime";
done
echo "expand by month:"
s_epoch=$(date +%s -d "$dd -$(($(date +%d -d $dd) - 1)) day") # start date of the month
e_epoch=$(date +%s -d "1970-01-01 00:00:00 +0000 +${s_epoch} seconds +1 month -1 day") # end date of the month
for etime in $(seq $s_epoch $DAYSECS $e_epoch); do
date +"%Y-%m-%d" -d "#$etime";
done

Related

Differences between two dates with %b %d %Y format

I was hoping to get some help with finding the difference in days between two dates.
Date 1: Sysdate
Date2: Mar 20 2022 (future)
What I was trying to do is convert it to EPOCH time, subtract and then divide by 86400 to get the number of days between the two dates. However, I've having issues with the systax. Here's what I've tried:
days_remaining=('date "+%s" -d "Mar 20 2022"'-'date "+%s" -d "$(date '+%b %d %Y')"')/86400
But the above isn't working. Any assistance would be appreciated.
To do calculations in bash you need an arithmetic context (( )). Also, to execute your date commands you have to put them inside $() instead of string quotes ''.
By the way: The last date command in date "+%s" -d "$(date '+%b %d %Y') isn't necessary. date -d 0:00 +%s will print the same unix time.
(( days_remaining = ($(date -d "Mar 20 2022" +%s) - $(date -d 0:00 +%s)) / 86400 ))
you can use this
days_remaining=$(($(($(date "+%s" -d "Mar 20 2022") - $(date "+%s" -d "$(date '+%b %d %Y')"))) / 86400))

How can we get weekday based on given date in unix

From a given date in %m-%d-%Y format we should determine what day it is.
Example: for the date 09-01-2017 output should be Friday
Very simple. Just use the date command itself with correct options.
$ date -j -f '%m-%d-%Y' "09-01-2017" +'%A'
Friday
If you have your date like this:
d="09-01-2017"
you need to reformat it to "YYYY-MM-DD"
date -d $(echo $d|awk -F- '{print $3 "-" $1 "-" $2}') +%A # DOW
Here is what I usually do. I would use the date function.
you can do 'man date' and find options.
$ d=2020-08-20 \
$ date -d "$d" +%u \
4 \
$ date -d "$d" +%A \
Thursday
DayOfWeek=$(date +%A)
This would yield the day of week monday-sunday
If your input date is strictly in the format MM-DD-YYYY, use the following
IFS='-' read -ra ADDR <<< "09-01-2017"
formattedDate=${ADDR[2]}-${ADDR[0]}-${ADDR[1]}
date -d $formattedDate +%A
The first line tokenizes the components of the date and the second rearranges them
You can pass it as %m/%d%Y which gets recognized by the date command.
$ date --date="`echo 09-01-2017| sed -e 's/-/\//g' `" +'%A'
Friday
To verify it, pass %F to get it in ISO format
$ date --date="`echo 09-01-2017| sed -e 's/-/\//g' `" +'%A %F'
Friday 2017-09-01
date +%A
# let us see in a for loop
for i in {1..7}; do date +%A --date=+${i}day; done
Wednesday
Thursday
Friday
Saturday
Sunday
Monday
Tuesday

Shell script to get difference between two dates

If there are dates as 2010-06-01 and another as 2010-05-15
Using shell script or date command how to get the number of days between the two dates
Thanks..
Using only date and shell arithmetics:
echo $((($(date -d "2010-06-01" "+%s") - $(date -d "2010-05-15" "+%s")) / 86400))
There's a solution that almost works: use the %s date format of GNU date, which prints the number of seconds since 1970-01-01 00:00. These can be subtracted to find the time difference between two dates.
echo $(( ($(date -d 2010-06-01 +%s) - $(date -d 2010-05-15 +%s)) / 86400))
But the following displays 0 in some locations:
echo $((($(date -d 2010-03-29 +%s) - $(date -d 2010-03-28 +%s)) / 86400))
Because of daylight savings time, there are only 23 hours between those times. You need to add at least one hour (and at most 23) to be safe.
echo $((($(date -d 2010-03-29 +%s) - $(date -d 2010-03-28 +%s) + 43200) / 86400))
Or you can tell date to work in a timezone without DST.
echo $((($(date -u -d 2010-03-29 +%s) - $(date -u -d 2010-03-28 +%s)) / 86400))
(POSIX says to call the reference timezone is UTC, but it also says not to count leap seconds, so the number of seconds in a day is always exactly 86400 in a GMT+xx timezone.)
OSX date is different than GNU date. Got it working like this in OSX. This is not portable solution.
start_date=$(date -j -f "%Y-%m-%d" "2010-05-15" "+%s")
end_date=$(date -j -f "%Y-%m-%d" "2010-06-01" "+%s")
echo $(( ($end_date - $start_date) / (60 * 60 * 24) ))
Idea is still same as in the other answers. Convert dates to epoch time, subtract and convert result to days.
Got it
d1=`date +%s -d $1`
d2=`date +%s -d $2`
((diff_sec=d2-d1))
echo - | awk -v SECS=$diff_sec '{printf "Number of days : %d",SECS/(60*60*24)}'
thanks..
Gnu date knows %j to display the day in year:
echo $(($(date -d 2010-06-01 +%j) - $(date -d 2010-05-15 +%j)))
crossing year-boundaries will give wrong results, but since you gave fixed dates ...

Get the date (a day before current time) in Bash

How can I print the date which is a day before current time in Bash?
if you have GNU date and i understood you correctly
$ date +%Y:%m:%d -d "yesterday"
2009:11:09
or
$ date +%Y:%m:%d -d "1 day ago"
2009:11:09
If you have BSD (OSX) date you can do it like this:
date -j -v-1d
Wed Dec 14 15:34:14 CET 2011
Or if you want to do date calculations on an arbitrary date:
date -j -v-1d -f "%Y-%m-%d" "2011-09-01" "+%Y-%m-%d"
2011-08-31
date --date='-1 day'
MAC OSX
For yesterday's date:
date -v-1d +%F
where 1d defines current day minus 1 day. Similarly,
date -v-1w +%F - for previous week date
date -v-1m +%F - for previous month date
IF YOU HAVE GNU DATE,
date --date="1 day ago"
More info: https://www.cyberciti.biz/tips/linux-unix-get-yesterdays-tomorrows-date.html
Sorry not mentioning I on Solaris system.
As such, the -date switch is not available on Solaris bash.
I find out I can get the previous date with little trick on timezone.
DATE=`TZ=MYT+16 date +%Y-%m-%d_%r`
echo $DATE
Well this is a late answer,but this seems to work!!
YESTERDAY=`TZ=GMT+24 date +%d-%m-%Y`;
echo $YESTERDAY;
Advanced Bash-scripting Guide
date +%Y:%m:%d -d "yesterday"
For details about the date format see the man page for date
date --date='-1 day'
date -d "yesterday" '+%Y-%m-%d'
or
date=$(date -d "yesterday" '+%Y-%m-%d')
echo $date
Use Perl instead perhaps?
perl -e 'print scalar localtime( time - 86400 ) . "\n";'
Or, use nawk and (ab)use /usr/bin/adb:
nawk 'BEGIN{printf "0t%d=Y\n", srand()-86400}' | adb
Came across this too ... insane!
/usr/bin/truss /usr/bin/date 2>&1 | nawk -F= '/^time\(\)/ {gsub(/ /,"",$2);printf "0t%d=Y\n", $2-86400}' | adb
date --date='-1 day'
Not very sexy but might do the job:
perl -e 'my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time - 86400);$year += 1900; $mon+= 1; printf ("YESTERDAY: %04d%02d%02d \n", $year, $mon, $mday)'
Formated from "martin clayton" answer.
You could do a simple calculation, pimped with an regex, if the chosen date format is 'YYYYMM':
echo $(($(date +"%Y%m") - 1)) | sed -e 's/99$/12/'
In January of 2020 it will return 201912 ;-)
But, it's only a workaround, when date does not have calculation options and other dateinterpreter options (e.g. using perl) not available ;-)
short answer (GNU format):
date +%Y-%m-%d -d "-2 day"
if you are using OSX, but you need create for GNU compatible, install coreutils first
brew install coreutils
then edit your profile with:
#gnu coreutils first
export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
re-start your terminal, and now you able to use GNU format!
yesterday=`date -d "-1 day" %F`
Puts yesterday's date in YYYY-MM-DD format into variable $yesterday.
#!/bin/bash
OFFSET=1;
eval `date "+day=%d; month=%m; year=%Y"`
# Subtract offset from day, if it goes below one use 'cal'
# to determine the number of days in the previous month.
day=`expr $day - $OFFSET`
if [ $day -le 0 ] ;then
month=`expr $month - 1`
if [ $month -eq 0 ] ;then
year=`expr $year - 1`
month=12
fi
set `cal $month $year`
xday=${$#}
day=`expr $xday + $day`
fi
echo $year-$month-$day
DST aware solution:
Manipulating the Timezone is possible for changing the clock some hours. Due to the daylight saving time, 24 hours ago can be today or the day before yesterday.
You are sure that yesterday is 20 or 30 hours ago. Which one? Well, the most recent one that is not today.
echo -e "$(TZ=GMT+30 date +%Y-%m-%d)\n$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1
The -e parameter used in the echo command is needed with bash, but will not work with ksh. In ksh you can use the same command without the -e flag.
When your script will be used in different environments, you can start the script with #!/bin/ksh or #!/bin/bash. You could also replace the \n by a newline:
echo "$(TZ=GMT+30 date +%Y-%m-%d)
$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1
Try the below code , which takes care of the DST part as well.
if [ $(date +%w) -eq $(date -u +%w) ]; then
tz=$(( 10#$gmthour - 10#$localhour ))
else
tz=$(( 24 - 10#$gmthour + 10#$localhour ))
fi
echo $tz
myTime=`TZ=GMT+$tz date +'%Y%m%d'`
Courtsey Ansgar Wiechers
date +%Y:%m:%d|awk -vFS=":" -vOFS=":" '{$3=$3-1;print}'
2009:11:9

YYYY-MM-DD format date in shell script

I tried using $(date) in my bash shell script, however, I want the date in YYYY-MM-DD format.
How do I get this?
In bash (>=4.2) it is preferable to use printf's built-in date formatter (part of bash) rather than the external date (usually GNU date).
As such:
# put current date as yyyy-mm-dd in $date
# -1 -> explicit current date, bash >=4.3 defaults to current time if not provided
# -2 -> start time for shell
printf -v date '%(%Y-%m-%d)T\n' -1
# put current date as yyyy-mm-dd HH:MM:SS in $date
printf -v date '%(%Y-%m-%d %H:%M:%S)T\n' -1
# to print directly remove -v flag, as such:
printf '%(%Y-%m-%d)T\n' -1
# -> current date printed to terminal
In bash (<4.2):
# put current date as yyyy-mm-dd in $date
date=$(date '+%Y-%m-%d')
# put current date as yyyy-mm-dd HH:MM:SS in $date
date=$(date '+%Y-%m-%d %H:%M:%S')
# print current date directly
echo $(date '+%Y-%m-%d')
Other available date formats can be viewed from the date man pages (for external non-bash specific command):
man date
Try: $(date +%F)
The %F option is an alias for %Y-%m-%d
You can do something like this:
$ date +'%Y-%m-%d'
$(date +%F)
output
2018-06-20
Or if you also want time:
$(date +%F_%H-%M-%S)
can be used to remove colons (:) in between
output
2018-06-20_09-55-58
You're looking for ISO 8601 standard date format, so if you have GNU date (or any date command more modern than 1988) just do: $(date -I)
date -d '1 hour ago' '+%Y-%m-%d'
The output would be 2015-06-14.
With recent Bash (version ≥ 4.2), you can use the builtin printf with the format modifier %(strftime_format)T:
$ printf '%(%Y-%m-%d)T\n' -1 # Get YYYY-MM-DD (-1 stands for "current time")
2017-11-10
$ printf '%(%F)T\n' -1 # Synonym of the above
2017-11-10
$ printf -v date '%(%F)T' -1 # Capture as var $date
printf is much faster than date since it's a Bash builtin while date is an external command.
As well, printf -v date ... is faster than date=$(printf ...) since it doesn't require forking a subshell.
I use the following formulation:
TODAY=`date -I`
echo $TODAY
Checkout the man page for date, there is a number of other useful options:
man date
if you want the year in a two number format such as 17 rather than 2017, do the following:
DATE=`date +%d-%m-%y`
I use $(date +"%Y-%m-%d") or $(date +"%Y-%m-%d %T") with time and hours.
I used below method. Thanks for all methods/answers
ubuntu#apj:/tmp$ datevar=$(date +'%Y-%m-%d : %H-%M')
ubuntu#apj:/tmp$ echo $datevar
2022-03-31 : 10-48
Whenever I have a task like this I end up falling back to
$ man strftime
to remind myself of all the possibilities for time formatting options.
Try to use this command :
date | cut -d " " -f2-4 | tr " " "-"
The output would be like: 21-Feb-2021
#!/bin/bash -e
x='2018-01-18 10:00:00'
a=$(date -d "$x")
b=$(date -d "$a 10 min" "+%Y-%m-%d %H:%M:%S")
c=$(date -d "$b 10 min" "+%Y-%m-%d %H:%M:%S")
#date -d "$a 30 min" "+%Y-%m-%d %H:%M:%S"
echo Entered Date is $x
echo Second Date is $b
echo Third Date is $c
Here x is sample date used & then example displays both formatting of data as well as getting dates 10 mins more then current date.
You can set date as environment variable and later u can use it
setenv DATE `date "+%Y-%m-%d"`
echo "----------- ${DATE} -------------"
or
DATE =`date "+%Y-%m-%d"`
echo "----------- ${DATE} -------------"
echo "`date "+%F"`"
Will print YYYY-MM-DD
Try this code for a simple human readable timestamp:
dt=$(date)
echo $dt
Output:
Tue May 3 08:48:47 IST 2022

Resources