45

I've got a shell script which does the following to store the current day's date in a variable 'dt':

date "+%a %d/%m/%Y" | read dt
echo ${dt}

How would i go about getting yesterdays date into a variable?

Basically what i'm trying to achieve is to use grep to pull all of yesterday's lines from a log file, since each line in the log contains the date in "Mon 01/02/2010" format.

Thanks a lot

Wolph
  • 78,177
  • 11
  • 137
  • 148
Chris
  • 39,719
  • 45
  • 189
  • 235

17 Answers17

77
dt=$(date --date yesterday "+%a %d/%m/%Y")
echo $dt
polemon
  • 4,722
  • 3
  • 37
  • 48
53

On Linux, you can use

date -d "-1 days" +"%a %d/%m/%Y"
z1x2
  • 793
  • 1
  • 5
  • 8
17

You can use GNU date command as shown below

Getting Date In the Past

To get yesterday and earlier day in the past use string day ago:

date --date='yesterday'

date --date='1 day ago'

date --date='10 day ago'

date --date='10 week ago'

date --date='10 month ago'

date --date='10 year ago'

Getting Date In the Future

To get tomorrow and day after tomorrow (tomorrow+N) use day word to get date in the future as follows:

date --date='tomorrow'

date --date='1 day'

date --date='10 day'

date --date='10 week'

date --date='10 month'

date --date='10 year'

ramit girdhar
  • 2,272
  • 1
  • 25
  • 26
14

If you have Perl available (and your date doesn't have nice features like yesterday), you can use:

pax> date
Thu Aug 18 19:29:49 XYZ 2010

pax> dt=$(perl -e 'use POSIX;print strftime "%d/%m/%Y%",localtime time-86400;')

pax> echo $dt
17/08/2010
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 1
    @Chris: note that this gives you the date 24 hours ago, which is subtly different from yesterday's date. If your locale has daylight savings time, this will give the wrong date after 23:00 on the first day of winter time. – Gilles 'SO- stop being evil' Aug 19 '10 at 12:17
  • @Gilles, that's not a bad point since I'm using locattime. If you're concerned about it, you can check if the hour is greater than 6pm, just subtract 6 hours. That should hopefully cover it. – paxdiablo Aug 19 '10 at 12:53
  • Good point gilles. I miss my C# : DateTime.Now.AddDays(-1) – Chris Aug 19 '10 at 23:43
  • `brew install coreutils` installs gnu date as gdate. Works on macOS and Linux. – HappyFace May 08 '20 at 04:08
10

If you are on a Mac or BSD or something else without the --date option, you can use:

date -r `expr \`date +%s\` - 86400` '+%a %d/%m/%Y'

Update: or perhaps...

date -r $((`date +%s` - 86400)) '+%a %d/%m/%Y'
DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • 2
    That would be less awkward using `$()` instead of `\``. ksh has `$()`? – bstpierre Aug 19 '10 at 01:16
  • 2
    +1 just for not assuming that every UNIX question is on Linux. Some of us have to work with other styles as well. – paxdiablo Aug 19 '10 at 01:22
  • @paxdiablo: agreed, but if no specific info is given than I personally assume that the GNU toolkit is an option ;) The differences between `HP-UX`, `AIX`, `Solaris` and `*BSD` are simply to great to guess the flavour. – Wolph Aug 19 '10 at 01:46
  • Could this fail in weird corner-cases? Like when there is a leap-second? – Alok Singhal Aug 19 '10 at 04:02
  • @Alok: POSIX/Unix doesn't track leap seconds (all days are 86400 seconds), but there is a corner case with DST (see my comment on [paxdiablo's answer](http://stackoverflow.com/questions/3517982/in-a-unix-shell-how-to-get-yesterdays-date-into-a-variable/3518086#3518086) – Gilles 'SO- stop being evil' Aug 19 '10 at 12:18
  • @DigitalRoss: Unfortunately `date +%s` is not POSIX either, though it's more widely available that `--date yesterday`. – Gilles 'SO- stop being evil' Aug 19 '10 at 12:19
  • `brew install coreutils ; gdate` – HappyFace May 08 '20 at 04:09
  • 1
    `$((` for arithmetic expansion is nice, but not what @bstpierre was talking about. Even inside there, you should really be using `$(`...`)` for the command expansion: `$(( $(date +%s) - 86400 ))`. – Mark Reed Sep 07 '21 at 12:35
7

I have shell script in Linux and following code worked for me:

#!/bin/bash
yesterday=`TZ=EST+24 date +%Y%m%d` # Yesterday is a variable
mkdir $yesterday # creates a directory with  YYYYMMDD format
jujuBee
  • 494
  • 5
  • 13
  • 1
    `TZ` is time zone, `EST+24` gives yesterday's date for Eastern Standard time (like wise you can use `EST-24` for tomorrow's date) `+%Y%m%d` is the format for YYYYMMDD. – jujuBee Jun 10 '15 at 13:16
  • 2
    This is by far the most succinct version that works on AIX for anyone who is searching for such an answer. AIX doesn't allow for the -r or -d flags but does in fact allow manipulating the time zone like this! You've made my day I've been trying to figure this out for like two hours, I'm making a date appear as half a year ago and the other ideas weren't working. – Davy M Jun 05 '17 at 23:36
