For example, given date is '2016-12-31', n is 2, expected output is '2016-12-29'.
I survey date
command and get n days ago from current date is easy: date -d "2 days ago" +%Y-%m-%d
Just mention the date you want to extract two days from:
$ date -d "2016-12-31 2 days ago" +%Y-%m-%d
2016-12-29
Or a bit better grammatically-wise:
$ date -d "2016-12-31 -2 days" +%Y-%m-%d
2016-12-29
If you do not have GNU date, perhaps you have BSD date instead. In that case, you can do this:
date -jf %s $(( $(date +%s) - 86400 * 2 ))
Note that this is not POSIX, nor is it GNU.
This tells BSD date not to change the clock (-j
) and to take the input as UNIX time (seconds after 1970/01/01 00:00:00 UTC, -f %s
). The time supplied is a mathematical substitution of the current time ($(date +%s)
, using the same format but as output) minus the number of seconds in a day (86400) times two.
I have, in the past, written code that looks for GNU and then fails over to BSD:
# Usage: _epoch2datefmt UNIX_TIME [+FORMAT]
if date -d @1484850180 +%s >/dev/null 2>&1
then _epoch2datefmt() { date -d @"$@"; } # GNU
else _epoch2datefmt() { date -jf %s "$@"; } # BSD
fi
For this question, we also need to go the other direction. BSD date needs the format too:
# Usage: _date2epoch YYYY-MM-DD [INPUT_FORMAT]
if date -d 2017-01-19 +%s >/dev/null 2>&1
then _yyyymmdd2epoch() { date -d "$1" +%s; } # GNU
else _yyyymmdd2epoch() { date -jf "$2" "$1" +%s; } # BSD
fi
Here's how to put those together to get two days before a given date with either GNU or BSD:
_epoch2datefmt $(( $(_date2epoch 2016-12-31 %Y-%m-%d) - 2 * 86400 )) +%Y-%m-%d
From the inside out, this converts 2016-12-31 to UNIX time, subtracts two days (there are 86400 seconds in a day), then passes the resulting UNIX time (the answer) to be converted back into YYYY-MM-DD format.
If you wanted this all in one function, it could be:
# Usage: _date_helper INPUT_FORMAT DATE [+OUTPUT_FORMAT]
if date -d@1484850180 +%s >/dev/null 2>&1
then _date_helper() { local A=; [ "$1" = %s ] && A=@; shift; date -d "$A$@"; }
else _date_helper() { date -jf "$@"; }
fi
(I had to be a little tricky to handle inputting the UNIX time (as indicated by the first argument being %s
) since GNU's date -d
requires a leading @
. This saves that prefix in $A
if necessary, purges the format (GNU is smart and doesn't otherwise need it), then passes the rest off to the GNU date
command. The BSD version should be self-explanatory.)
Here's how to run it to get "two days before 2016-12-31" using this function:
_date_helper %s $(( $(_date_helper %Y-%m-%d 2016-12-31 +%s) - 86400 * 2)) +%Y-%m-%d
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With