How to get the day of year in a batch file - windows

How can I get the day of year from the current date in a Windows batch file?
I have tried
SET /A dayofyear=(%Date:~0,2%*30.5)+%Date:~3,2%
But it does not work with leap years, and it is always off by a few days. I would not like to use any third-party executables.

If you want the Julian Day Number, you may use the method posted in my accepted answer given at previous link. However, the "day of year" is just a number between 1 and 365 (366 for leap years). The Batch file below correctly calculate it:
#echo off
setlocal EnableDelayedExpansion
set /A i=0, sum=0
for %%a in (31 28 31 30 31 30 31 31 30 31 30 31) do (
set /A i+=1
set /A accum[!i!]=sum, sum+=%%a
)
set /A month=1%Date:~0,2%-100, day=1%Date:~3,2%-100, yearMOD4=%Date:~6,4% %% 4
set /A dayOfYear=!accum[%month%]!+day
if %yearMOD4% equ 0 if %month% gtr 2 set /A dayOfYear+=1
echo %dayOfYear%
Note: This relies on the date format MM/DD/YYYY.
EDIT 2020/08/10: Better method added
I modified the method so it now uses wmic to get the date. The new method is also shorten, but no simpler! ;):
#echo off
setlocal
set "daysPerMonth=0 31 28 31 30 31 30 31 31 30 31 30"
for /F "tokens=1-3" %%a in ('wmic Path Win32_LocalTime Get Day^,Month^,Year') do (
set /A "dayOfYear=%%a, month=%%b, leap=!(%%c%%4)*(((month-3)>>31)+1)" 2>NUL
)
set /A "i=1, dayOfYear+=%daysPerMonth: =+(((month-(i+=1))>>31)+1)*%+leap"
echo %dayOfYear%

#Aacini's answer has got two weak points (although it suffices for many applications, and it is a great approach after all!):
the retrieved system date relies on format MM/DD/YYYY, but %Date% is locale-dependent;
the calculation does not fully comply with the definition of leap years (see this article);
The following is a revised version of #Aacini's batch script (described within explanatory remarks):
#echo off
setlocal EnableDelayedExpansion
set /A i=0, sum=0
rem accumulate day-offsets for every month in %accum[1...12]%
for %%a in (31 28 31 30 31 30 31 31 30 31 30 31) do (
set /A i+=1
set /A accum[!i!]=sum, sum+=%%a
)
rem check for availability of alternative date value given via (1st) command line argument,
rem just for convenient batch testing
if "%1"=="" (
rem WMIC retrieves current system date/time in standardised format;
rem parse its output by FOR /F, then store it in %CurrDate%
for /F "tokens=2 delims==" %%D in ('wmic OS GET LocalDateTime /VALUE ^| find "="') do (
set CurrDate=%%D
)
) else (
rem apply date value from command line in YYYYMMDD format (not checked for validity)
set CurrDate=%1
)
rem extract %month% and %day%;
set /A month=1%CurrDate:~4,2%-100, day=1%CurrDate:~6,2%-100
rem compute several moduli needed for determining whether year is leap year
set /A yearMOD4=%CurrDate:~0,4% %% 4
set /A yearMOD100=%CurrDate:~0,4% %% 100, yearMOD400=%CurrDate:~0,4% %% 400
rem calculate %dayOfYear% as it were not a leap year
set /A dayOfYear=!accum[%month%]!+day
rem adapt %dayOfYear% only in case %month% is past February (29th)
if %month% gtr 2 (
rem check for leap year and adapt %dayOfYear% accordingly
if %yearMOD4% equ 0 set /A dayOfYear+=1
if %yearMOD400% neq 0 if %yearMOD100% equ 0 set /A dayOfYear-=1
)
rem compound statement to let %dayOfYear% survive SETLOCAL/ENDLOCAL block
endlocal & set dayOfYear=%dayOfYear%
rem return result
echo %dayOfYear%

This use the laps years in editable in loop | for /l %%L in (2020 4 2100) | < or more!
#echo off & setlocal enabledelayedexpansion && set "_cmd=Get Day^,Month^,Year^"
for /l %%L in (2020 4 2100)do set "_array_leap_year_=!_array_leap_year_!%%L,"
for /f "tokens=1-3delims= " %%a in ('wmic Path Win32_LocalTime !_cmd! ^| findstr /r "[0-9]"')do (
set "_yy=%%c" & set "_mm=0%%b" & set "_dd=0%%a" && set "_mm=!_mm:~-2!" & set "_dd=!_dd:~-2!" & set _date=!_yy!_!_mm!_!_dd!)
echo/!_array_leap_year_!|findstr /lic:"!_date:~0,4!," >nul&&(set "_leap_=29" & set "_year_=366")||(set "_leap_=28" & set "_year_=365")
set "_mm_dd_year_=01-31,02-!_leap_!,03-31,04-30,05-31,06-30,07-31,08-31,09-30,10-31,11-30,12-31" && set /a "_cnt=0" & set /a "_loop=!_mm! * 6"
(for /l %%d in (0 6 !_loop!)do set "_sum=!_mm_dd_year_:~%%d,5!" & if "9!_sum:~,2!" lss "9!_mm!" set /a "_day_year_+=!_sum:~-2!")
set /a "_day_year_+=!_dd!" && set /a "_remain=!_day_year_! - !_year_!" && echo/Today: !_date! ^| Day of Year: !_day_year_! ^| Days Remaining: !_remain:-=!
| Result | Today: 2019_04_21 | Day of Year: 111 | Days Remaining: 254
Conventional formatting:
#echo off & setlocal enabledelayedexpansion
set "_cmd=Get Day^,Month^,Year^"
for /l %%L in (2020 4 2100)do set "_array_leap_year_=!_array_leap_year_!%%L,"
for /f "tokens=1-3delims= " %%a in ('wmic Path Win32_LocalTime !_cmd! ^| findstr /r "[0-9]"')do (
set "_yy=%%c"
set "_mm=0%%b"
set "_dd=0%%a"
set "_mm=!_mm:~-2!"
set "_dd=!_dd:~-2!"
set _date=!_yy!_!_mm!_!_dd!
)
echo/!_array_leap_year_!|findstr /lic:"!_date:~0,4!," >nul && (
set "_leap_=29" & set "_year_=366" )||( set "_leap_=28" & set "_year_=365" )
set "_mm_dd_year_=01-31,02-!_leap_!,03-31,04-30,05-31,06-30,07-31,08-31,09-30,10-31,11-30,12-31"
set /a "_loop=!_mm! * 6"
for /l %%d in (0 6 !_loop!)do set "_sum=!_mm_dd_year_:~%%d,5!" && (
if "9!_sum:~,2!" lss "9!_mm!" set /a "_day_year_+=!_sum:~-2!" )
set /a "_day_year_+=!_dd!"
set /a "_remain=!_day_year_! - !_year_!"
echo/Today: !_date! ^| Day of Year: !_day_year_! ^| Days Remaining: !_remain:-=!

Related

batch script Errror : get the day of the year

