Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for dateadd.bat

(view source code of dateadd.bat as plain text)

  1. @ECHO OFF
  2. ECHO.
  3.  
  4. :: Reset variables
  5. SET "cDate="
  6. SET "iDate="
  7. SET "sDate="
  8.  
  9. :: Check the Windows version
  10. IF NOT "%OS%"=="Windows_NT" GOTO Syntax
  11.  
  12. SETLOCAL ENABLEDELAYEDEXPANSION
  13.  
  14. :: Initialize variable
  15. SET "Error=0"
  16.  
  17. :: Check the command line arguments
  18. IF     "%~1"=="" GOTO Syntax
  19. IF NOT "%~3"=="" GOTO Syntax
  20. ECHO.%* | FINDSTR.EXE /R /I /C:"[^-\""adnotwy/0-9 ]" >NUL && GOTO Syntax
  21.  
  22. :: Get today's date in local date format
  23. SET ArgsCount=0
  24. FOR %%A IN (%Date%) DO (
  25. 	SET /A ArgsCount += 1
  26. 	SET "Today=%%~A"
  27. )
  28. IF %ArgsCount% GTR 2 (
  29. 	REM Use WMIC to get today's date in ISO 8601 format
  30. 	FOR /F "skip=1 tokens=1-3" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Month^,Year /Format:table') DO (
  31. 		IF NOT "%%~F"=="" (
  32. 			SET Today=%%C-%%B-%%A
  33. 		)
  34. 	)
  35. )
  36.  
  37. IF "%~2"=="" (
  38. 	SET "cDate=%Today%"
  39. 	SET /A "cDays=%~1" >NUL 2>&1
  40. ) ELSE (
  41. 	SET "cDate=%~1"
  42. 	IF /I "%~1"=="Now"   (SET "cDate=%Today%")
  43. 	IF /I "%~1"=="Today" (SET "cDate=%Today%")
  44. 	SET /A "cDays=%~2" >NUL 2>&1
  45. )
  46. IF "%cDays%"=="0" (
  47. 	ECHO.
  48. 	ECHO Error: %cDays% is not a valid integer
  49. 	GOTO Syntax
  50. )
  51.  
  52. :: Read the Date format from the registry; if this fails, we're probably dealing with an older Windows version
  53. FOR /F "tokens=3" %%A IN ('REG.EXE Query "HKEY_CURRENT_USER\Control Panel\International" /v iDate 2^>NUL') DO SET "iDate=%%~A"
  54. FOR /F "tokens=3" %%A IN ('REG.EXE Query "HKEY_CURRENT_USER\Control Panel\International" /v sDate 2^>NUL') DO SET "sDate=%%~A"
  55. IF "%iDate%"=="" GOTO Syntax
  56.  
  57. :: Check if a valid date in local format was specified
  58. ECHO.%cDate% | FINDSTR.EXE /R /B /C:"[0-9][0-9]*%sDate%[0-9][0-9]*%sDate%[0-9][0-9][0-9][0-9]" >NUL
  59. IF ERRORLEVEL 1 (
  60. 	REM Try testing for ISO 8601 format
  61. 	ECHO.%cDate% | FINDSTR.EXE /R /B /C:"[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" >NUL
  62. 	IF ERRORLEVEL 1 (
  63. 		ECHO.
  64. 		ECHO Error: %cDate% is not a valid date
  65. 		GOTO Syntax
  66. 	) ELSE (
  67. 		SET "iDate=2"
  68. 		SET "sDate=-"
  69. 	)
  70. )
  71.  
  72. :: Parse the date specified, abort on failure
  73. CALL :ParseDate %cDate%
  74. IF "%Error%"=="1" GOTO Syntax
  75.  
  76. :: Convert the parsed Gregorian date to Julian
  77. CALL :JDate %GYear% %GMonth% %GDay%
  78.  
  79. :: Display original input
  80. ECHO Starting date   : %cDate%
  81.  
  82. :: Add or subtract the specified number of days
  83. IF "%cDays:~0,1%"=="-" (
  84. 	SET /A "NewJDate = %JDate% - %cDays:~1%"
  85. 	ECHO Days subtracted : %cDays:~1%
  86. ) ELSE (
  87. 	SET /A "NewJDate = %JDate% + %cDays%"
  88. 	ECHO Days added      : %cDays%
  89. )
  90.  
  91. :: Convert the new Julian date back to Gregorian again
  92. CALL :GDate %NewJDate%
  93.  
  94. :: Reformat the date to local format
  95. CALL :ReformatDate %GDate%
  96.  
  97. :: Display the result
  98. ECHO Resulting date  : %LDate%
  99.  
  100. :: Return the result in a variable named after this batch file
  101. ENDLOCAL & SET "%~n0=%LDate%"
  102. GOTO:EOF
  103.  
  104.  
  105. ::===================================::
  106. ::                                   ::
  107. ::   -   S u b r o u t i n e s   -   ::
  108. ::                                   ::
  109. ::===================================::
  110.  
  111.  
  112. :GDate
  113. :: Convert Julian date back to "normal" Gregorian date
  114. :: Argument : Julian date
  115. :: Returns  : YYYY MM DD
  116. ::
  117. :: Algorithm based on Fliegel-Van Flandern
  118. :: algorithm from the Astronomical Almanac,
  119. :: provided by Doctor Fenton on the Math Forum
  120. :: (http://mathforum.org/library/drmath/view/51907.html),
  121. :: and converted to batch code by Ron Bakowski.
  122. ::
  123. SET /A "P      = %~1 + 68569"
  124. SET /A "Q      = 4 * %P% / 146097"
  125. SET /A "R      = %P% - ( 146097 * %Q% + 3 ) / 4"
  126. SET /A "S      = 4000 * ( %R% + 1 ) / 1461001"
  127. SET /A "T      = %R% - 1461 * %S% / 4 + 31"
  128. SET /A "U      = 80 * %T% / 2447"
  129. SET /A "V      = %U% / 11"
  130. SET /A "GYear  = 100 * ( %Q% - 49 ) + %S% + %V%"
  131. SET /A "GMonth = %U% + 2 - 12 * %V%"
  132. SET /A "GDay   = %T% - 2447 * %U% / 80"
  133. :: Clean up the mess
  134. FOR %%A IN (P Q R S T U V) DO SET "%%~A="
  135. :: Add leading zeroes
  136. IF 1%GMonth% LSS 20 SET "GMonth=0%GMonth%"
  137. IF 1%GDay%   LSS 20 SET "GDay=0%GDay%"
  138. :: Return value
  139. SET "GDate=%GYear% %GMonth% %GDay%"
  140. GOTO:EOF
  141.  
  142.  
  143. :JDate
  144. :: Convert date to Julian
  145. :: Arguments : YYYY MM DD
  146. :: Returns   : Julian date
  147. ::
  148. :: First strip leading zeroes
  149. SET "MM=%2"
  150. SET "DD=%3"
  151. IF "%MM:~0,1%"=="0" SET "MM=%MM:~1%"
  152. IF "%DD:~0,1%"=="0" SET "DD=%DD:~1%"
  153. ::
  154. :: Algorithm based on Fliegel-Van Flandern
  155. :: algorithm from the Astronomical Almanac,
  156. :: provided by Doctor Fenton on the Math Forum
  157. :: (http://mathforum.org/library/drmath/view/51907.html),
  158. :: and converted to batch code by Ron Bakowski.
  159. SET /A "Month1 = ( %MM% - 14 ) / 12"
  160. SET /A "Year1  = %~1 + 4800"
  161. SET /A "JDate  = 1461 * ( %Year1% + %Month1% ) / 4 + 367 * ( %MM% - 2 -12 * %Month1% ) / 12 - ( 3 * ( ( %Year1% + %Month1% + 100 ) / 100 ) ) / 4 + %DD% - 32075"
  162. FOR %%A IN (Month1 Year1) DO SET "%%~A="
  163. GOTO:EOF 
  164.  
  165.  
  166. :ParseDate
  167. :: Parse (Gregorian) date depending on registry's date format settings
  168. :: Argument : Gregorian date in local date format, or in ISO 8601 format
  169. :: Requires : sDate (local date separator), iDate (local date format number)
  170. :: Returns  : GYear (4-digit year), GMonth (2-digit month), GDay (2-digit day)
  171. ::
  172. IF "%iDate%"=="0" FOR /F "tokens=1-3 delims=%sDate%" %%A IN ('ECHO.%1') DO (
  173. 	SET "GYear=%%~C"
  174. 	SET "GMonth=%%~A"
  175. 	SET "GDay=%%~B"
  176. )
  177. IF "%iDate%"=="1" FOR /F "tokens=1-3 delims=%sDate%" %%A IN ('ECHO.%1') DO (
  178. 	SET "GYear=%%~C"
  179. 	SET "GMonth=%%~B"
  180. 	SET "GDay=%%~A"
  181. )
  182. IF "%iDate%"=="2" FOR /F "TOKENS=1-3 DELIMS=%sDate%" %%A IN ('ECHO.%1') DO (
  183. 	SET "GYear=%%~A"
  184. 	SET "GMonth=%%~B"
  185. 	SET "GDay=%%~C"
  186. )
  187. IF %GDay%   GTR 31 SET "Error=1"
  188. IF %GMonth% GTR 12 SET "Error=1"
  189. GOTO:EOF
  190.  
  191.  
  192. :ReformatDate
  193. :: Reformat the date back to the local format
  194. :: Arguments : YYYY MM DD
  195. :: Returns   : LDate (Gregorian date in local format)
  196. ::
  197. IF "%iDate%"=="0" SET "LDate=%~2%sDate%%~3%sDate%%~1"
  198. IF "%iDate%"=="1" SET "LDate=%~3%sDate%%~2%sDate%%~1"
  199. IF "%iDate%"=="2" SET "LDate=%~1%sDate%%~2%sDate%%~3"
  200. GOTO:EOF
  201.  
  202.  
  203. :Syntax
  204. ECHO.
  205. ECHO DateAdd.bat,  Version 2.02 for Windows XP Professional and later
  206. ECHO Add the specified number of days to the specified date
  207. ECHO.
  208. ECHO Usage:   DATEADD  [ date ]  days
  209. ECHO.
  210. ECHO Where:   date     is a "normal" Gregorian date, either in the local date
  211. ECHO                   format, or in ISO 8601 yyyy-MM-dd format, or "Today"
  212. ECHO                   or "Now" (default if not specified: today's date)
  213. ECHO          days     is the number of days to add (negative to subtract)
  214. ECHO.
  215. ECHO E.g.     DATEADD  2017-01-01   1        will return 2017-01-02
  216. ECHO          DATEADD  2017-01-01  -1        will return 2016-12-31
  217. :: To show the following "advanced" examples, Windows XP or later is required
  218. IF NOT "%OS%"=="Windows_NT" GOTO Skipped2
  219. FOR /F "tokens=3" %%A IN ('REG.EXE Query "HKEY_CURRENT_USER\Control Panel\International" /v iDate 2^>NUL') DO SET "iDate=%%~A"
  220. FOR /F "tokens=3" %%A IN ('REG.EXE Query "HKEY_CURRENT_USER\Control Panel\International" /v sDate 2^>NUL') DO SET "sDate=%%~A"
  221. :: Windows XP or later is required to read iDate, so if iDate isn't set, skip the "advanced" examples
  222. IF "%iDate%"=="" GOTO Skipped2
  223. FOR %%A IN (%Date%) DO SET "Today=%%~A"
  224. CALL :ParseDate %Today%
  225. IF NOT "%Error%"=="0" GOTO Skipped1
  226. CALL :JDate %GYear% %GMonth% %GDay%
  227. SET /A "NewJDate = %JDate% + 1"
  228. CALL :GDate %NewJDate%
  229. CALL :ReformatDate %GDate%
  230. SET "Tomorrow=%LDate%"
  231. CALL :ParseDate %Today%
  232. CALL :JDate %GYear% %GMonth% %GDay%
  233. SET /A "NewJDate = %JDate% - 1"
  234. CALL :GDate %NewJDate%
  235. CALL :ReformatDate %GDate%
  236. SET "Yesterday=%LDate%"
  237. :Skipped1
  238. IF "%Yesterday%"=="" (
  239. 	ECHO          DATEADD  %Today%   1        will return tomorrow's date  ^(as will DATEADD  1^)
  240. 	ECHO          DATEADD  %Today%  -1        will return yesterday's date ^(as will DATEADD -1^)
  241. ) ELSE (
  242. 	ECHO          DATEADD  %Today%   1        will return %Tomorrow%
  243. 	ECHO          DATEADD  1                     will return %Tomorrow% too
  244. 	ECHO          DATEADD  %Today%  -1        will return %Yesterday%
  245. 	ECHO          DATEADD  -1                    will return %Yesterday% too
  246. )
  247. :: End of "advanced" examples section
  248. :Skipped2
  249. ECHO.
  250. ECHO Notes:   By default, the returned date will be presented in the local date
  251. ECHO          format; however, if the date in the command line argument is in the
  252. ECHO          ISO 8601 yyyy-MM-dd format, the result will be in ISO 8601 format too.
  253. ECHO          Unlike its earlier 1.* versions, this batch file does not require
  254. ECHO          elevated privileges.
  255. ECHO.
  256. ECHO Credits: Julian date conversion based on Fliegel-Van Flandern algorithms from
  257. ECHO          the Astronomical Almanac, provided by Doctor Fenton on the Math Forum
  258. ECHO          http://mathforum.org/library/drmath/view/51907.html
  259. ECHO          and converted to batch code by Ron Bakowski.
  260. ECHO.
  261. ECHO Written by Rob van der Woude
  262. ECHO http://www.robvanderwoude.com
  263.  
  264. IF "%OS%"=="Windows_NT" ENDLOCAL
  265. IF "%OS%"=="Windows_NT" EXIT /B 1
  266.  

page last modified: 2024-04-16; loaded in 0.0224 seconds