In a unix shell, how to get yesterday's date into a variable?
Asked Answered
S

17

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

Sanction answered 19/8, 2010 at 1:5 Comment(1)
Perl is an option if necessary...Sanction
W
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
Wolfgram answered 19/8, 2010 at 1:34 Comment(4)
@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.Borrego
@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.Wolfgram
Good point gilles. I miss my C# <sob>: DateTime.Now.AddDays(-1)Sanction
brew install coreutils installs gnu date as gdate. Works on macOS and Linux.Round
W
77
dt=$(date --date yesterday "+%a %d/%m/%Y")
echo $dt
Windham answered 19/8, 2010 at 1:12 Comment(2)
+1 for answering the question precisely. Caveat is that the -yesterday flag may not be supported on posters version of unixWarsle
"-d yesterday" for short syntax.Orin
S
53

On Linux, you can use

date -d "-1 days" +"%a %d/%m/%Y"
Sideward answered 19/8, 2010 at 3:52 Comment(3)
This is the best answer among all the others, short, sweet, easy, handy, cool and it proves the story 'Give a man a fish he is fed for a day, but teach him to fish, he is fed for life'Finegrain
Note for AIX users, the -d flag is not supported for date sadly.Jost
Thanks. It helped.Stralsund
E
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'

Excommunicate answered 8/9, 2015 at 5:10 Comment(0)
W
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
Wolfgram answered 19/8, 2010 at 1:34 Comment(4)
@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.Borrego
@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.Wolfgram
Good point gilles. I miss my C# <sob>: DateTime.Now.AddDays(-1)Sanction
brew install coreutils installs gnu date as gdate. Works on macOS and Linux.Round
L
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'
Lamoree answered 19/8, 2010 at 1:11 Comment(8)
That would be less awkward using $() instead of `. ksh has $()?Dirt
+1 just for not assuming that every UNIX question is on Linux. Some of us have to work with other styles as well.Wolfgram
@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.Properly
Could this fail in weird corner-cases? Like when there is a leap-second?Parachronism
@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 answerBorrego
@DigitalRoss: Unfortunately date +%s is not POSIX either, though it's more widely available that --date yesterday.Borrego
brew install coreutils ; gdateRound
$(( for arithmetic expansion is nice, but not what @Dirt was talking about. Even inside there, you should really be using $(...) for the command expansion: $(( $(date +%s) - 86400 )).Photometer
B
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
Bogusz answered 11/6, 2014 at 20:41 Comment(2)
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.Bogusz
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.Jost
J
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.

Jaehne answered 15/5, 2014 at 15:41 Comment(0)
P
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.

Properly answered 19/8, 2010 at 1:8 Comment(3)
@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.Properly
Not that it matters but you don't need to add 1900 to the year if you're then going to %100 the result :-)Wolfgram
@paxdiablo: fair point, Perl is obviously not one of my strong points ;) I'll +1 your answer instead.Properly
S
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
Selenodont answered 2/9, 2011 at 10:3 Comment(0)
S
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
Sanction answered 19/8, 2010 at 3:18 Comment(0)
M
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.

Messieurs answered 19/8, 2010 at 12:40 Comment(0)
R
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
Raymonderaymonds answered 26/11, 2010 at 19:39 Comment(0)
R
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.

Rawden answered 31/1, 2013 at 1:54 Comment(1)
@clarkw: Good suggestion, I'll add it to the answer.Rawden
K
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

Karate answered 7/8, 2013 at 13:53 Comment(0)
R
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
Rianna answered 25/8, 2014 at 3:48 Comment(0)
V
2
$var=$TZ;
TZ=$TZ+24;
date;
TZ=$var;

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

Vickyvico answered 18/5, 2015 at 18:32 Comment(0)
A
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.

Advisement answered 7/4, 2018 at 17:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.