This script let me get the day of year from the current date in a Windows batch file
i used it since january without problem but this month the script breaks off unnoticed and show incorrect informations.
This is the error :
Invalid number. Numeric constants are either decimal (17),
hexadecimal (0x11) or octal (021) numbers.
here is the batch code
#echo off & setlocal enabledelayedexpansion
set "_cmd=Get Day^,Month^,Year^"
for /l %%L in (2020 4 2100)do set "_array_leap_year_=!_array_leap_year_!%%L,"
for /f "tokens=1-3delims= " %%a in ('wmic Path Win32_LocalTime !_cmd! ^| findstr /r "[0-9]"')do (
set "_yy=%%c"
set "_mm=0%%b"
set "_dd=0%%a"
set "_mm=!_mm:~-2!"
set "_dd=!_dd:~-2!"
set _date=!_yy!_!_mm!_!_dd!
)
echo/!_array_leap_year_!|findstr /lic:"!_date:~0,4!," >nul && (
set "_leap_=29" & set "_year_=366" )||( set "_leap_=28" & set "_year_=365" )
set "_mm_dd_year_=01-31,02-!_leap_!,03-31,04-30,05-31,06-30,07-31,08-31,09-30,10-31,11-30,12-31"
set /a "_loop=!_mm! * 6"
for /l %%d in (0 6 !_loop!)do set "_sum=!_mm_dd_year_:~%%d,5!" && (
if "9!_sum:~,2!" lss "9!_mm!" set /a "_day_year_+=!_sum:~-2!" )
set /a "_day_year_+=!_dd!"
set /a "_remain=!_day_year_! - !_year_!"
echo/Today: !_date! ^| Day of Year: !_day_year_! ^| Days Remaining: !_remain:-=!
Copy the code exactly as is:
All we changed here is set /a "_loop=1!_mm! * 6 - 600" which effectively does set _loop=108 * 6 - 600 which results in 48 same result as 6 * 8
#echo off & setlocal enabledelayedexpansion
set "_cmd=Get Day^,Month^,Year^"
for /l %%L in (2020 4 2100)do set "_array_leap_year_=!_array_leap_year_!%%L,"
for /f "tokens=1-3delims= " %%a in ('wmic Path Win32_LocalTime !_cmd! ^| findstr /r "[0-9]"')do (
set "_yy=%%c"
set "_mm=0%%b"
set "_dd=0%%a"
set "_mm=!_mm:~-2!"
set "_dd=!_dd:~-2!"
set _date=!_yy!_!_mm!_!_dd!
)
echo/!_array_leap_year_!|findstr /lic:"!_date:~0,4!," >nul && (
set "_leap_=29" & set "_year_=366" )||( set "_leap_=28" & set "_year_=365" )
set "_mm_dd_year_=01-31,02-!_leap_!,03-31,04-30,05-31,06-30,07-31,08-31,09-30,10-31,11-30,12-31"
set /a "_loop=1!_mm! * 6 - 600"
for /l %%d in (0 6 !_loop!)do set "_sum=!_mm_dd_year_:~%%d,5!" && (
if "9!_sum:~,2!" lss "9!_mm!" set /a "_day_year_+=!_sum:~-2!" )
set /a "_day_year_+=!_dd!"
set /a "_remain=!_day_year_! - !_year_!"
echo/Today: !_date! ^| Day of Year: !_day_year_! ^| Days Remaining: !_remain:-=!
You may use this simpler method instead:
#echo off
setlocal EnableDelayedExpansion
set /A i=0, sum=0
for %%a in (31 28 31 30 31 30 31 31 30 31 30 31) do (
set /A i+=1
set /A accum[!i!]=sum, sum+=%%a
)
for /F "tokens=1-3" %%a in ('wmic Path Win32_LocalTime Get Day^,Month^,Year') do (
set /A day=%%a, month=%%b, yearMOD4=%%c %% 4 2>NUL
)
set /A dayOfYear=accum[%month%]+day
if %yearMOD4% equ 0 if %month% gtr 2 set /A dayOfYear+=1
echo %dayOfYear%
EDIT: Simpler method added
This method may be simplified and shorten this way:
#echo off
setlocal
set "daysPerMonth=0 31 28 31 30 31 30 31 31 30 31 30"
for /F "tokens=1-3" %%a in ('wmic Path Win32_LocalTime Get Day^,Month^,Year') do (
set /A "dayOfYear=%%a, month=%%b, leap=!(%%c%%4)*(((month-3)>>31)+1)" 2>NUL
)
set /A "i=1, dayOfYear+=%daysPerMonth: =+(((month-(i+=1))>>31)+1)*%+leap"
echo %dayOfYear%
You could, of course, use powershell from your batch-file too:
#For /F %%G In ('%__AppDir__%WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command ^
"$NOW=Get-Date;$DOY=$NOW.DayOfYear;$YDR=(Get-Date -Month 12 -Day 31).DayOfYear-$DOY;" ^
"Write-Host ""_date=$($NOW.ToString('yyyy_MM_dd'))`n_day_year_=$DOY`n_remain=$YDR"""'
)Do #Set "%%G"
#Echo Today: %_date% ^| Day of Year: %_day_year_% ^| Days Remaining: %_remain% & Pause

using a FOR /L loop to loop through the months of the year depedning on the current month in a batch file