5

Try the following method:

dt=`case "$OSTYPE" in darwin*) date -v-1d "+%s"; ;; *) date -d "1 days ago" "+%s"; esac`
echo $dt

It works on both Linux and OSX.

kenorb
  • 155,785
  • 88
  • 678
  • 743
4

You have atleast 2 options

  1. Use perl:

    perl -e '@T=localtime(time-86400);printf("%02d/%02d/%02d",$T[4]+1,$T[3],$T[5]+1900)'
    
  2. Install GNU date (it's in the sh_utils package if I remember correctly)

    date --date yesterday "+%a %d/%m/%Y" | read dt
    echo ${dt}
    
  3. Not sure if this works, but you might be able to use a negative timezone. If you use a timezone that's 24 hours before your current timezone than you can simply use date.

Wolph
  • 78,177
  • 11
  • 137
  • 148
  • @Chris: I assumed it wouldn't be a GNU compatible `date` but since you didn't specify the Unix variant I simply guessed ;) With `HP-UX` your options are a little more limited, `date` doesn't have these options so `Perl` might be the best option. – Wolph Aug 19 '10 at 01:34
  • Not that it matters but you don't need to add `1900` to the year if you're then going to `%100` the result :-) – paxdiablo Aug 19 '10 at 02:07
  • @paxdiablo: fair point, Perl is obviously not one of my strong points ;) I'll +1 your answer instead. – Wolph Aug 19 '10 at 02:10
3

Here is a ksh script to calculate the previous date of the first argument, tested on Solaris 10.

#!/bin/ksh
 sep=""
 today=$(date '+%Y%m%d')
 today=${1:-today}
 ty=`echo $today|cut -b1-4` # today year
 tm=`echo $today|cut -b5-6` # today month
 td=`echo $today|cut -b7-8` # today day
 yy=0 # yesterday year
 ym=0 # yesterday month
 yd=0 # yesterday day

 if [ td -gt 1 ];
 then
         # today is not first of month
         let yy=ty       # same year
         let ym=tm       # same month
         let yd=td-1     # previous day
 else
         # today is first of month
         if [ tm -gt 1 ];
         then
                 # today is not first of year
                 let yy=ty       # same year
                 let ym=tm-1     # previous month
                 if [ ym -eq 1 -o ym -eq 3 -o ym -eq 5 -o ym -eq 7 -o ym -eq 8 -o ym -     eq 10 -o ym -eq 12 ];
                 then
                         let yd=31
                 fi
                 if [ ym -eq 4 -o ym -eq 6 -o ym -eq 9 -o ym -eq 11 ];
                 then
                         let yd=30
                 fi
                 if [ ym -eq 2 ];
                 then
                         # shit... :)
                         if [ ty%4 -eq 0 ];
                         then
                                 if [ ty%100 -eq 0 ];
                                 then
                                         if [ ty%400 -eq 0 ];
                                         then
                                         #echo divisible by 4, by 100, by 400
                                                 leap=1 
                                         else
                                         #echo divisible by 4, by 100, not by 400
                                                 leap=0
                                         fi
                                 else
                                         #echo divisible by 4, not by 100
                                         leap=1 
                                 fi
                         else
                                 #echo not divisible by 4
                                 leap=0 # not divisible by four
                         fi
                         let yd=28+leap
                 fi
         else
                 # today is first of year
                 # yesterday was 31-12-yy
                 let yy=ty-1     # previous year
                 let ym=12
                 let yd=31
         fi
 fi
 printf "%4d${sep}%02d${sep}%02d\n" $yy $ym $yd

Tests

bin$ for date in 20110902 20110901 20110812 20110801 20110301 20100301 20080301 21000301 20000301 20000101 ; do yesterday $date; done
20110901
20110831
20110811
20110731
20110228
20100228
20080229
21000228
20000229
19991231
WrightsCS
  • 50,551
  • 22
  • 134
  • 186
2

ksh93:

dt=${ printf "%(%a %d/%m/%Y)T" yesterday; }

or:

dt=$(printf "%(%a %d/%m/%Y)T" yesterday)

The first one runs in the same process, the second one in a subshell.

danlei
  • 14,121
  • 5
  • 58
  • 82
2

For Hp-UX only below command worked for me:

TZ=aaa24 date +%Y%m%d

you can use it as :

ydate=`TZ=aaa24 date +%Y%m%d`

echo $ydate

Anvesh
  • 91
  • 10
2

If you have access to python, this is a helper that will get the yyyy-mm-dd date value for any arbitrary n days ago:

function get_n_days_ago {
  local days=$1
  python -c "import datetime; print (datetime.date.today() - datetime.timedelta(${days})).isoformat()"
}

# today is 2014-08-24

$ get_n_days_ago 1
2014-08-23

$ get_n_days_ago 2
2014-08-22
wuster
  • 41
  • 2
2
$var=$TZ;
TZ=$TZ+24;
date;
TZ=$var;

Will get you yesterday in AIX and set back the TZ variable back to original

santymano
  • 21
  • 3
2

Thanks for the help everyone, but since i'm on HP-UX (after all: the more you pay, the less features you get...) i've had to resort to perl:

perl -e '@T=localtime(time-86400);printf("%02d/%02d/%04d",$T[3],$T[4]+1,$T[5]+1900)' | read dt
Chris
  • 39,719
  • 45
  • 189
  • 235
2

If your HP-UX installation has Tcl installed, you might find it's date arithmetic very readable (unfortunately the Tcl shell does not have a nice "-e" option like perl):

dt=$(echo 'puts [clock format [clock scan yesterday] -format "%a %d/%m/%Y"]' | tclsh)
echo "yesterday was $dt"

This will handle all the daylight savings bother.

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
2

If you don't have a version of date that supports --yesterday and you don't want to use perl, you can use this handy ksh script of mine. By default, it returns yesterday's date, but you can feed it a number and it tells you the date that many days in the past. It starts to slow down a bit if you're looking far in the past. 100,000 days ago it was 1/30/1738, though my system took 28 seconds to figure that out.

    #! /bin/ksh -p

    t=`date +%j`
    ago=$1
    ago=${ago:=1} # in days
    y=`date +%Y`

    function build_year {
            set -A j X $( for m in 01 02 03 04 05 06 07 08 09 10 11 12
                    {
                            cal $m $y | sed -e '1,2d' -e 's/^/ /' -e "s/ \([0-9]\)/ $m\/\1/g"
                    } )
            yeardays=$(( ${#j[*]} - 1 ))
    }

    build_year

    until [ $ago -lt $t ]
    do
            (( y=y-1 ))
            build_year
            (( ago = ago - t ))
            t=$yeardays
    done

    print ${j[$(( t - ago ))]}/$y
Ken Beer
  • 21
  • 2
2

Though all good answers, unfortunately none of them worked for me. So I had to write something old school. ( I was on a bare minimal Linux OS )

$ date -d @$( echo $(( $(date +%s)-$((60*60*24)) )) )

You can combine this with date's usual formatting. Eg.

$ date -d @$( echo $(( $(date +%s)-$((60*60*24)) )) ) +%Y-%m-%d

Explanation : Take date input in terms of epoc seconds ( the -d option ), from which you would have subtracted one day equivalent seconds. This will give the date precisely one day back.

Gautam
  • 1,862
  • 9
  • 16