54

I have a Bash script that takes an argument of a date formatted as yyyy-mm-dd.

I convert it to seconds with

startdate="$(date -d"$1" +%s)";

What I need to do is iterate eight times, each time incrementing the epoch date by one day and then displaying it in the format mm-dd-yyyy.

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
JAyenGreen
  • 1,385
  • 2
  • 12
  • 23
  • 2
    Where did you get stuck? – lynxlynxlynx Sep 09 '13 at 20:53
  • On the Mac, you can convert the date into another format (like seconds) add the appropriate constant (like the number of seconds in a day) and then convert the data back all using the date command. I don't know if you can do that on Linux with the date command. You might be able to do this with gawk, and you can definitely do this in Perl or Python. Will those solutions work for you? – David W. Sep 09 '13 at 21:20
  • See also: [Unix & Linux: How do I add X days to date and get new date?](https://unix.stackexchange.com/q/49053/114401) – Gabriel Staples Mar 07 '22 at 15:21

7 Answers7

117

Use the date command's ability to add days to existing dates.

The following:

DATE=2013-05-25

for i in {0..8}
do
   NEXT_DATE=$(date +%m-%d-%Y -d "$DATE + $i day")
   echo "$NEXT_DATE"
done

produces:

05-25-2013
05-26-2013
05-27-2013
05-28-2013
05-29-2013
05-30-2013
05-31-2013
06-01-2013
06-02-2013

Note, this works well in your case but other date formats such as yyyymmdd may need to include "UTC" in the date string (e.g., date -ud "20130515 UTC + 1 day").

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
swdev
  • 2,941
  • 2
  • 25
  • 37
  • 2
    I was able to successfully increment the date in format "yyyymmdd" without using UTC, in Ubuntu machine, with `date +%Y%m%d -d "20130515 + 1 day"` – belindanju Mar 03 '17 at 20:45
  • 7
    Maybe point out that this is not portable across platforms. The `-d` option is correct for GNU `date` (i.e. Linux et al.) but not for *BSD `date` (MacOS etc). – tripleee Dec 17 '18 at 12:54
  • 6
    @tripleee: You're right! Here's how to add a day with macOS' [`date`](https://www.unix.com/man-page/FreeBSD/1/date/#neo-man-page-output): `date -v +1d -jf %F 1999-12-31 +%F` which produces `2000-01-01`. – Matthias Braun Apr 25 '20 at 14:41
  • to expand @MatthiasBraun, to make your full original answer work for macOS, the `NEXT_DATE` line should be `NEXT_DATE=$(date -v +$((i))d -jf %F $DATE +%F)` – pjdrew Dec 23 '21 at 17:06
  • 1
    Not portable across all Unix OSes – Gilles Quénot Apr 21 '23 at 12:43
7
startdate=$(date -d"$1" +%s)
next=86400 # 86400 is one day

for (( i=startdate; i < startdate + 8*next; i+=next )); do
     date -d"@$i" +%d-%m-%Y
done
Aleks-Daniel Jakimenko-A.
  • 10,335
  • 3
  • 41
  • 39
  • 1
    Are you sure adding 1 to each time is correct? It's an epoch date at that point and adding 1 would seem to be seconds and doesn't seem to affect the date at all...I get 8 of the same. – JAyenGreen Sep 09 '13 at 21:08
  • 1
    Whoops, didn't notice that OP wanted it to be incremented by one day. Fixed now. Also note that it will start from the input day. – Aleks-Daniel Jakimenko-A. Sep 09 '13 at 21:21
  • It is wrong to assume each day has 86400 seconds. You are totally missing any leap seconds. – ceving Sep 10 '13 at 09:06
  • @ceving are you sure? I thought that leap seconds exist only in UTC and ``date +%s`` wouldn't ever use leap seconds. Am I wrong? – Aleks-Daniel Jakimenko-A. Sep 10 '13 at 11:37
  • @Aleks-DanielJakimenko See here how long a day really is: http://en.wikipedia.org/wiki/Mean_solar_day – ceving Sep 10 '13 at 18:04
  • @ceving can you provide an example? Here is a leap second day: ``date -d '30 June 2012 23:59:59 next second'`` Does not return ``23:59:60``. I have tried playing with several other dates and I haven't found anything. – Aleks-Daniel Jakimenko-A. Sep 10 '13 at 18:15
  • @Aleks-DanielJakimenko The problem is that you add 86400 seconds even for days which are 86401 seconds long. This will not increment the day. – ceving Sep 10 '13 at 21:34
  • 1
    @Aleks-DanielJakimenko But it seems to me that your calculation works. But not because it is correct, but because GNU date does not handle leap seconds correctly. ;-) – ceving Sep 10 '13 at 21:54
