Skip to content

Instantly share code, notes, and snippets.

@santa4nt
Created November 3, 2010 01:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save santa4nt/660674 to your computer and use it in GitHub Desktop.
Save santa4nt/660674 to your computer and use it in GitHub Desktop.
Advance (or reverse) system clock a specified number of days.
@echo off
setlocal
set Error=0
if "%~1" == "" goto SYNTAX
if not "%~2" == "" goto SYNTAX
for %%A in (%DATE%) do set cDate=%%A
set cDays=%~1
:: Read the Date format from the registry
call :ReadDateFormat
:: Parse the date specified
call :ParseDate %cDate%
:: Check for errors
if %Error% NEQ 0 goto Syntax
:: Convert the parsed Gregorian date to Julian
call :JDate %GYear% %GMonth% %GDay%
:: Display current date
echo Starting date: %cDate%
:: Add or subtract the specified number of days
if "%cDays:~0,1%" == "-" (
set /a NewJDate = %JDate% - %cDays:~1%
echo Days subtracted: %cDays:~1%
) else (
set /a NewJDate = %JDate% + %cDays%
echo Days added: %cDays%
)
:: Convert the new Julian date back to Gregorian again
call :GDate %NewJDate%
:: Reformat the date to local format
call :ReformatDate %GDate%
:: Display the result
echo Resulting date: %LDate%
:: Set the system clock to the resulting date
date %LDate%
:: Return the result in a variable named after this abtch file
endlocal & set %~n0=%LDate%
goto:eof
:: -----------------------------------------------------------------------------
:: Subroutines
:: -----------------------------------------------------------------------------
:ReadDateFormat
:: Read the Date format from the registry.
:: Argumnets: none
:: Returns: sDate (separator). iDate (date format number)
::
:: First, export registry settings to a temporary file
start /w regedit /e "%TEMP%.\_TEMP.REG" "HKEY_CURRENT_USER\Control Panel\International"
:: Now, read the exported data
for /f "tokens=1* delims==" %%A in ('type "%TEMP%.\_TEMP.REG" ^| find /i "iDate"') do set iDate=%%B
for /f "tokens=1* delims==" %%A in ('type "%TEMP%.\_TEMP.REG" ^| find /i "sDate"') do set sDate=%%B
:: Remove the temporary file:
del "%TEMP%.\_TEMP.REG"
:: Remove quotes from the data read:
for %%A in (%iDate%) do set iDate=%%~A
for %%A in (%sDate%) do set sDate=%%~A
goto:eof
:ParseDate
:: Parse (Gregorian) date depending on registry's date format settings
:: Argument : Gregorian date in local date format,
:: Requires : sDate (local date separator), iDate (local date format number)
:: Returns : GYear (4-digit year), GMonth (2-digit month), GDay (2-digit day)
::
if %iDate% == 0 for /f "tokens=1-3 delims=%sDate%" %%A in ('echo.%1') do (
set GYear=%%C
set GMonth=%%A
set GDay=%%B
)
if %iDate% == 1 for /f "tokens=1-3 delims=%sDate%" %%A in ('echo.%1') do (
set GYear=%%C
set GMonth=%%B
set GDay=%%A
)
if %iDate% == 2 for /f "tokens=1-3 delims=%sDate%" %%A in ('echo.%1') do (
set GYear=%%A
set GMonth=%%B
set GDay=%%C
)
if %GDay% GTR 31 set Error=1
if %GMonth% GTR 12 set Error=1
goto:eof
:JDate
:: Convert date to Julian
:: Arguments : YYYY MM DD
:: Returns : Julian date
::
:: First strip leading zeroes
set MM=%2
set DD=%3
if %MM:~0,1% EQU 0 set MM=%MM:~1%
if %DD:~0,1% EQU 0 set DD=%DD:~1%
::
:: Algorithm based on Fliegel-Van Flandern
:: algorithm from the Astronomical Almanac,
:: provided by Doctor Fenton on the Math Forum
:: (http://mathforum.org/library/drmath/view/51907.html),
:: and converted to batch code by Ron Bakowski.
set /A Month1 = ( %MM% - 14 ) / 12
set /A Year1 = %1 + 4800
set /A JDate = 1461 * ( %Year1% + %Month1% ) / 4 + 367 * ( %MM% - 2 -12 * %Month1% ) / 12 - ( 3 * ( ( %Year1% + %Month1% + 100 ) / 100 ) ) / 4 + %DD% - 32075
for %%A in (Month1 Year1) do set %%A=
goto:eof
:GDate
:: Convert Julian date back to "normal" Gregorian date
:: Argument : Julian date
:: Returns : YYYY MM DD
::
:: Algorithm based on Fliegel-Van Flandern
:: algorithm from the Astronomical Almanac,
:: provided by Doctor Fenton on the Math Forum
:: (http://mathforum.org/library/drmath/view/51907.html),
:: and converted to batch code by Ron Bakowski.
::
set /a P = %1 + 68569
set /a Q = 4 * %P% / 146097
set /a R = %P% - ( 146097 * %Q% +3 ) / 4
set /a S = 4000 * ( %R% + 1 ) / 1461001
set /a T = %R% - 1461 * %S% / 4 + 31
set /a U = 80 * %T% / 2447
set /a V = %U% / 11
set /a GYear = 100 * ( %Q% - 49 ) + %S% + %V%
set /a GMonth = %U% + 2 - 12 * %V%
set /a GDay = %T% - 2447 * %U% / 80
:: Clean up the mess
for %%A in (P Q R S T U V) do set %%A=
:: Add leading zeroes
if 1%GMonth% LSS 20 set GMonth=0%GMonth%
if 1%GDay% LSS 20 set GDay=0%GDay%
:: Return value
set GDate=%GYear% %GMonth% %GDay%
goto:eof
:ReformatDate
:: Reformat the date back to the local format
:: Arguments : YYYY MM DD
:: Returns : LDate (Gregorian date in local format)
::
if %iDate% == 0 set LDate=%2%sDate%%3%sDate%%1
if %iDate% == 1 set LDate=%3%sDate%%2%sDate%%1
if %iDate% == 2 set LDate=%1%sDate%%2%sDate%%3
goto:eof
:SYNTAX
echo AdvanceDays.bat
echo Add (or subtract) the specified number of days from the current date,
echo and then set the system clock to that date.
echo.
echo Usage: AdvanceDays days
echo.
echo Where: "days" is the number of days to add or subtract
echo.
echo Derived from a script written by Rob van der Woude
echo http://www.robvanderwoude.com
goto:eof
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment