How to get yesterday and day before yesterday in linux? - linux

I want to get sysdate -1 and sysdate -2 in variable and echo it. I am using below query which gives todays date as output.
#! /bin/bash
tm=$(date +%Y%d%m)
echo $tm
How to get yesterday and day before yesterdays date?

Here is another one way,
For yesterday,
date -d '-1 day' '+%Y%d%m'
For day before yesterday,
date -d '-2 day' '+%Y%d%m'

Yesterday date
YES_DAT=$(date --date=' 1 days ago' '+%Y%d%m')
Day before yesterdays date
DAY_YES_DAT=$(date --date=' 2 days ago' '+%Y%d%m')
For any date you can use below one default it take 1 days. If its passing value that day before it take
ANY_YES_DAT=$(date --date=' $1 days ago' '+%Y%d%m')

You can get the yesterday date by this:
date -d "yesterday 13:00 " '+%Y-%m-%d'
and day before yesterday by this:-
date -d "yesterday-1 13:00 " '+%Y-%m-%d'

For older versions of BSD date (on old versions of macOS for example) which don't provide a -v option, you can get yesterdays date by subtracting 86400 seconds (seconds in a day) from the current epoch.
date -r $(( $(date '+%s') - 86400 ))
Obviously, you can subtract 2 * 86400 away for the day for yesterday etc.
Edit: Add reference to old macOS versions.

Related

Comparing last modified date of a file and current date in shell script

I am trying to create a new file if the last modified date of the previously created file is less then the current date. Below is the code i tried but not sure getting what value as difference between last modified date and current date.
Code
LAST_MODIFIED_DATE=$(stat -c %y ${APPDIR}/data/XYZ.csv)
echo "LAST_MODIFIED_DATE ${LAST_MODIFIED_DATE}"
NOW=$(date +%s)
echo "NOW ${NOW}"
let diff=${NOW}-${LAST_MODIFIED_DATE}
echo "Diff ${diff}"
Result
LAST_MODIFIED_DATE 2021-08-03 10:30:56.627022878 -0500
NOW 1629354883
Diff 1629354883-2021-08-03 10:30:56.627022878 -0500
You should convert LAST_MODIFIED_DATE in seconds since 1970-01-01 first:
NOW="$(date +%s)"
LAST_MODIFIED_DATE="$(stat -c %y ${APPDIR}/data/XYZ.csv)"
LAST_MODIFIED_DATE_EPOCH="$(date +%s --date="$LAST_MODIFIED_DATE")"
diff=$(($NOW - $LAST_MODIFIED_DATE_EPOCH))
echo "Diff ${diff}"
But diff will be all the time positive unless the file ${APPDIR}/data/XYZ.csv was created with a date in the future.
If you want to test against a different date (for instance to check whether the file has been created in the last hour or not) you can modify the definition of NOW:
NOW="$(date +%s --date '1 hour ago')"

