1

I have a very simple batch file I am trying to write.

If today is 03/13, I would like my batch file to output:

"I will call you back on 03/15"

So it will take the date and ADD 2 business days. So if it were 03/15:

"I will call you back on 03/19"

J B
  • 11
  • 1
  • 2
  • 1
    Just a friendly piece of advice: Don't do this with a batch file. Date math and manipulation is nigh-impossible there and requires great care and horrible amounts of code. – Joey Mar 13 '13 at 14:55
  • Is there a way to do this in excel and then have the batch file call the output? – J B Mar 13 '13 at 14:56

3 Answers3

2

Eh, do not worry, it can be done in batch. :) Here is an implementation of mine (~150 lines of code).

Example

https://gist.github.com/DavidRuhmann/4666270

Usage

Do something like this to adjust for the weekends.

if "%Date:~0,3%"=="Thu" call :DaysAhead 4
if "%Date:~0,3%"=="Fri" call :DaysAhead 4
if "%Date:~0,3%"=="Sat" call :DaysAhead 3
if "%Date:~0,3%"=="Sun" call :DaysAhead 2
if "%Date:~0,3%"=="Mon" call :DaysAhead 2
if "%Date:~0,3%"=="Tue" call :DaysAhead 2
if "%Date:~0,3%"=="Wed" call :DaysAhead 2
Community
  • 1
  • 1
David Ruhmann
  • 11,064
  • 4
  • 37
  • 47
  • This fails for other regional settings. That's precisely what I meant with that date stuff is hard to get right in batch files. You should probably grab the date from WMI instead. Then there is the problem with `set /a` on 0-padded values which works fine for now but just wait until 2013-04-09 to see it break. – Joey Mar 13 '13 at 15:24
  • @Joey - That is exactly why I said it *can* be done and here is *an* implementation. I wrote my script so it can be easily adjusted. Requires that only 7 `%Date%` calls be changed to support a different format. Also, fixed the `set /a` issue. **`:)`** – David Ruhmann Mar 13 '13 at 16:01
  • **NOTE: I Recommend** using [rojo](http://stackoverflow.com/users/1683264/rojo)'s JScript batch hybrid answer, unless you need a pure batch solution. – David Ruhmann Mar 13 '13 at 17:31
2

Use JScript to calculate the date and you're golden.

@if (@X)==(@Y) @end /* (batch + jscript hybrid script init)

:: *** Batch script *****

@echo off
setlocal
for /f %%I in ('cscript /nologo /e:jscript "%~f0"') do (
    echo I will call you back on %%I
)

goto :EOF

:: *** JScript script *****/
var dow = new Date().getDay();
var days = (dow > 4) ? 9 - dow : (dow == 4 ? 4 : 2);
var d = new Date(new Date().getTime() + (1000 * 60 * 60 * 24) * days);
WScript.echo((d.getMonth() + 1) + '/' + d.getDate());

If today is Thursday, the script will return the following Monday. Friday through Sunday, the following Tuesday. Monday through Wednesday, two days ahead. And you don't have to worry about locale, leap year, leap frogs, lunar cycles, etc.

rojo
  • 24,000
  • 5
  • 55
  • 101
  • Ha! I love this very original way of mixing batch and jscript. I haven't seen that before. +1 :-) – Nate Hekman Mar 13 '13 at 17:03
  • @NateHekman - :) I can't take full credit for it. [dbenham](http://stackoverflow.com/users/1012053/dbenham) is a master at this sort of stuff. I first got the idea from him. Check out his [repl.bat](http://www.dostips.com/forum/viewtopic.php?p=20753) script. It's a hybrid batch + jscript script that works similar to `sed`. It's pretty impressive. – rojo Mar 13 '13 at 17:12
  • @rojo: May I suggest you a different format for your Batch-JScript hybrid sripts? http://stackoverflow.com/questions/15167742/execute-wshshell-command-from-a-batch-script/15176096#15176096 In my opinion, that format is clearer (your method may be confusing for people that don't know that `*/` ends the Batch section and start JScript code). – Aacini Mar 13 '13 at 18:10
