I strongly agree with @JosefZ, date math is a complex matter. Vbscript and PowerShell have it incorporated and it is used and depended on like a black box.
Even if batch only has 32bit signed integer math this is sufficient to solve this. When packaged into callable sub routines stored at the end of batches it shouldn't irritate to much.
There is even a method to put them into a batchlibrary somewhere in the path and just a small stub is needed to invoke them.
So here is the variant with only batch code (with massive overhead compared to the powershell one liner) No restrictions to date format and language.
Output:
Today Year: 2016 Month: 12 Day: 08
-38 Year: 2016 Month: 10 Day: 31
Batch
@Echo off
Call :GetDate yy mm dd
Echo Today Year: %yy% Month: %mm% Day: %dd%
Set /A n=-38
Call :DateAdd yy mm dd %n%
Echo %n% Year: %yy% Month: %mm% Day: %dd%
Pause
Goto :Eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:GetDate yy mm dd
::
:: Func: Loads local system date components into args 1 to 3.
::
:: Args: %1 var to receive year, 4 digits (by ref)
:: %2 var to receive month, 2 digits, 01 to 12 (by ref)
:: %3 Var to receive day of month, 2 digits, 01 to 31 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
SetLocal EnableExtensions
for /f "tokens=1-3 delims=.+-" %%A in (
'wmic os get LocalDateTime^|findstr ^^[0-9]'
) do Set _DT=%%A
Set "yy=%_DT:~0,4%"&Set "MM=%_DT:~4,2%"&Set "dd=%_DT:~6,2%"
endlocal&set %1=%yy%&set %2=%MM%&set %3=%dd%&goto :EOF
:: GetDate.cmd :::::::::::::::::::::::::::::::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:DateAdd yy mm dd #days
::
:: Func: Adds/subs Days from/to a given date by converting to a
:: Julian Day adding the offset and converting back.
:: Args:
:: %1 year component used to create JD, 4 digits (by ref)
:: %2 month component used to create JD, leading zero ret (by ref)
:: %3 day of month used to create MJD, leading zero ret (by ref)
:: %4 days offset may be positive or negative (by val)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
SetLocal
Call set /A "yy=%%%1%%,mm=100%%%2%% %%%%100,dd=100%%%3%% %%%%100"
Set /A jd=(1461*(yy+4800+(mm-14)/12))/4
Set /A jd=jd+(367*(mm-2-12*((mm-14)/12)))/12
Set /A jd=jd-(3*((yy+4900+(mm-14)/12)/100))/4,jd=jd+dd-32075
Set /A jd=jd+%4
set /A l=jd+68569,n=(4*l)/146097,l=l-(146097*n+3)/4
Set /A i=(4000*(l+1))/1461001,l=l-(1461*i)/4+31,j=(80*l)/2447
Set /A dd=l-(2447*j)/80,l=j/11,mm=j+2-(12*l),yy=100*(n-49)+i+l
(if %mm% LSS 10 set mm=0%mm%)&(if %dd% LSS 10 set dd=0%dd%)
Endlocal&set %1=%yy%&set %2=%mm%&set %3=%dd%&Goto :Eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::