bash difference between 2 dates in bash by yyyy-mm-dd in N days [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I write a long script in bash and somehow I am able to print 2 dates in yyyy-mm-dd format.
My outputs are like 2019-12-30 and 2019-12-21
1st date is always yesterday date, my output won't print date function it just prints a value of date,
So. I need to tell bash that its a date and give me a difference in days.
#!/bin/bash
START=$(date --date=yesterday +%F)
END=$(date --date "2 days ago" +%F)
DIFF=$(( $END - $START ))
echo " $DIFF "
It shows me 85 only. how can I get the difference in dayes like "1" (2 days ago - yesterday)
I would appreciate if someone answer with some explanation
PS: i dont know if datediff is premade. the function of Linux, it's not in my centos 6
Expanding on my comment:
see the accepted answer for Quickly calculate date differences
The person who answered that question wrote a custom function called datediff:
$ datediff() {
d1=$(date -d "$1" +%s)
d2=$(date -d "$2" +%s)
echo $(( (d1 - d2) / 86400 )) days
}
We can use this same function to compare the 2 dates from the question:
$ START=$(date --date=yesterday +%F)
$ END=$(date --date "2 days ago" +%F)
$ echo "${START} : ${END}"
2019-12-30 : 2019-12-29
$ datediff "${START}" "${END}"
1 days

How I can get the next month in shell?

I would like to get the current and next months using shell script, I have tried this command:
$ date '+%b'
mar
$ date +"%B %Y" --date="$(date +%Y-%m-15) next month"
March 2018
But it always displays only the current month.
Could you please help me if there is something wrong with the commands.
$ date -d "next month" '+%B %Y'
April 2018
Check this post about specific caveats
Note: your command works just fine for me (archlinux, bash4, date GNU coreutils 8.29)
I wouldn't rely on date alone to do this. Instead, perform a little basic math on the month number.
this_month=$(date +%-m) # GNU extension to avoid leading 0
next_month=$(( this_month % 12 + 1 ))
next_month_name=$(date +%B --date "2018-$next_month-1")
Since you are using bash, you don't need to use date at all to get the current month; the built-in printf can call the underlying date/time routines itself, saving a fork.
$ printf -v this_month '%(%-m)T\n'
$ echo $this_month
3
What variant and version of date are you running? "Solaris 5.2" was never released, though SunOS 5.2 was a kernel in Solaris 2.2 (EOL in 1999). See the Solaris OS version history. The Solaris 10 (SunOS 5.10) man page for date does not support GNU's --date= syntax used in the question, so I'm guessing you're using some version of date from GNU coreutils.
Here's a solution using BSD date (note, this is academic in the face of BSD's date -v 1m):
date -jf %s $((1728000+$(date -jf %Y-%m-%d $(date +%Y-%m-15) +%s))) +"%B %Y"
There are three date calls here. BSD's date allows specifying a format (GNU can intuit most formats on its own). The parent call is the one that takes the final time (as seconds since the 1970 epoch), expressing it in the desired "Month Year" format. Seconds are determine by adding 20 days to the epoch time of the current month on the 15th day. Since no month has 15+20 days, this is always the following month.
Here's a direct translation of that logic to GNU date:
date +"%B %Y" --date="#$((1728000+$(date +%s --date=$(date +%Y-%m-15))))"
Here's a simpler solution using GNU date, with one fewer date call:
date +"%B %Y" --date="$(date +%Y-%m-15) 20 days"
(A bug in GNU date will give you the wrong month if you run date --date="next month" on the 31st.)
The below one works in Red Hat 4.4.7-23, Linux version 2.6.32-754.2.1.el6.x86_64.
Just use the "month" for future months and "month ago" for previous months.. Dont confuse with adding +/- signs to the number. Check out.
> date "+%B-%Y" #current month
November-2018
> date -d" 1 month" "+%B-%Y"
December-2018
> date -d" 1 month ago" "+%B-%Y"
October-2018
>
More..
> date -d" 7 month ago" "+%B-%Y"
April-2018
> date -d" 7 month " "+%B-%Y"
June-2019
>

Get yesterday's date in bash on Linux, DST-safe