I am trying to do a FOR /L loop for a class of mine i have gotten it to loop the 12 times but its not changing the MonthName variable to display each month. what i want it ot so is take the current month number and execute the loop that many times with the months of the year like for the first time through the loop i want it to display 1. January then 2. Febuary and so on till it reaches the current month here is the code i have so far and a sample execution i can only get it to display the current month's name
rem #echo off
setlocal enabledelayedexpansion
set CurrentMonth=%date:~4,2%
IF %currentMonth% EQU 08 (
set /a currentMonth=8
)
IF %currentMonth% EQU 09 (
set /a currentMonth=9
)
set Mmap=1-Januray;2-Febuary;3-March;4-April;5-May;6-June;7-July;8-August;9-September;10-October;11-November;12-December;
FOR /L %%x in (1,1,!CurrentMonth!) DO (
call set MonthName=%%Mmap:*%%x-=%%
set MonthName=%MonthName:;=&rem.%
echo %%x !MonthName! )
C:\Users\cis106stu\BATCHFILES5>FORLOOP
1 December
2 December
3 December
4 December
5 December
6 December
7 December
8 December
9 December
10 December
11 December
12 December
C:\Users\cis106stu\BATCHFILES5>
As you insist on using a for /l loop:
#echo off
setlocal enabledelayedexpansion
set /a CurrentMonth=1%date:~4,2%-100
set "Mmap=;1-Januray;2-Febuary;3-March;4-April;5-May;6-June;7-July;8-August;9-September;10-October;11-November;12-December;"
FOR /L %%x in (1,1,!CurrentMonth!) DO (
set MonthName=!Mmap:*;%%x-=!
for /f "delims=;" %%y in ("!MonthName!") do echo %%x %%y
)
I added a leading ; to Mmap, used another method to split the string and took advantage of delayed expansion (why not use it when you already enabled it)
(Note: the format of %date% is highly user configurable, so %date:~4,2% may extract the wrong string. It works for the format DDD MM/dd/yyyy and has to be adapted for other formats (better use a settings-independent solution))
Just use a for /l loop and loop 12 times to get the variables we've set and wmic to determine the month you're in.
#echo off
set "m1=January" & set "m2=February" & set "m3=March" & set "m4=April" & set "m5=May" & set "m6=June" & set "m7=July" & set "m8=August" & set "m9=September" & set "m10=October" & set "m11=November" & set "m12=December"
for /f %%i in ('wmic path win32_localtime get month ^| findstr /r /c:[1-12]') do for /l %%a in (1,1,12) do if %%a leq %%i call echo %%a %%m%%a%%%
The above does not require the CurrentMonth variable to be set as the metavariable %%i has that value. If you however still want to set the variable, you can:
#echo off
set "m1=January" & set "m2=February" & set "m3=March" & set "m4=April" & set "m5=May" & set "m6=June" & set "m7=July" & set "m8=August" & set "m9=September" & set "m10=October" & set "m11=November" & set "m12=December"
for /f %%i in ('wmic path win32_localtime get month ^| findstr /r /c:[1-12]') do set /a CurrentMonth=%%i
for /l %%a in (1,1,12) do if %%a leq %CurrentMonth% call echo %%a %%m%%a%%%
Let me suggest an alternative approach (both with correcting the date format and with the extraction from the string Mmap:
#echo off
setlocal
set /a CurrentMonth=1%date:~4,2%-100
set "Mmap=1-Januray;2-Febuary;3-March;4-April;5-May;6-June;7-July;8-August;9-September;10-October;11-November;12-December"
for %%a in (%Mmap%) do (
for /f "tokens=1,2 delims=-" %%b in ("%%a") do (
if %%b leq %CurrentMonth% echo %%b %%c
)
)
(Note: the format of %date% is highly user configurable, so %date:~4,2% may extract the wrong string. It works for the format DDD MM/dd/yyyy and has to be adapted for other formats (better use a settings-independent solution))

Day minus in windows batch file in 2 digit

I have a bat file which simply generates a date
for /f "tokens=2,3,4 delims=/ " %%a in ('date /t') do set CurrYear=%%c
for /f "tokens=2,3,4 delims=/ " %%a in ('date /t') do set CurrMoth=%%a
for /f "tokens=2,3,4 delims=/ " %%a in ('date /t') do set CurrDay=%%b
set bDate =01/%CurrMoth%/%CurrYear%
set eDate=%CurrDay%/%CurrMoth%/%CurrYear%
set /a dayminus = %CurrDay% - 1
echo %dayminus%
pause
The answer I get for echo %dayminus% is 6 instead of 06 & that's my problem.
If your intent is to simply ensure a number is left-zero-padded to two places, you can just use:
if %dayminus% lss 10 set dayminus=0%dayminus%
However, you'll soon run into another problem, specifically what you do when you run this on the first of the month. But that's probably a matter for a separate question (or you could just look at this one).
If you're open to using other tools (which ship with Windows, just like cmd.exe does), then VBScript is possibly the easiest option. You can just create a one-liner yesterdom.vbs:
wscript.echo day(date()-1)
and then call it from your script:
for /f %%a in ('cscript //nologo yesterdom.vbs') do set dayminus=%%a
If you don't want the hassle of maintaining the one-liner, you can create and destroy it from within your script, such as with:
#echo off
echo wscript.echo day(date()-1) >yesterdom.vbs
for /f %%a in ('cscript //nologo yesterdom.vbs') do set dayminus=%%a
del /q yesterdom.vbs >nul: 2>nul:
echo %dayminus%
(Interestingly, most people want to know how to go the other way.) The reason this is happening is because batch considers numbers that begin with a 0 to be octal and then simplifies them to drop the 0 when printing as an integer. You can get around this by treating the variable like a string instead.
set /a dayminus=%CurrDay%-1
if %dayminus% lss 10 (
set dayminus=0%dayminus%
)
echo %dayminus%
Here is a quick workaround that I have prepared for you in a sample program:
#echo off
set /a test = 4
IF %test% lss 10 (
#echo 0%test%
)
#pause
This will always get you a two digit number since anything below 10 will have the added 0 in front of it when it's being written to the screen.
This is a pure Batch file solution that get the date of yesterday; it also works for the current date minus any number of days less than a month:
#echo off
setlocal EnableDelayedExpansion
rem Create array of days per month; both month and day are 100-based
set i=100
for %%a in (31 28 31 30 31 30 31 31 30 31 30 31) do (
set /A i+=1
set "daysPerMonth[!i!]=1%%a"
)
rem Get today's date parts (from "Dow MM/DD/YYYY" format) - 1 day
for /F "tokens=2-4 delims=/ " %%a in ('date /T') do (
set /A MM=1%%a, DD=1%%b-1, YYYY=%%c, YYYYmod4=YYYY %% 4
)
if %YYYYmod4% equ 0 set "daysPerMonth[102]=129"
rem Adjust date if previous month
if %DD% equ 100 (
set /A MM-=1
if !MM! equ 100 (
set /A MM=112, YYYY-=1
)
set /A DD=daysPerMonth[!MM!]
)
set "dateMinus=%DD:~1%/%MM:~1%/%YYYY%
echo %dateMinus%

Split %date% in a batch file regardless of Regional Settings

Is there a way to split the %date% in a batch file (say, in 3 environment variables), but regardless of Regional Settings? Today's date would be 3/13/2013 for US, but with my Regional Settings it is 13.3.2013 - the delimiter is changed and the order as well.
Four years have passed, but this question doesn't get old, and I think now there's a slightly better answer than using wmic (on win7 onwards).
for /F "tokens=1,2,3 delims=_" %%i in ('PowerShell -Command "& {Get-Date -format "MM_dd_yyyy"}"') do (
set MONTH=%%i
set DAY=%%j
set YEAR=%%k
)
echo %MONTH% %DAY% %YEAR%
With powershell Get-Date you can fine-tune the format you want (short,long, numbers,names,etc..). In this example "MM_dd_yyyy" will get you a numeric date with leading zeros in case of single digit months or days
You can do it using wmic (but WMIC isn't included with XP Home):
#ECHO OFF
:: Check WMIC is available
WMIC.EXE Alias /? >NUL 2>&1 || GOTO s_error
:: Use WMIC to retrieve date and time
FOR /F "skip=1 tokens=1-6" %%G IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table') DO (
IF "%%~L"=="" goto s_done
Set _yyyy=%%L
Set _mm=00%%J
Set _dd=00%%G
Set _hour=00%%H
SET _minute=00%%I
)
:s_done
:: Pad digits with leading zeros
Set _mm=%_mm:~-2%
Set _dd=%_dd:~-2%
Set _hour=%_hour:~-2%
Set _minute=%_minute:~-2%
:: Display the date/time in ISO 8601 format:
Set _isodate=%_yyyy%-%_mm%-%_dd% %_hour%:%_minute%
Echo %_isodate%
GOTO:EOF
:s_error
Echo GetDate.cmd
Echo Displays date and time independent of OS Locale, Language or date format.
Echo Requires Windows XP Professional, Vista or Windows 7
Echo.
Echo Returns 6 environment variables containing isodate,Year,Month,Day,hour and minute.
And you can do it by parsing the date command to lookup what the current date format is required to be.
The first link indicates you might need to edit the code in the second, on Win7, to handle a few extra wrinkles around short date/long date form.
I've reworked sashoalm's version to take care of the suppressed-leading-zero situation:
#Echo OFF
SETLOCAL
If "%Date%A" LSS "A" (Set _NumTok=1-3) Else (Set _NumTok=2-4)
:: Default Delimiter of TAB and Space are used
For /F "TOKENS=2*" %%A In ('REG QUERY "HKCU\Control Panel\International" /v iDate') Do Set _iDate=%%B
For /F "TOKENS=2*" %%A In ('REG QUERY "HKCU\Control Panel\International" /v sDate') Do Set _sDate=%%B
IF %_iDate%==0 For /F "TOKENS=%_NumTok% DELIMS=%_sdate% " %%F In ("%Date%") Do CALL :procdate %%H %%F %%G
IF %_iDate%==1 For /F "TOKENS=%_NumTok% DELIMS=%_sdate% " %%F In ("%Date%") Do CALL :procdate %%H %%G %%F
IF %_iDate%==2 For /F "TOKENS=%_NumTok% DELIMS=%_sdate% " %%F In ("%Date%") Do CALL :procdate %%F %%G %%H
endlocal&SET YYYYMMDD=%YYYYMMDD%
GOTO :eof
::
:: Date elements are supplied in Y,M,D order but may have a leading zero
::
:procdate
:: if single-digit day then 1%3 will be <100 else 2-digit
IF 1%3 LSS 100 (SET YYYYMMDD=0%3) ELSE (SET YYYYMMDD=%3)
:: if single-digit month then 1%2 will be <100 else 2-digit
IF 1%2 LSS 100 (SET YYYYMMDD=0%2%YYYYMMDD%) ELSE (SET YYYYMMDD=%2%YYYYMMDD%)
:: Similarly for the year - I've never seen a single-digit year
IF 1%1 LSS 100 (SET YYYYMMDD=20%YYYYMMDD%) ELSE (SET YYYYMMDD=%1%YYYYMMDD%)
GOTO :eof
returning YYYYMMDD - substring at your will.
Interestingly, inserting after SETLOCAL
IF NOT "%1"=="" set date=%1
will allow any date in the local sequence (without the dayname) to be decoded to YYYYMMDD (but be careful that 19xx dates provided with the yy form will appear as 20xx - easily compensated-for if you find it necessary)
I have an additional suggestion with robocopy:
#echo off &setlocal enabledelayedexpansion
set "day="
for /f "tokens=3,4,8skip=4delims=: " %%i in ('robocopy') do if not defined day (
set "month=%%i"
set "day=0%%j"
set "year=%%k"
)
set /a cnt=0
for %%i in (Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec) do (
set /a cnt+=1
if "%%i"=="%month%" set "month=0!cnt!"
)
set "day=%day:~-2%"
set "month=%month:~-2%"
echo.%day%.%month%.%year%
endlocal
Try this: Set_date.cm
#echo off&goto :start
:Set_Date DateEnv [Date] or [/p="Prompt for Date: "] [/r]
echo.
echo.Usage: Set_Date.cmd DateEnv [Date] or [/p="Prompt for Date: "]
echo.Populates date variables labeled: 'DateEnv_???', see below
echo.Accepted date formats:
echo. m-d-y, m/d/y, yyyymmdd, dd-Mon-yy or 7 digit julian date
echo. If "%%date%%" is passed as the 2nd arg it will be interpreted
echo. according to the current regional date setting ie. day dd/mm/yyyy
echo. If /r is passed then the date contained in the DateEnv variable
echo. and/or the [Date] argument will be interpreted in regional format
echo. The /r option should be placed at the end of the list if used
echo. The /r option should only be used if date input is not included
echo. in one of the default listed formats or unexpected consequences...
echo.
echo.DateEnv, if passed alone may be a valid defined date variable or if
echo.undefined then todays date will be used to populate the variables
echo.Two digit years input 'XX' are interpreted as the year '20XX'
echo.Valid dates must be in the year 1601 or greater for the validity check
echo.Returns 0 in errorlevel if the date is valid, else non-zero
echo.
echo.If DateEnv is valid or if [Date] is passed DateEnv_??? will be set to:
echo.DateEnv_mdy will be set to mm-dd-yyyy
echo.DateEnv_ymd will be set to yyyymmdd
echo.DateEnv_y.m.d will be set to yyyy.mm.dd
echo.DateEnv_dte will be set to the current active regional date format
echo.DateEnv_jul will be set to the 7 digit Julian date
echo.DateEnv_dow will be set to day of week, ie. Monday, Tuesday, etc.
echo.DateEnv_vrb will be set to Verbose Date, ie. Saturday, August 20th, 2011
echo.DateEnv_dd will be set to the 2 digit day
echo.DateEnv_mm will be set to the 2 digit month
echo.DateEnv_yyyy will be set to the 4 digit year
echo.DateEnv_month will be set to the month, ie. February or December
echo.DateEnv_mon will be set to the 3 letter month, ie. Jan or Aug
echo.
echo.DateEnv itself will not be changed regardless if its a valid date or not
echo.Also formats yyyymmdd or 7 digit julian date input to desired output
echo.Example: Set_Date today "%%date%%" or Set_Date newyear99 01-Jan-99
echo.
echo.Finally:
echo.If DateEnv is not defined and there is no second argument then %%date%% in
echo.the current regional format will be used to populate the variables
echo.If /p is passed as 2nd argument then quoted 3rd argument will prompt for date
echo.
echo.Examples:
echo. set "AprilsFools=4/1/1"
echo. set_date AprilFools
echo. echo Aprils fools date for 2001 in Julian format is: %%AprilFools_jul%%
echo. echo Aprils fools date in 2001 was on a %AprilFools_dow% ^(Sunday^)
echo. Set_Date birthday /p="Enter your birth date: "
echo. ECHO You were born on a %%birthday_dow%%
echo. set "today="
echo. Set_Date today
echo. echo today is %%today_dte%% or %%today_jul%% in Julian format
echo.
echo.If the '/p' option is used then the _GetString.cmd routine must be in the PATH
echo. or else set/p routine will ask for date with no validity checking
exit /b 1
:start
set "jul="&set "Format="&set "Sep="&set "reg="
if "%~1"=="" exit /b 255
if /i "%~1" equ "/?" goto :Set_Date Syntax
SetLocal EnableDelayedExpansion
echo %*|find /i "/r">nul
if %errorlevel% equ 0 set/a reg=1&if /i "%~1" equ "/r" shift
if defined %~1 (call set jul=%%%~1%%) else (
if "%~2"=="" set "jul=%date%"
)
if not "%~2"=="" (
if /i "%~2" neq "/r" (
set "jul=%~2"&set "args=%~3"
)
) else (if not defined %~1 set/a reg=1)
call :RegDateFmt Format Separator yy mm dd jul
if %errorlevel% neq 0 goto :BadDate
if /i "%~2" equ "%date%" set/a reg=1
if defined reg (
set "jul=!mm!-!dd!-!yy!"
)
if /i "%jul%" equ "/p" (
call :_GetString.cmd "%args%" jul /d
if !errorlevel! gtr 0 goto :BadDate
) else if /i "%jul:~0,1%" gtr "9" (
if defined args set "jul=%jul% %args%"
set "jul=!jul:* =!"
) else if /i "%jul:~3,1%" gtr "9" (
set "Mon=%jul:~3,3%"
call :month_convert Mon
if !errorlevel! gtr 0 goto :BadDate
set "jul=!Mon!-%jul:~0,2%-%jul:~-2%"
)
set mdy=%jul:/=%
set mdy=%mdy:-=%
if /i %mdy% equ %jul% (
call :strlen %mdy%
if /i !errorlevel! equ 7 (
call :date_cvt mdy /j
) else (call :date_cvt jul /j)
) else (call :date_cvt jul /j)
if /i %errorlevel% equ 0 (
set/a mdy=%jul%
set/a dow=%jul% %% 7&call :set_day dow
) else (goto :BadDate)
call :date_cvt mdy /j
set "vrb=%mdy%"
call :format_verbose vrb dow month
set/a ymd=%errorlevel%
set "mon=%month:~0,3%"
set/a dte=%ymd%
call :setRegDate dte Format Separator dow mon
if /i %errorlevel% gtr 0 goto :BadDate
Endlocal&(
call set "%~1_mdy=%mdy%"&call set "%~1_ymd=%ymd%"&call set "%~1_jul=%jul%"
call set "%~1_vrb=%vrb%"&call set "%~1_dow=%dow%"&call set "%~1_dd=%ymd:~-2%"
call set "%~1_mm=%mdy:~0,2%"&call set "%~1_yyyy=%ymd:~0,4%"
call set "%~1_mon=%mon%"&call set "%~1_yy=%ymd:~2,2%"&call set "%~1_dte=%dte%"
call set "%~1_y.m.d=%ymd:~0,4%.%mdy:~0,2%.%ymd:~-2%"&call set "%~1_month=%month%"
exit /b 0
)
:BadDate
Endlocal&(
call set "%~1_mdy="&call set "%~1_ymd="&call set "%~1_dte="&call set "%~1_jul="
call set "%~1_vrb="&call set "%~1_dow="&call set "%~1_vrb="&call set "%~1_y.m.d="
call set "%~1_month="
)&exit /b %errorlevel%
::**********************************::
::*******|| SUBROUTINES ||*******::
::**********************************::
:set_day
SetLocal&call set/a tkn=%%%~1%%+1
for /f "tokens=%tkn%" %%a in ("Monday Tuesday Wednesday Thursday Friday Saturday Sunday") do (
set "dayofwk=%%a"
)
EndLocal&call set %~1=%dayofwk%&exit /b 1
:Date_Cvt DateEnv [/Julian] Date_env is converted
if "%~1"=="" exit /b 1
SetLocal&call set "mdy=%%%~1%%"
set ech=&set "arg="
if not "%~2"=="" (set arg=%~2&set arg=!arg:~0,2!)
xcopy /d:%mdy% /h /l "%~f0" "%~f0\">nul 2>&1
if /i %errorlevel% equ 0 (
for /f "tokens=1-3 delims=/- " %%a in ("%mdy%") do (
set m=%%a&set d=%%b&set "y=%%c"
if /i 1!m! lss 20 set "m=0!m!"
if /i 1!d! lss 20 set "d=0!d!"
if /i 1!y! lss 20 set "y=0!y!"
if /i !y! lss 80 (set y=20!y!) else (if !y! lss 100 set y=19!y!)
set "mdy=!m!-!d!-!y!"
)
) else (
set /a rc=1
for /f "tokens=1-3 delims=0123456789" %%a in ("%mdy%") do set "rc=%%a"
if /i !rc! neq 1 set /a err=2&goto :end
call :strlen %mdy%
if /i !errorlevel! gtr 8 set /a err=3&goto :end
)
set "mdy=%mdy:/=-%"
set "ymd=%mdy:-=%"
if %ymd%==%mdy% (
call :strlen %ymd%
set /a err=!errorlevel!
if /i !err! equ 7 if /i "%arg%" equ "/j" (
call :gdate %ymd%
set /a ymd=!errorlevel!
set /a err=8&set "arg="
)
if /i !err! neq 8 goto :end
set mdy=!ymd:~4,2!-!ymd:~6,2!-!ymd:~0,4!&set "ech=!mdy!"
) else (
set ymd=%ymd:~4,4%%ymd:~0,4%&set "ech=!ymd!"
)
xcopy /d:%mdy% /h /l "%~f0" "%~f0\">nul 2>&1
set /a err=%errorlevel%
if /i %err% neq 0 (set ech=)
if /i %err% equ 0 if /i "%arg%" equ "/j" (
call :jdate %ymd%
set /a ech=!errorlevel!
)
:end
EndLocal&call set "%~1=%ech%"&exit /b %err%
:Strlen Returns length of string in errorlevel
setlocal&set "#=%*"
if not defined # exit /b 0
set/a len=0
:loop
set/a len+=1
set "#=!#:~1!"&if not defined # endlocal&exit/b %len%
goto :loop
:jdate
SetLocal
set "yyyymmdd=%~1"
set "yyyy=%yyyymmdd:~0,4%"
set "mm=%yyyymmdd:~4,2%"
set "dd=%yyyymmdd:~6,2%"
if %mm:~0,1% equ 0 set "mm=%mm:~1%"
if %dd:~0,1% equ 0 set "dd=%dd:~1%"
set /a Month1=(%mm%-14)/12
set /a Year1=%yyyy%+4800
set /a JDate=1461*(%Year1%+%Month1%)/4+367*(%mm%-2-12*%Month1%)^
/12-(3*((%Year1%+%Month1%+100)/100))/4+%dd%-32075
EndLocal&exit /b %JDate%
:gdate
SetLocal
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
if /i 1%GMonth% lss 20 set "GMonth=0%GMonth%"
if /i 1%GDay% lss 20 set "GDay=0%GDay%"
set "GDate=%GYear%%GMonth%%GDay%"
EndLocal&exit /b %GDate%
:Format_Verbose M/D/Y dayofweek to verbose date
SetLocal&call set "dte=%%%~1%%"
set "dow=%%%~2%%"
set "st="
set "day=%dte:~3,2%"
set "mon=%dte:~0,2%"
set "year=%dte:~6,4%"
set "ymd=%year%%mon%%day%"
set "dy=%day:~1%"
if %day:~0,1% equ 0 set "day=%day:~1%"
if %mon:~0,1% equ 0 set "mon=%mon:~1%"
set months=January February March April May June^
July August September October November December
for /f "tokens=%mon%" %%a in ("%months%") do set "month=%%a"
if /i %dy% equ 0 set "st=th"
if /i %dy% gtr 3 set "st=th"
if /i %day% geq 11 if /i %day% leq 13 set "st=th"
if defined st goto :end
set/a rst=%day% %% 10
for /f "tokens=%rst%" %%s in ("st nd rd") do set "st=%%s"
:end
set "dow=%dow%, %month% %day%%st%, %year%"
EndLocal&call set %~1=%dow%&call set %~3=%month%&exit /b %ymd%
:_GetString.cmd
set p0=%0&set "p0=!p0:~1!"
if not exist _GetString.cmd (
call :checkpath %p0%
if !errorlevel! neq 0 (
set/p %~2="%~1"
exit/b 0
)
)
call _GetString.cmd "%~1" %~2 %~3
exit/b %errorlevel%
:checkpath
if exist "%~$PATH:1" exit/b 0
exit/b 1
:RegDateFmt Format Separator y m d dte
if "%~2"=="" exit/b 1
setlocal EnabledelayedExpansion
set "Day="&set "Mon="&set "dte="
if not "%~6"=="" set "dte=!%~6!"
if not defined dte set "dte=%date%"
for /f "tokens=2 delims=:" %%A in ('date^<nul') do set Format=%%A&goto :next
:next
set "Format=%Format: =%"
for %%A in (/ - . ,) do (
echo %Format%|find "%%A">nul&if !errorlevel! equ 0 set "Separator=%%A"
)
if /i %Format:~0,1% gtr 9 set "Day=Day "
for /f "skip=1 tokens=2-4 delims=(-)" %%a in ('date^<nul') do (
set "Format=%Day%%%a%Separator%%%b%Separator%%%c"
for /f "tokens=1-3 delims=.-/ " %%d in ("%dte:* =%") do (
set %%a=%%d&set %%b=%%e&set "%%c=%%f"
echo !yy:~3!|find "ECHO">nul
if /i "!errorlevel!" neq "0" set "Format=!Format:yy=yyyy!"
if /i "!mm:~0,1!" gtr "9" (
set "Format=!Format:mm=Mon!"
call :month_convert mm
if /i "!errorlevel!" neq "0" endlocal&exit/b 1
)
)
)
endlocal&(
call set "%~1=%Format%"
call set "%~2=%Separator%"
if not "%~3"=="" call set "%~3=%yy%"
if not "%~4"=="" call set "%~4=%mm%"
if not "%~5"=="" call set "%~5=%dd%"
)&exit/b 0
:month_convert
set "months=Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
call set "month=%%%~1%%"
set/a mnum=0
for %%m in (%months%) do set/a mnum+=1&if /i %month% equ %%m call set "%~1=!mnum!"&exit /b 0
exit/b 1
:setRegDate dte format sep dow mon
setlocal EnableDelayedExpansion
if /i "%~5"=="" exit/b 1
set mon=!%~5!&set dow=!%~4!&set "dow=!dow:~0,3! "
set sep=!%~3!&set "format=!%~2!"&set "dte=!%~1!"
set yyyy=%dte:~0,4%&set yy=%dte:~2,2%&set mm=%dte:~4,2%&set "dd=%dte:~-2%"
set "toks=2-4"
echo %format%|find " ">nul
if %errorlevel% equ 1 set "dow="& set "toks=1-3"
for /f "tokens=%toks% delims=%sep% " %%a in ("%format%") do (
set "dte=%dow%!%%a!%sep%!%%b!%sep%!%%c!"
)
endlocal&call set "%~1=%dte%"&exit/b 0
I found this in http://forums.techguy.org/dos-other/837046-solved-date-format-bat-file.html
I've reworked it a bit to actually split it in 3 environment variables.
The downside is it needs to query the registry, probably to find out the order day, month and year.
#Echo Off
Set _Date=%date%
If "%_Date%A" LSS "A" (Set _NumTok=1-3) Else (Set _NumTok=2-4)
:: Default Delimiter of TAB and Space are used
For /F "TOKENS=2*" %%A In ('REG QUERY "HKCU\Control Panel\International" /v iDate') Do Set _iDate=%%B
For /F "TOKENS=2*" %%A In ('REG QUERY "HKCU\Control Panel\International" /v sDate') Do Set _sDate=%%B
IF %_iDate%==0 For /F "TOKENS=%_NumTok% DELIMS=%_sDate% " %%B In ("%_Date%") Do Set _fdate=%%D%%B%%C
IF %_iDate%==1 For /F "TOKENS=%_NumTok% DELIMS=%_sDate% " %%B In ("%_Date%") Do Set _fdate=%%D%%C%%B
IF %_iDate%==2 For /F "TOKENS=%_NumTok% DELIMS=%_sDate% " %%B In ("%_Date%") Do Set _fdate=%%B%%C%%D
Set _Month=%_fdate:~4,2%
Set _Day=%_fdate:~6,2%
Set _Year=%_fdate:~0,4%
Echo _Year=%_Year%
Echo _Month=%_Month%
Echo _Day=%_Day%
REG QUERY is not sufficient, if sShortDate was set to something like dd yy. Use REG ADD:
#echo off &setlocal
for /f "tokens=2*" %%a in ('reg query "HKCU\Control Panel\International" /v sShortDate^|find "REG_SZ"') do set "ssShortDate=%%b"
reg add "HKCU\Control Panel\International" /f /v sShortDate /d "dd MM yyyy" >nul
set "cdate=%date%"
reg add "HKCU\Control Panel\International" /f /v sShortDate /d "%ssShortDate%" >nul
for /f "tokens=1-3" %%i in ("%cdate%") do set "day=0%%i"&set "month=0%%j"&set "year=%%k"
set "day=%day:~-2%"
set "month=%month:~-2%"
echo.%day%.%month%.%year%
endlocal
This function should work on all regions.
Remarks:
Returns month in text format for MMM regions
#echo off
call :GetDateIntl year month day
echo/Using GetDateIntl you get: %year%-%month%-%day%
goto:eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:GetDateIntl yy mm dd [/A]
:: Returns the current date on any machine with regional-independent settings
:: Arguments:
:: yy = variable name for the year output
:: mm = variable name for the month output
:: dd = variable name for the day output
:: /A = OPTIONAL, removes leading 0 on days/months smaller than 10 (example: 01 becomes 1)
:: Remarks:
:: Will return month in text format in regions with MMM month
::
SETLOCAL ENABLEEXTENSIONS
if "%date%A" LSS "A" (set toks=1-3) else (set toks=2-4)
for /f "tokens=2-4 delims=(-)" %%a in ('echo:^|date') do (
for /f "tokens=%toks% delims=.-/ " %%i in ('date/t') do (
set '%%a'=%%i
set '%%b'=%%j
set '%%c'=%%k
)
)
if /I "%'yy'%"=="" set "'yy'=%'aa'%"
if /I "%'yy'%"=="" ( set "'yy'=%'jj'%" & set "'dd'=%'tt'%" )
if %'yy'% LSS 100 set 'yy'=20%'yy'%
endlocal&set %1=%'yy'%&set %4 %2=%'mm'%&set %4 %3=%'dd'%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Below there is a pure Batch solution that just use DATE command and %DATE% variable, so it works on any Windows version. To make this program really universal, just add the name of the day and month parts shown by second line of DATE command in other languages, enclosed in slashes. For example, let's suppose that in German the day part is shown as TT, so you just need to modify this value: set DayNames=/dd/tt/ in order to also use this program in German language Windows (besides all the languages that use DD for the day part).
#echo off
setlocal EnableDelayedExpansion
rem GetStdDate.bat: Get date in standard format independently of Regional Settings
rem Antonio Perez Ayala
rem Set Day and Month names shown by second line of DATE command, enclosed in slashes (add any missing language):
set DayNames=/dd/
set MonthNames=/mm/
rem Get date NAMES from second line of date COMMAND, enclosed in parentheses
for /F "skip=1 tokens=2 delims=()" %%n in ('date ^< NUL') do (
rem Separate and store date names
for /F "tokens=1-3 delims=/-.:" %%a in ("%%n") do (
set one=%%a& set two=%%b& set three=%%c
rem Get date VALUES from %date% VARIABLE
for /F "tokens=1-3 delims=/-.:" %%x in ("%date%") do (
rem Assign date values to date names
set %%a=%%x& set %%b=%%y& set %%c=%%z
)
)
)
rem Identify locale date format and assemble StdDate=YYYY/MM/DD
if "!DayNames:/%one%/=!" neq "%DayNames%" (
rem Locale format is DD/MM/YYYY
set StdDate=!%three%!/!%two%!/!%one%!
) else if "!MonthNames:/%one%/=!" neq "%MonthNames%" (
rem Locale format is MM/DD/YYYY
set StdDate=!%three%!/!%one%!/!%two%!
) else (
rem Locale format is YYYY/MM/DD
set StdDate=!%one%!/!%two%!/!%three%!
)
echo Standard date: %StdDate%
Read a locale independent YYYY-MM-DDThh:mm:ss value.
WMIC gives 20220812142505.576000+180 value and using a simple ~substring we can construct a datetime format.
#set dt=
#CALL :GETDATETIME
#echo Step1 %dt%
#timeout /T 4
#CALL :GETDATETIME
#echo Step2 %dt%
#GOTO :END
:GETDATETIME
#for /f "tokens=2 delims==" %%X in ('wmic os get localdatetime /value') do #set dt=%%X
#set dt=%dt:~0,4%-%dt:~4,2%-%dt:~6,2%T%dt:~8,2%:%dt:~10,2%:%dt:~12,2%
#GOTO :EOF
:END
#pause

Setting a windows batch file variable to the day of the week

I have a windows batch file that runs daily. Wish to log data into a file and want to rotate it (i.e. having at most the last 7 days worth of data).
Looked into the commands DATE and DELIMS - Cannot figure out a solution.
Is there a simple solution to create a file name that contains the day of the week i.e. 0 for monday etc.
Or do I have to resort to some better shell script.
%DATE% is not your friend. Because the %DATE% environment variable (and the DATE command) returns the current date using the Windows short date format that is fully and endlessly customizable. One user may configure the system to return 07/06/2012 while another might choose Fri060712. Using %DATE% is a complete nightmare for a BAT programmer.
There are two possible approaches to solve this problem:
You may be tempted to temporarily change the short date format, by changing the locale settings in the registry value HKCU\Control Panel\International\sShortDate, to your recognizable format. Then access %DATE% to get the date in the format you want; and finally restore the format back to the original user format. Something like this
reg copy "HKCU\Control Panel\International" "HKCU\Control Panel\International-Temp" /f >nul
reg add "HKCU\Control Panel\International" /v sShortDate /d "ddd" /f >nul
set DOW=%DATE%
reg copy "HKCU\Control Panel\International-Temp" "HKCU\Control Panel\International" /f >nul
but this method has two problems:
it tampers with a global registry value for its local particular purpouses, so it may interfere with other processes or user tasks that at the very same time query the date in short date format, including itself if run simultaneously.
and it returns the three letter day of the week in the local language that may be different in different systems or different users.
use WMIC Win32_LocalTime, that returns the date in a convenient way to directly parse it with a FOR command.
FOR /F "skip=1" %%A IN ('WMIC Path Win32_LocalTime Get DayOfWeek' ) DO (
set DOW=%%A
)
this is the method I recommend.
few more ways:
1.Robocopy not available in XP but can be downloaded form with win 2003 resource tool kit .Also might depend on localization:
#echo off
setlocal
for /f "skip=8 tokens=2,3,4,5,6,7,8 delims=: " %%D in ('robocopy /l * \ \ /ns /nc /ndl /nfl /np /njh /XF * /XD *') do (
set "dow=%%D"
set "month=%%E"
set "day=%%F"
set "HH=%%G"
set "MM=%%H"
set "SS=%%I"
set "year=%%J"
)
echo Day of the week: %dow%
endlocal
2.MAKECAB - works on every windows machine (but creates a small temp file).Function provided by carlos:
#Echo Off
Call :GetDate.Init
Rem :GetDate.Init should be called one time in the code before call to :Getdate
Call :GetDate
Echo weekday:%weekday%
Goto :EOF
:GetDate.Init
Set /A "jan=1,feb=2,mar=3,apr=4,may=5,jun=6,jul=7,aug=8,sep=9,oct=10,nov=11,dec=12"
Set /A "mon=1,tue=2,wed=3,thu=4,fri=5,sat=6,sun=7"
(
Echo .Set InfHeader=""
Echo .Set InfSectionOrder=""
Echo .Set InfFooter="%%2"
Echo .Set InfFooter1=""
Echo .Set InfFooter2=""
Echo .Set InfFooter3=""
Echo .Set InfFooter4=""
Echo .Set Cabinet="OFF"
Echo .Set Compress="OFF"
Echo .Set DoNotCopyFiles="ON"
Echo .Set RptFileName="NUL"
) >"%Temp%\~foo.ddf"
Goto :Eof
:GetDate
Set "tf=%Temp%\~%random%"
Makecab /D InfFileName="%tf%" /F "%Temp%\~foo.ddf" >NUL
For /F "usebackq tokens=1-7 delims=: " %%a In ("%tf%") Do (
Set /A "year=%%g,month=%%b,day=1%%c-100,weekday=%%a"
Set /A "hour=1%%d-100,minute=1%%e-100,second=1%%f-100")
Del "%tf%" >NUL 2>&1
Goto :Eof
3.W32TM - uses command switches introduced in Vista so will not work on windows 2003/XP:
#echo off
setlocal
call :w32dow day_ow
echo %day_ow%
pause
exit /b 0
endlocal
:w32dow [RrnVar]
setlocal
rem :: prints the day of the week
rem :: works on Vista and above
rem :: getting ansi date ( days passed from 1st jan 1601 ) , timer server hour and current hour
FOR /F "tokens=4,5 delims=:( " %%D in ('w32tm /stripchart /computer:localhost /samples:1 /period:1 /dataonly /packetinfo^|find "Transmit Timestamp:" ') do (
set "ANSI_DATE=%%D"
set "TIMESERVER_HOURS=%%E"
)
set "LOCAL_HOURS=%TIME:~0,2%"
if "%TIMESERVER_HOURS:~0,1%0" EQU "00" set TIMESERVER_HOURS=%TIMESERVER_HOURS:~1,1%
if "%LOCAL_HOURS:~0,1%0" EQU "00" set LOCAL_HOURS=%LOCAL_HOURS:~1,1%
set /a OFFSET=TIMESERVER_HOURS-LOCAL_HOURS
rem :: day of the week will be the modulus of 7 of local ansi date +1
rem :: we need need +1 because Monday will be calculated as 0
rem :: 1st jan 1601 was Monday
rem :: if abs(offset)>12 we are in different days with the time server
IF %OFFSET%0 GTR 120 set /a DOW=(ANSI_DATE+1)%%7+1
IF %OFFSET%0 LSS -120 set /a DOW=(ANSI_DATE-1)%%7+1
IF %OFFSET%0 LEQ 120 IF %OFFSET%0 GEQ -120 set /a DOW=ANSI_DATE%%7+1
rem echo Day of the week: %DOW%
endlocal & if "%~1" neq "" (set "%~1=%DOW%") else echo %DOW%
4..bat/jscript hybrid (must be saved as .bat):
#if (#x)==(#y) #end /***** jscript comment ******
#echo off
for /f %%d in ('cscript //E:JScript //nologo "%~f0"') do echo %%d
exit /b 0
***** end comment *********/
WScript.Echo((new Date).getDay());
5..bat/vbscript hybrid (must be saved as .bat)
:sub echo(str) :end sub
echo off
'>nul 2>&1|| copy /Y %windir%\System32\doskey.exe '.exe >nul
'& echo/
'& for /f %%w in ('cscript /nologo /E:vbscript %~dpfn0') do echo day of the week %%w
'& echo/
'& del /q "'.exe" >nul 2>&1
'& exit /b
WScript.Echo Weekday(Date)
WScript.Quit
6.powershell can be downloaded from microsoft.Available by default in everything form win7 and above:
#echo off
setlocal
for /f %%d in ('"powershell (Get-Date).DayOfWeek.Value__"') do set dow=%%d
echo day of the week : %dow%
endlocal
7.WMIC already used as an answer but just want to have a full reference.And with cleared <CR>:
#echo off
setlocal
for /f "delims=" %%a in ('wmic path win32_localtime get dayofweek /format:list ') do for /f "delims=" %%d in ("%%a") do set %%d
echo day of the week : %dayofweek%
endlocal
9.Selfcompiled jscript.net (must be saved as .bat):
#if (#X)==(#Y) #end /****** silent line that start jscript comment ******
#echo off
::::::::::::::::::::::::::::::::::::
::: compile the script ::::
::::::::::::::::::::::::::::::::::::
setlocal
if exist "%~n0.exe" goto :skip_compilation
set "frm=%SystemRoot%\Microsoft.NET\Framework\"
:: searching the latest installed .net framework
for /f "tokens=* delims=" %%v in ('dir /b /s /a:d /o:-n "%SystemRoot%\Microsoft.NET\Framework\v*"') do (
if exist "%%v\jsc.exe" (
rem :: the javascript.net compiler
set "jsc=%%~dpsnfxv\jsc.exe"
goto :break_loop
)
)
echo jsc.exe not found && exit /b 0
:break_loop
call %jsc% /nologo /out:"%~n0.exe" "%~dpsfnx0"
::::::::::::::::::::::::::::::::::::
::: end of compilation ::::
::::::::::::::::::::::::::::::::::::
:skip_compilation
"%~n0.exe"
exit /b 0
****** end of jscript comment ******/
import System;
import System.IO;
var dt=DateTime.Now;
Console.WriteLine(dt.DayOfWeek);
#ECHO OFF
REM GET DAY OF WEEK VIA DATE TO JULIAN DAY NUMBER CONVERSION
REM ANTONIO PEREZ AYALA
REM GET MONTH, DAY, YEAR VALUES AND ELIMINATE LEFT ZEROS
FOR /F "TOKENS=1-3 DELIMS=/" %%A IN ("%DATE%") DO SET /A MM=10%%A %% 100, DD=10%%B %% 100, YY=%%C
REM CALCULATE JULIAN DAY NUMBER, THEN DAY OF WEEK
IF %MM% LSS 3 SET /A MM+=12, YY-=1
SET /A A=YY/100, B=A/4, C=2-A+B, E=36525*(YY+4716)/100, F=306*(MM+1)/10, JDN=C+DD+E+F-1524
SET /A DOW=(JDN+1)%%7
DOW is 0 for Sunday, 1 for Monday, etc.
I thought that my first answer gives the correct day of week as a number between 0 and 6. However, because you had not indicated why this answer does not give the result you want, I can only guess the reason.
The Batch file below create a log file each day with a digit in the name, 0=Sunday, 1=Monday, etc... The program assume that echo %date% show the date in MM/DD/YYYY format; if this is not the case, just change the position of mm and dd variables in the for command.
#echo off
for /F "tokens=1-3 delims=/" %%a in ("%date%") do set /A mm=10%%a %% 100, dd=10%%b %% 100, yy=%%c
if %mm% lss 3 set /A mm+=12, yy-=1
set /A a=yy/100, b=a/4, c=2-a+b, e=36525*(yy+4716)/100, f=306*(mm+1)/10, dow=(c+dd+e+f-1523)%%7
echo Today log data > Day-%dow%.txt
If this is not what you want, please indicate the problem so I can fix it.
EDIT: The version below get date parts independent of locale settings:
#echo off
for /F "skip=1 tokens=2-4 delims=(-/)" %%A in ('date ^< NUL') do (
for /F "tokens=1-3 delims=/" %%a in ("%date%") do (
set %%A=%%a
set %%B=%%b
set %%C=%%c
)
)
set /A mm=10%mm% %% 100, dd=10%dd% %% 100
if %mm% lss 3 set /A mm+=12, yy-=1
set /A a=yy/100, b=a/4, c=2-a+b, e=36525*(yy+4716)/100, f=306*(mm+1)/10,
dow=(c+dd+e+f-1523)%%7
echo Today log data > Day-%dow%.txt
EDIT: The version below insert day of week as 3-letter short name:
#echo off
for /F "skip=1 tokens=2-4 delims=(-/)" %%A in ('date ^< NUL') do (
for /F "tokens=1-3 delims=/" %%a in ("%date%") do (
set %%A=%%a
set %%B=%%b
set %%C=%%c
)
)
set /A mm=10%mm% %% 100, dd=10%dd% %% 100
if %mm% lss 3 set /A mm+=12, yy-=1
set /A a=yy/100, b=a/4, c=2-a+b, e=36525*(yy+4716)/100, f=306*(mm+1)/10,
dow=(c+dd+e+f-1523)%%7 + 1
for /F "tokens=%dow%" %%a in ("Sun Mon Tue Wed Thu Fri Sat") do set dow=%%a
echo Today log data > Day-%dow%.txt
Regards,
Antonio
This turned out way more complex then I first suspected, and I guess that's what intrigued me, I searched every where and all the methods given wouldnt work on Windows 7.
So I have an alternate solution which uses a Visual Basic Script.
The batch creates and executes the script(DayOfWeek.vbs), assigns the scripts output (Monday, Tuesday etc) to a variable (dow), the variable is then checked and another variable (dpwnum) assigned with the days number, afterwards the VBS is deleted hope it helps:
#echo off
REM Create VBS that will get day of week in same directory as batch
echo wscript.echo WeekdayName(Weekday(Date))>>DayOfWeek.vbs
REM Cycle through output to get day of week i.e monday,tuesday etc
for /f "delims=" %%a in ('cscript /nologo DayOfWeek.vbs') do #set dow=%%a
REM delete vbs
del DayOfWeek.vbs
REM Used for testing outputs days name
echo %dow%
REM Case of the days name is important must have a capital letter at start
REM Check days name and assign value depending
IF %dow%==Monday set downum=0
IF %dow%==Tuesday set downum=1
IF %dow%==Wednesday set downum=2
IF %dow%==Thursday set downum=3
IF %dow%==Friday set downum=4
IF %dow%==Saturday set downum=5
IF %dow%==Sunday set downum=6
REM print the days number 0-mon,1-tue ... 6-sun
echo %downum%
REM set a file name using day of week number
set myfile=%downum%.bak
echo %myfile%
pause
exit
EDIT:
Though I turned to VBS, It can be done in pure batch, took me a while to get it working and a lot of searching lol, but this seems to work:
#echo off
SETLOCAL enabledelayedexpansion
SET /a count=0
FOR /F "skip=1" %%D IN ('wmic path win32_localtime get dayofweek') DO (
if "!count!" GTR "0" GOTO next
set dow=%%D
SET /a count+=1
)
:next
echo %dow%
pause
The only caveat for you on the above batch is that its day of weeks are from 1-7 and not 0-6
This works for me
FOR /F "tokens=3" %%a in ('robocopy ^|find "Started"') DO SET TODAY=%%a
I am in the US. I can run this code in Windows 7, Windows 2008 R2, Windows Server 2003, Windows XP (All OS's are current with Windows Updates and patches). All with short date setting without ddd (or dddd) (day of week).
#echo off
for /f %%a in ('date /t') do set DAY=%%a
echo.
echo The Day Is: %DAY%
echo.
If today is Thursday, it would output "The Day Is: Thu".
This returns the day on all 4 Windows versions I have tested on. And only the day. When I changed my short date setup to be "ddd, M/d/yyyy", my output would show the day with a comma (e.g. Thu,) which tells me this code does use the short date format. But what also may be happening is that if the short date does not contain the day of week, it may look to the long date format which on all 4 machines I tested on, have dddd in the format.
This is not my work (well, I modified it slightly from the example), and it's late to the game, but this works on Server 2003 for me;
#echo off
set daysofweek=Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
for /F "skip=2 tokens=2-4 delims=," %%A in ('WMIC Path Win32_LocalTime Get DayOfWeek /Format:csv') do set daynumber=%%A
for /F "tokens=%daynumber% delims=," %%B in ("%daysofweek%") do set day=%%B
Citation: TechSupportForum
First - Copy CON SETUPDAY.001
SET WORKDAY=^Z (very important - no cr/lf)
DATE /T >SETUPDAY.002
COPY SETUPDAY.001+SETUPDAY.002 NEWDAY.BAT >nul
CALL NEWDAY.BAT
SET WEEKDAY=%WORKDAY:~0,3%
SET MDY=%WORKDAY:~4,10%
USE %WEEKDAY% IN YOUR SCRIPT
Locale-dependent version: In some environments, the following will extract the day name from the date:
set dayname=%date:~0,3%
It assumes that the day name is the first part of %date%. Depending on the machine settings, though, the substring part (~0,3) would need to change.
A statement such as this would dump to a file with a three character day name:
set logfile=%date:~0,3%.log
echo some stuff > %logfile%
Locale-independent version: If you need it less dependent on the current machine's day format, another way of doing it would be to write a tiny application that prints the day of the week. Then use the output of that program from the batch file. For example, the following C application prints dayN where N=0..6.
#include <stdio.h>
#include <time.h>
int main( int argc, char* argv[] )
{
time_t curtime;
struct tm * tmval;
time( &curtime );
tmval = localtime( &curtime );
// print dayN. Or use a switch statement and print
// the actual day name if you want
printf( "day%d", tmval->tm_wday );
}
If the above were compiled and linked as myday.exe, then you could use it from a batch file like this:
for /f %%d in ('myday.exe') do set logfile=%%d.log
echo some stuff > %logfile%
I have this solution working for me:
Create a file named dayOfWeek.vbs in the same dir where the cmd file will go.
dayOfWeek.vbs contains a single line:
wscript.stdout.write weekdayname(weekday(date))
or, if you want day number instead of name:
wscript.stdout.write weekday(date)
The cmd file will have this line:
For /F %%A In ('CScript dayOfWeek.vbs //NoLogo') Do Set dayName=%%A
Now you can use variable dayName like:
robocopy c:\inetpub \\DCStorage1\Share1\WebServer\InetPub_%dayName% /S /XD history logs
Another spin on this topic. The below script displays a few days around the current, with day-of-week prefix.
At the core is the standalone :dpack routine that encodes the date into a value whose modulo 7 reveals the day-of-week per ISO 8601 standards (Mon == 0). Also provided is :dunpk which is the inverse function:
#echo off& setlocal enabledelayedexpansion
rem 10/23/2018 daydate.bat: Most recent version at paulhoule.com/daydate
rem Example of date manipulation within a .BAT file.
rem This is accomplished by first packing the date into a single number.
rem This demo .bat displays dates surrounding the current date, prefixed
rem with the day-of-week.
set days=0Mon1Tue2Wed3Thu4Fri5Sat6Sun
call :dgetl y m d
call :dpack p %y% %m% %d%
for /l %%o in (-3,1,3) do (
set /a od=p+%%o
call :dunpk y m d !od!
set /a dow=od%%7
for %%d in (!dow!) do set day=!days:*%%d=!& set day=!day:~,3!
echo !day! !y! !m! !d!
)
exit /b
rem gets local date returning year month day as separate variables
rem in: %1 %2 %3=var names for returned year month day
:dgetl
setlocal& set "z="
for /f "skip=1" %%a in ('wmic os get localdatetime') do set z=!z!%%a
set /a y=%z:~0,4%, m=1%z:~4,2% %%100, d=1%z:~6,2% %%100
endlocal& set /a %1=%y%, %2=%m%, %3=%d%& exit /b
rem packs date (y,m,d) into count of days since 1/1/1 (0..n)
rem in: %1=return var name, %2= y (1..n), %3=m (1..12), %4=d (1..31)
rem out: set %1= days since 1/1/1 (modulo 7 is weekday, Mon= 0)
:dpack
setlocal enabledelayedexpansion
set mtb=xxx 0 31 59 90120151181212243273304334& set /a r=%3*3
set /a t=%2-(12-%3)/10, r=365*(%2-1)+%4+!mtb:~%r%,3!+t/4-(t/100-t/400)-1
endlocal& set %1=%r%& exit /b
rem inverse of date packer
rem in: %1 %2 %3=var names for returned year month day
rem %4= packed date (large decimal number, eg 736989)
:dunpk
setlocal& set /a y=%4+366, y+=y/146097*3+(y%%146097-60)/36524
set /a y+=y/1461*3+(y%%1461-60)/365, d=y%%366+1, y/=366
set e=31 60 91 121 152 182 213 244 274 305 335
set m=1& for %%x in (%e%) do if %d% gtr %%x set /a m+=1, d=%d%-%%x
endlocal& set /a %1=%y%, %2=%m%, %3=%d%& exit /b
If you can change format of short date in the PC to "ddd yyyy-MM-dd" (only first parameter 'ddd' is compulsory), then following command returns-
c:\>vol | date
The current date is: Mon 2014-12-01
Then you can write you batch file -
#echo off
vol | date | find /i "sun" > nul
if not errorlevel 1 goto SUN
vol | date | find /i "mon" > nul
if not errorlevel 1 goto MON
# write block for other week days
goto END
:SUN
set fname="sun"
goto BACKUP
:MON
set fname="mon"
goto BACKUP
# write block for other week days
:BACKUP
echo %fname%
:END
Rem Remove the end comma and add /A to set for this line worked for me.
set /A a=yy/100, b=a/4, c=2-a+b, e=36525*(yy+4716)/100, f=306*(mm+1)/10
Was looking to do this myself and saw complaints about blank lines:
rem Make the win32_localtime output all one line, though some versions may contain blank lines as well.
rem So ignore blank lines and just pick up the number after the equal sign.
for /f "delims== tokens=2" %%a in ('wmic path win32_localtime get dayofweek /format:list') do (
rem Increment the DOW as it is documented to be a zero-based index starting with Sunday.
set /a DayOfWeekIndex=%%a+1
)
rem Also get name day of week. The DOW coming in is now a one-based index.
rem This is used to reference the "array" of week day names.
set DayOfWeekNames=Sun Mon Tue Wed Thu Fri Sat
for /f "tokens=%DayOfWeekIndex%" %%b in ("%DayOfWeekNames%") do (
set DayOfWeekName=%%b
)
I Improved Aacini Answer
to make it Echo Full day of week Name
So here's my Code
#echo off
for /F "skip=1 tokens=2-4 delims=(-/)" %%A in ('date ^< NUL') do (
for /F "tokens=1-3 delims=/" %%a in ("%date%") do (
set %%A=%%a
set %%B=%%b
set %%C=%%c
)
)
set /A mm=10%mm% %% 100, dd=10%dd% %% 100
if %mm% lss 3 set /A mm+=12, yy-=1
set /A a=yy/100, b=a/4, c=4-a+b, e=36525*(yy+4716)/100, f=306*(mm+1)/10,dow=(c+dd+e+f-1523)%%7 + 1
for /F "tokens=%dow%" %%a in ("Sunday Monday Tuesday Wednesday Thursday Friday Saturday ") do set dow=%%a
echo Today is %dow%>"Today is %dow%.txt"
echo Today is %dow%
Pause>Nul
REM Sun Mon Tue Wed Thu Fri Sat
REM Sunday Monday Tuesday Wednesday Thursday Friday Saturday
I use Tiny C to write a weekday.exe and run with batch file.
for /f %% in ('weekday.exe') do set weekday=%%i
weekday.c:
#include <time.h>
#include <stdio.h>
int main(int argc, char** argv) {
time_t curtime;
struct tm * tmval;
time( &curtime );
tmval = localtime( &curtime );
if (tmval->tm_wday == 1) printf("Mon");
if (tmval->tm_wday == 2) printf("Tue");
if (tmval->tm_wday == 3) printf("Wed");
if (tmval->tm_wday == 4) printf("Thu");
if (tmval->tm_wday == 5) printf("Fri");
if (tmval->tm_wday == 6) printf("Sat");
if (tmval->tm_wday == 0) printf("Sun");
return 0;
}
A version using MSHTA and javascript. Change %jsfunc% to whateve jscript function you want to call
#echo off
::Invoke a javascript function using mhta
set jsfunc=new Date().getDay()
set dialog="about:<script>resizeTo(0,0);new ActiveXObject('Scripting.FileSystemObject').
set dialog=%dialog%GetStandardStream(1).WriteLine(%jsfunc%);close();</script>"
for /f "tokens=* delims=" %%p in ('mshta.exe %dialog%') do set ndow=%%p
::get dow string from array of strings
for /f "tokens=%ndow%" %%d in ("Mon Tue Wed Thu Fri Sat Sun") do set dow=%%d
echo dow is : %ndow% %dow%
pause

Resources