I would like to have this run and show the previous month. When I try to subtract the month it makes the last day of the month field not appear.
@echo off
set FirstDay=01
set Month=%date:~4,2%
set Year=%date:~10,4%
if %Month%==01 set LastDay=31 & goto foundate
if %Month%==02 set LastDay=28 & goto foundate
if %Month%==03 set LastDay=31 & goto foundate
if %Month%==04 set LastDay=30 & goto foundate
if %Month%==05 set LastDay=31 & goto foundate
if %Month%==06 set LastDay=30 & goto foundate
if %Month%==07 set LastDay=31 & goto foundate
if %Month%==08 set LastDay=31 & goto foundate
if %Month%==09 set LastDay=30 & goto foundate
if %Month%==10 set LastDay=31 & goto foundate
if %Month%==11 set LastDay=30 & goto foundate
if %Month%==12 set LastDay=31 & goto foundate
:foundate
echo The year is: %Year%
echo The month is: %Month%
echo First day of this month is: %FirstDay%
echo Last day of this month is: %LastDay%
Dates are complicated to work with and easy to get wrong, and if you can avoid rolling your own, do so.
CMD does not come with a native date library, but the .NET System.DateTime
library is available via PowerShell. The following PS script shows how to use .NET to do what you're asking.
Get-LastMonthStats.ps1
$lastmonth = (Get-Date).addMonths(-1)
"The year is $($lastmonth.year)"
"The month is $($lastmonth.Month)"
"First day of this month is 01"
"Last day of this month is $([DateTime]::DaysInMonth($lastmonth.year, $lastmonth.month))"
Nearly all of this script is formatting the output. To run from CMD, launch this with the command
powershell.exe -ex bypass -f Get-LastMonthStats.ps1
Alternatively, you can put the whole script on one (very long) command line, if you don't want to create a separate .ps1
file.
powershell -c "$lastmonth = (Get-Date).addMonths(-1); 'The year is ' + $lastmonth.year; 'The month is ' + $lastmonth.Month; 'First day of this month is 01'; 'Last day of this month is ' + [DateTime]::DaysInMonth($lastmonth.year, $lastmonth.month)"
I made a function library that has these functions. Doing what you want with this library is easy, check below.
The functions are at the end of the code. Just copy to the end of your file (after a goto:eof) and call them using specified arguments.
The given code inside :main should do what you are asking for.
Remarks:
- Has inbuilt Leap Year check, so if the year is a Leap Year, Februrary will return 29 days.
- When copying functions to your file, please keep Author information
Code:
@echo off
:main
:: Recommended to use GetDateIntl function, to get region-independent results (Check functions at the end of this file)
call :GetDateIntl Year Month Day /A
echo/Using GetDateIntl to get current date: %Year%-%Month%-%day%
echo/
:: Call function to get last day of this month (Check functions at the end of this file)
call :GetLastDayOfMonth %Month% %Year% LastDay
echo This month is: %Month%/%Year%
echo First day of any month is always 1
echo Last day of this month is: %LastDay%
echo/
:: Get previous month number
set /A "PMonth= %Month% - 1"
set "PYear=%Year%"
:: Correct PMonth and PYear if this month is December
if %PMonth%==0 ( set "PMonth=12" & set /A "PYear= %PYear% - 1" )
:: Call function to get last day of previous month (Check function after :main)
call :GetLastDayOfMonth %PMonth% %PYear% PLastDay
echo Previous month is: %PMonth%/%PYear%
echo Last day of previous month is: %PLastDay%
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
::
:: By Cyberponk, v1.1 - 11/05/2016
:: v1.0 - 2015
::
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 "%'yy'%"=="" set 'yy'=%'aa'%
if %'yy'% LSS 100 set 'yy'=20%'yy'%
endlocal&set %1=%'yy'%&set %4 %2=%'mm'%&set %4 %3=%'dd'%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:IsLeapYear %year% IsLeap
:: Checks if a year is a Leap Year (year that has 366 days)
:: Arguments:
:: %year% = year number input. Can be a number or a variable containing a 4 digit number
:: IsLeap = result output containing 1 or 0 (1= is leap year, 0= not yeap lear)
::
:: By Cyberponk, v1.1 - 11/05/2016
::
SETLOCAL ENABLEEXTENSIONS
set /A "IsLeap=(!(%1 %% 4) & !!(%1 %% 100)) | !(%1 %% 400)"
endlocal & set %2=%IsLeap%& goto:EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:GetLastDayOfMonth %month% %year% LastDay
:: Gets the last day of a given month from a given year
:: Arguments:
:: %month% = month number input. Can be a number or a variable containing a number
:: %year% = year for reference (used to check for leap years)
:: LastDay = result output containing last day of the specified month
::
:: By Cyberponk, v1.0 - 11/05/2016
::
SETLOCAL ENABLEEXTENSIONS
:: Mathematical formula to last day of month
set /A "LastDay= 28 + (%1 + (%1/8)) %% 2 + 2 %% %1 + 2 * (1/%1)
:: Add 1 day if year is a Leap Year and month is February
call :IsLeapYear %2 IsLeap
if %LastDay%==28 set /A LastDay=%LastDay% + %IsLeap%
endlocal & set %3=%LastDay%& goto:EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
here's a piece of code that will get the previous month:
@echo off
for /f "" %%# in ('WMIC Path Win32_LocalTime Get month /format:value') do (
for /f %%Z in ("%%#") do set /a %%Z-1
)
if %month% equ 0 set month=12
echo %month%
Better use wmic to get the date parts because it's independent from the machine's date format unlike the %date%
variable.
EDIT (as requested in the comments) :
@echo off
setlocal disableDelayedExpansion
for /f "" %%# in ('"WMIC Path Win32_LocalTime Get month,year /format:value"') do (
for /f %%Z in ("%%#") do set "%%Z"
)
set /a month=month-1
if %month% equ 0 set month=12
rem echo %month% -- %year%
set /A "leap=!(year&3) + (!!(year%%100)-!!(year&15))"
if %leap% equ 0 (set "m2=29") else (set "m2=28")
setlocal enableDelayedExpansion
set m1=31
set m3=31
set m4=30
set m5=31
set m6=30
set m7=31
set m8=31
set m9=30
set m10=31
set m11=30
set m12=31
set premonLastDay=!m%month%!
endlocal & set premonLastDay=%premonLastDay%
if %month% equ 12 (
set /a year=year-1
)
echo %premonLastDay%-%month%-%year%
endlocal