2

The Batch file below do what you want:

@echo off
rem AddBusinessDays.bat date numOfDays
rem Antonio Perez Ayala

rem Convert the date to Julian Day Number + number of days
for /F "tokens=1-3 delims=/" %%a in ("%1") do (
   set /A mm=10%%a %% 100, dd=10%%b %% 100, yy=%%c
)
set /A a=mm-14, jd=(1461*(yy+4800+a/12))/4+(367*(mm-2-12*(a/12)))/12-(3*((yy+4900+a/12)/100))/4+dd-32075+2+%2, dow=jd%%7

rem Adjust Julian Day Number to avoid weekends
if %dow% lss 2 set /A jd+=2-dow

rem Convert Julian Day Number back to date
set /A l=jd+68569-2,n=(4*l)/146097,l=l-(146097*n+3)/4,i=(4000*(l+1))/1461001,l=l-(1461*i)/4+31,j=(80*l)/2447,dd=l-(2447*j)/80,l=j/11,mm=j+2-(12*l),yy=100*(n-49)+i+l

rem Assemble the result
if %dd% lss 10 set dd=0%dd%
if %mm% lss 10 set mm=0%mm%
set newDate=%mm%/%dd%/%yy%
echo %newDate%

Reference: http://www.hermetic.ch/cal_stud/jdn.htm#comp

For example:

>echo %date%
03/13/2013

>AddBusinessDays.bat %date% 2
03/15/2013

>AddBusinessDays.bat %date% 3
03/18/2013

>AddBusinessDays.bat %date% 4
03/18/2013

>AddBusinessDays.bat %date% 5
03/18/2013

>AddBusinessDays.bat %date% 6
03/19/2013

Antonio

PS - Yes, I know that this method will not work for everyone in the world. The good news are that I not wrote this solution for they all, but precisely for the OP although it is very easy to modify it for every computer. For example, previous program does NOT work in my computer because my locale is DD/MM/YYYY, but I can interchange dd and mm in two lines of previous program and I am pretty sure that most people in this world are also capable to do so! ;-)

Hi Antonio, Just today I found that the code you shared didn't work for more than 7 days ahead, I changed some thing and now it works ever.

@echo off
rem AddBusinessDays.bat date numOfDays
rem adapted by Leonardo Contreras based on Antonio Perez Ayala with handling for more than 7 days

rem to convert Dow mm/dd/yyyy to mm/dd/yy
set mydate=%date:~4,2%/%date:~7,2%/%date:~10,4%

rem Convert the date to Julian Day Number + number of days
for /F "tokens=1-3 delims=/" %%a in ("%mydate%") do (
   set /A mm=10%%a %% 100, dd=10%%b %% 100, yy=%%c
)
rem dow_orig is based on a 0-6 days statrting on Monday
set /A a=mm-14, jd_orig = (1461*(yy+4800+a/12))/4+(367*(mm-2-12*(a/12)))/12-(3*((yy+4900+a/12)/100))/4+dd-32075, dow_orig=jd_orig%%7

rem calculate new julian's day
set /A numw = (dow_orig+%3)/5, njd = jd_orig+%3+numw*2, dow=(njd)%%7 

rem Adjust Julian Day Number to avoid weekends
if %dow% gtr 5 (set /A jd+=2 )

rem Convert Julian Day Number back to date
set /A l=njd+68569,n=(4*l)/146097,l=l-(146097*n+3)/4,i=(4000*(l+1))/1461001,l=l-(1461*i)/4+31,j=(80*l)/2447,dd=l-(2447*j)/80,l=j/11,mm=j+2-(12*l),yy=100*(n-49)+i+l

rem Assemble the result
if %dd% lss 10 set dd=0%dd%
if %mm% lss 10 set mm=0%mm%
set newDate=%mm%/%dd%/%yy%
echo %newDate%
Community
  • 1
  • 1
Aacini
  • 65,180
  • 12
  • 72
  • 108
  • :O You can put multiple assignments in a single `set /a` call? I never noticed the expression separator in the help text. – Joey Mar 14 '13 at 06:40