There are times when you will need to calculate yesterday’s date in a UNIX shell script to run some date sensitive cron jobs. There are currently no standard command line tools in UNIX to perform such date arithmetic.

Writing a program in C or Java to perform such date arithmetic is actually an overkill. If you have the GNU date command installed, you can get the date quite easily by running date as follows:

[ibrahim@anfield ~]#  date -d "-1 day"
Sat Jul  4 16:30:08 MPST 2009

GNU date is available in Linux distributions. It’s not available by default in commercial UNIX distributions such as AIX or Solaris. To calculate yesterday’s date for such platforms, you can use the following script instead. Save the following script to a file called yesterday, chmod to 755 and copy it to a directory in your PATH.

#!/bin/sh

#
# Script to calculate yesterday's date with custom output date format
#
# Author: ibrahim - www.digitalinternals.com
#

  # default output format
  defaultof="%Y%m%d"

  # check for input format, else use default format,
  # refer to 'man date' for help on format
  # script only supports %Y %m %d at the moment
  of=$defaultof
  [ $# -eq 1 ] && of="$1"

  # get today's date
  eval "`date +'y=%Y m=%m d=%d'`"

  # subtract 1 day
  d=`expr $d - 1`
  if [ $d -eq 0 ];  then
    # if day is 0, subtract month by 1
    m=`expr $m - 1`
    if [ $m -eq 0 ]; then
      # if month is 0, subtract year and set month to 12
      m=12
      y=`expr $y - 1`
    fi

    # set day depending on value of month
    d=31
    if [ $m -eq 4 ] || [ $m -eq 6 ] || [ $m -eq 9 ] || [ $m -eq 11 ] ; then
      d=30
    fi

    # check for leap year
    if [ $m -eq 2 ]; then
      d=28
      leap1=`expr $y % 4`
      leap2=`expr $y % 100`
      leap3=`expr $y % 400`
      if [ $leap1 -eq 0 ] ; then
        if [ $leap2 -gt 0 ] || [ $leap3 -eq 0 ] ; then
          d=29
        fi
      fi
    fi
  fi

  #Solaris date does not accept -d
  #date -d "$y-$m-$d" +"$of"

  eval "y=`expr $y + 0` m=`expr $m + 0` d=`expr $d + 0`"
  eval "y=`printf "%04d" $y` m=`printf "%02d" $m` d=`printf "%02d" $d`"
  echo "$of" | sed -e "s/%Y/$y/" -e s/%m"/$m/" -e "s/%d/$d/"

Below are some examples on how the script can be called:

[ibrahim@anfield ~]# date
Sun Jul  5 17:13:12 MPST 2009

[ibrahim@anfield ~]# yesterday
20090704

[ibrahim@anfield ~]# yesterday "prefix %Y-%m-%d postfix"
prefix 2009-07-04 postfix

[ibrahim@anfield ~]# yesterday "%Y-%m-%d"
2009-07-04

Update (9-Nov-2010): Script updated to run on Solaris platforms

Update (7-Aug-2011): Script updated to prevent printf function from interpreting certain numbers as octal

The following two tabs change content below.

Mohamed Ibrahim

Ibrahim is a Telecom Engineer by profession. A technology enthusiast with great interest in open source projects.