To simplify the problem, lets say I have variable: dat="10152015" (representing 15th October 2015) the result for dat should be 10142015

Note that I am not using today's date.

What I have problem with is thinking of a way to decrement the date by 1 day. I could just decrement the 4th digit, but this is a calendar.

My current thinking is to convert this into a format that unix understands (whatever that is), then try working from there, and then convert the answer back


requires GNU date:

date -d "${dat:4}${dat:0:4} yesterday" +%m%d%Y 

YYYYMMDD is an ISO 9601 date format and the packed amercan format MMDDYYYY can be translated to that by simply swapping the two halves using ordinary substring expansion.

this requires gnu date, I don't think other versions of date support displaying non-current time.

| improve this answer | |
  • It is indeed GNU specific, but note that FreeBSD date also supports displaying non-current time, but using a completely different syntax. – Stéphane Chazelas Nov 22 '15 at 21:13

This first uses sed to convert the format you gave, 10152015, to the format mm/dd/yyyy, which the GNU implementation of the date command, with its -d options understands. This is accomplished by echoing the original date into sed which inserts the slashes /. This re-formatted date value is stored in D. Next we call date with instructions to print the output format "mmddyyyy", and tell it to print the date of yesterday using $D as the current date.

D=$(echo "${1-10152015}" | sed 's,^\(..\)\(..\)\(....\)$,\1/\2/\3,')
date +%m%d%Y -d"$D yesterday"
| improve this answer | |

bash is not the best shell for date calculation as its date-manipulation capabilities are very limited.

With zsh:

zmodload zsh/datetime
strftime -rs d %m%d%Y%H ${d}12
strftime %m%d%Y $((d-86400))

With ksh93:

printf "%(%m%d%Y)T\n" "${d:4}${d:0:4} yesterday"

With bash, you'd either have to do the calculation by hand or rely on perl or some GNU or FreeBSD extensions of the date utility.

| improve this answer | |

@Jasen's elegant answer inspired me to think of this variation, also requiring GNU date:




date -d"$YYYY$MMDD yesterday" +%m%d%Y

This uses the POSIX compliant Parameter Expansion substring processing with pattern matching notation, thus also runs under any POSIX /bin/sh as well as bash.

This could also be accomplished without the intermediate variables YYYY and MMDD, but I think they help to clearly document the input and output formats. They give the observer an extra symbolic clue about what's being done, without the addition of extra logic. Especially helpful because I think this notation is slightly more cryptic than the bash version.

| improve this answer | |

Note: the following assumes GNU date from GNU coreutils. Adapt to your system's date if you have a different date utility.

Your thinking is correct, you need to convert to seconds since the epoch (Jan 1 1970 00:00:00).

GNU date is reasonably flexible in the date formats it will interpret, but MMDDYYYY is not one of them. Fortunately, you can use sed to reformat the date (into YYYY-MM-DD format) before giving it to date -d

secs=$(date +%s -d $(echo "$dat" | sed -e 's/\(..\)\(..\)\(....\)/\3-\1-\2/'))
newsecs=$((secs - 86400))
date -d "@$newsecs"
| improve this answer | |
  • 2
    Actually, if you're going to use GNU date, you might as well get it do the calculation: date -d "10/15/2015 - 1 day", for example, or date -d "2015-10-15 - 1 day". – muru Nov 22 '15 at 2:53
  • OTOH, converting to seconds-since-the-epoch and performing additions and subtractions on that is a tried-and-tested generic technique that works in every language that has even minimal date functions. – cas Nov 22 '15 at 3:09
  • OTFH, it does rely on assumptions about time. – muru Nov 22 '15 at 3:11
  • yes. time is arbitary and everyone makes assumptions about it. e.g. adding or subtracting 86400 won't work properly on a day with a leap-second, or on transition days to/from Daylight Savings – cas Nov 22 '15 at 3:23
  • subtracting 24 hours is not reliable. some days are 23 hours long, some 25. – Jasen Nov 22 '15 at 7:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.