2

Just another way to increment or decrement days from today that's a bit more compact:

$ date %y%m%d ## show the current date
$ 20150109
$ ## add a day:
$ echo $(date %y%m%d -d "$(date) + 1 day")
$ 20150110
$ ## Subtract a day:
$ echo $(date %y%m%d -d "$(date) - 1 day")
$ 20150108
$ 
Bill Matsoukas
  • 153
  • 1
  • 5
  • 1
    To be correct need to put plus sign before the format string. Also there are even more compact ways to do this. ex `echo $(date +%y%m%d -d "-1 day")` – swdev Jan 11 '18 at 18:44
  • The [`echo` is useless](http://www.iki.fi/era/unix/award.html#echo), too. – tripleee Apr 25 '20 at 15:26
  • triplee, the echo was simply for demonstration purposes. – Bill Matsoukas Aug 13 '20 at 14:58
  • 1
    date: the argument ‘%y%m%d’ lacks a leading '+'; when using an option to specify date(s), any non-option argument must be a format string beginning with '+' Try 'date --help' for more information. – DachuanZhao Feb 14 '22 at 02:48
2

Increment date in bash script and create folder structure based on Year, Month and Date to organize the large number of files from a command line output.

for m in {0..100}
do
    folderdt=$(date -d "Aug 1 2014 + $m days" +'%Y/%m/%d')
    procdate=$(date -d "Aug 1 2014 + $m days" +'%Y.%m.%d')
    echo $folderdt
    mkdir -p $folderdt
    #chown <user>:<group> $folderdt -R
    cd $folderdt
    #commandline --process-date $procdate
    cd -
done
Haroldo Gondim
  • 7,725
  • 9
  • 43
  • 62
Benoy G
  • 21
  • 4
2

There is another way similar to this, may not be as fast as adding 86400 seconds to the day, but worth try -

day="2018-07-01"
last_day="2019-09-18"
while [[ $(date +%s -d "$day") -le $(date +%s -d "${last_day}") ]];do 
    echo $i;    
    # here you can use the section you want to use
    day=$(date -d "$day next day" +%Y-%m-%d); 
done
v_sukt
  • 1,384
  • 1
  • 10
  • 21
1

date -d is not portable across OSes, and sometimes not reliable at all.

With Perl with core modules (installed by default), this is a robust, portable and reliable way in a shell:

perl -MTime::Piece -MTime::Seconds -sE '
    my $d = Time::Piece->strptime($mydate, "%Y-%m-%d %H:%M:%S");
    ($dow, $month, $dom, $hour, $year) = split / +/, $d +ONE_DAY;
    my $dateold = Time::Piece->strptime(
        "$dow $month $dom $year $hour",
        "%a %b %d %Y %H:%M:%S");
    say $dateold->strftime("%Y-%d-%m %H:%M:%S");
' -- -mydate='2023-06-03 06:21:33'
2023-07-03 06:21:33   
Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
0

It is not that easy to increment days. Normally it is done by converting the Gregorian date into a Julian day number. Then you can increment the day. And after that you calculate the Gregorian date. Here is example code:

http://it.toolbox.com/wiki/index.php/Convert_a_date_to_a_Julian_day

http://it.toolbox.com/wiki/index.php/Convert_a_Julian_day_to_a_date

ceving
  • 21,900
  • 13
  • 104
  • 178