Date Command ‘1 Month Ago’ Option – How It Works

coreutilsdate

I'm not sure if this gets the past date within the current day or if it only takes 30 or 31 days to it.

e.g.

If the current date is March 28th, 1 month ago must be February 28th, but what happen when it's March 30th?

Scenario

I want to backup some files each day, the script will save this files within the current date with $(date +%Y%m%d) format, like 20150603_bckp.tar.gz, then when the next month arrives, remove all those files within 1 month ago except the 1st's and the 15th's files, so this is my condition:

past_month = $(date -d "-1 month" +%Y%m%d)
day = $(date +%d)
if [ "$day" != 01 ] && [ "$day" != 15 ]
then
    rm /path/of/files/${past_month}_bckp.tar.gz
    echo "Depuration done"
else
    echo "Keep file"
fi

But I want to know, what will happen when the date is 30th, 31th or even the past February example? It will keep those files? or remove day 1st files?

When it's 31th the depuration will execute, so if the past month only had 30 days, this will remove the day 1st file?

I hope I hinted.

Best Answer

- 1 month will subtract one from the month number, and then if the resulting date is not valid (February 30, for example), adjust it so that it is valid. So December 31 - 1 month is December 1, not a day in November, and March 31 - 1 month is March 3 (unless executed in a leap year).

Here's quote from the info page for Gnu date (which is the date version which implements this syntax), which includes a good suggestion to make the arithmetic more robust:

The fuzz in units can cause problems with relative items. For example, 2003-07-31 -1 month might evaluate to 2003-07-01, because 2003-06-31 is an invalid date. To determine the previous month more reliably, you can ask for the month before the 15th of the current month. For example:

    $ date -R
    Thu, 31 Jul 2003 13:02:39 -0700
    $ date --date='-1 month' +'Last month was %B?'
    Last month was July?
    $ date --date="$(date +%Y-%m-15) -1 month" +'Last month was %B!'
    Last month was June!

Another warning, also quoted from the info page:

Also, take care when manipulating dates around clock changes such as daylight saving leaps. In a few cases these have added or subtracted as much as 24 hours from the clock, so it is often wise to adopt universal time by setting the TZ environment variable to UTC0 before embarking on calendrical calculations.

Related Question