I have a shell script that runs on Linux and uses this call to get yesterday's date in YYYY-MM-DD format:
date -d "1 day ago" '+%Y-%m-%d'
It works most of the time, but when the script ran yesterday morning at 2013-03-11 0:35 CDT it returned "2013-03-09" instead of "2013-03-10".
Presumably daylight saving time (which started yesterday) is to blame. I'm guessing the way "1 day ago" is implemented it subtracted 24 hours, and 24 hours before 2013-03-11 0:35 CDT was 2013-03-09 23:35 CST, which led to the result of "2013-03-09".
So what's a good DST-safe way to get yesterday's date in bash on Linux?
I think this should work, irrespective of how often and when you run it ...
date -d "yesterday 13:00" '+%Y-%m-%d'
Under Mac OSX date works slightly different:
For yesterday
date -v-1d +%F
For Last week
date -v-1w +%F
This should also work, but perhaps it is too much:
date -d #$(( $(date +"%s") - 86400)) +"%Y-%m-%d"
If you are certain that the script runs in the first hours of the day, you can simply do
date -d "12 hours ago" '+%Y-%m-%d'
BTW, if the script runs daily at 00:35 (via crontab?) you should ask yourself what will happen if a DST change falls in that hour; the script could not run, or run twice in some cases. Modern implementations of cron are quite clever in this regard, though.
Here a solution that will work with Solaris and AIX as well.
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
date -d "yesterday" '+%Y-%m-%d'
To use this later:
date=$(date -d "yesterday" '+%Y-%m-%d')
you can use
date -d "30 days ago" +"%d/%m/%Y"
to get the date from 30 days ago, similarly you can replace 30 with x amount of days
Just use date and trusty seconds:
As you rightly point out, a lot of the details about the underlying computation are hidden if you rely on English time arithmetic. E.g. -d yesterday, and -d 1 day ago will have different behaviour.
Instead, you can reliably depend on the (precisely documented) seconds since the unix epoch UTC, and bash arithmetic to obtain the moment you want:
date -d #$(( $(date +"%s") - 24*3600)) +"%Y-%m-%d"
This was pointed out in another answer. This form is more portable across platforms with different date command line flags, is language-independent (e.g. "yesterday" vs "hier" in French locale), and frankly (in the long-term) will be easier to remember, because well, you know it already. You might otherwise keep asking yourself: "Was it -d 2 hours ago or -d 2 hour ago again?" or "Is it -d yesterday or -d 1 day ago that I want?"). The only tricky bit here is the #.
Armed with bash and nothing else:
Bash solely on bash, you can also get yesterday's time, via the printf builtin:
%(datefmt)T
causes printf to output the date-time string resulting from using
datefmt as a format string for strftime(3). The corresponding argu‐
ment is an integer representing the number of seconds since the
epoch. Two special argument values may be used: -1 represents the
current time, and -2 represents the time the shell was invoked.
If no argument is specified, conversion behaves as if -1 had
been given.
This is an exception to the usual printf behavior.
So,
# inner printf gets you the current unix time in seconds
# outer printf spits it out according to the format
printf "%(%Y-%m-%d)T\n" $(( $(printf "%(%s)T" -1) - 24*3600 ))
or, equivalently with a temp variable (outer subshell optional, but keeps environment vars clean).
(
now=$(printf "%(%s)T" -1);
printf "%(%Y-%m-%d)T\n" $((now - 24*3600));
)
Note: despite the manpage stating that no argument to the %()T formatter will assume a default -1, i seem to get a 0 instead (thank you, bash manual version 4.3.48)
You can use:
date -d "yesterday 13:55" '+%Y-%m-%d'
Or whatever time you want to retrieve will retrieved by bash.
For month:
date -d "30 days ago" '+%Y-%m-%d'
As this question is tagged bash "DST safe":
And using fork to date command implie delay, there is a simple and more efficient way using pure bash built-in:
printf -v tznow '%(%z %s)T' -1
TZ=${tznow% *} printf -v yesterday '%(%Y-%m-%d)T' $(( ${tznow#* } - 86400 ))
echo $yesterday
This is a lot quicker on more system friendly than having to fork to date.
From bash version 5.0, there is a new variable $EPOCHSECONDS
printf -v tz '%(%z)T' -1
TZ=$tz printf -v yesterday '%(%Y-%m-%d)T' $(( EPOCHSECONDS - 86400 ))
echo $yesterday

bash - extract day of week of variable

What is the syntax to extract the day of the week from a stored date variable?
The dateinfile format is always [alphanum]_YYYYMMDD.
In this pseudocode example, trying to get dayofweek to store Saturday:
#! /bin/bash
dateinfile="P_20090530"
dayofweek="$dateinfile -u +%A"
[me#home]$ date --date=${dateinfile#?_} "+%A"
Saturday
Or, to put it as you've requested:
[me#home]$ dayofweek=$(date --date=${dateinfile#?_} "+%A")
[me#home]$ echo $dayofweek
Saturday
date -d $(echo $dateinfile | cut -f2 -d_) -u +%A
The inner expression separates the 20090530 from P_20090530, and the outer one extracts the day of week from that date
I needed the same output recently and googled upon this, but I had the same problem stating Bad Substition error.
I then read the date manual and made my version up as follows:
#! /bin/sh
dateinfile="P_20090530"
dayofweek=`date --reference $dateinfile +%A`
echo $dayofweek

Resources