Gregorian Calendar for Windows Command Prompt

Published on
13,090 Points
Last Modified:
If like me you are one who spends a lot of time working and scripting with cmd.exe, sometimes it is handy to be able to quickly view a calendar for a given month and year. This script will quickly do just that!  Save the code posted below to a .bat file called gcal.bat.  Then you will be able to view the current calendar (default) or specify a month and year, all with a simple command:

  gcal  [month]  [YYYY]


  gcal  July
  gcal  August 2012
  gcal  09 2012
  gcal  10/2012
  gcal  nov .  dec .  jan 2013

Notes:  This is a pure script solution - no additional third party tools or scripts are required.  (EDIT: I now use the wmic program that comes with the OS to get the default month and year in a regionally non-dependant manner, but I left the "pure script" version in for reference, and for use with older OS versions.  See the formatParams section.)

The script is divided into four sections.  The first section (formatParams) validates and formats the input parameters (if any).  For flexibility the script will take various month formats.  The years is always a number from 1-9999.

The second section (getDayList) simply builds a string of numbers to represent the days in the specified month, 1 - 28, 29, 30, or 31 as required.

The third section (getSTARTDOW) actually does the work - determining which day of the week is the first of the month specified.

The fourth section (displayCalendar) displays the calendar by pulling sub-strings from the data build in section 2 - one for each week of the month.

Finally, it should be noted that the Gregorian calendar was first adapted in 1582, and gained widespread acceptance in 1752.  Therefore, renderings of the Gregorian calendar prior to these dates are just projections.

Edit 2016-02-01 - added a feature to surround the current day in brackets when the current month is rendered. Also some minor bug fixes.

Now the script!

@echo off
 setlocal DISableDelayedExpansion

:REM      gcal.bat - Gregorian Calendar
:REM      written by:  Ralph L. Brown
:REM      syntax: gcal.bat [month] [YYYY] ...


 set params=%~1/%~2
 set params=%params:/= %
 set params=%params:-= %

 call :formatParams %params%  ||  exit/b 1
 call :getDayList
 call :getSTARTDOW
 call :displayCalendar

 set _p1=%~1
 if "%_p1%" == "%_p1:/=%" shift /1
 shift /1
 if not "%1"=="" goto :START

 exit/b 0


:formatParams - This section validates the month and year parameters (if supplied).

 set currentDate=%date:~10,4%%date:~4,2%%date:~7,2%
 set/a currentDate+=0 2>nul

 REM - if the above fails, then get these fields using a regionally independent method:
 if NOT "%currentDate%"=="%date:~10,4%%date:~4,2%%date:~7,2%"  for /f "delims= " %%C in ('wmic path Win32_LocalTime Get Day^,Month^,Year /Format:List 2^>nul ^| find "="') do @(set current%%C) 2>nul

 REM - but this way is generally faster...
 if not defined currentYear   set/a currentYear=%currentDate:~0,4%
 if not defined currentMonth  set/a currentMonth=%currentDate:~0,6% %% %currentDate:~0,4%00
 if not defined currentDay    set/a currentDay=%currentDate% %% %currentDate:~0,6%00

 set currentMonth=%decode%

 set/a calMonth=%~1 2>nul  ||  set calMonth=%~1
 if 0%calMonth% equ 0 set calMonth=%~1
 if "%calMonth%"==""  set calMonth=%currentMonth%
 if "%calMonth%"=="." set calMonth=%currentMonth%

 set calMonth=%decode%

 if not defined calMonth call :syntax Invalid month specified: "%~1"\n Valid range is 1-12, or month name (or abbreviation), or . for current month. || exit/b 1

 set calYear=%~2
 if "%calYear%"=="." set calYear=
 if defined calYear  set calYear=%calYear:X=#%
 if defined calYear  set/a calYear=%calYear% 2>nul
 if defined calYear  if NOT "%calYear%"=="%~2"  set calYear=INVALID
 for %%Y in (00,01,02,03,04,05,06,07,08,09) do if "%~2"=="%%Y" set calYear=%currentYear:~0,2%%%Y
 if NOT defined calYear set calYear=%currentYear%

 REM - Comment-out the next 2 lines if you want to render years 1 A.D. - 99 A.D.
 if %calYear% LSS    10 set calYear=%currentYear:~0,2%0%calYear%
 if %calYear% LSS   100 set calYear=%currentYear:~0,2%%calYear%

 if %calYear% LSS 10000 if %calYear% GEQ 0 exit/b 0

 call :syntax Invalid year specified: "%~2"\n Valid range is 100 - 9999, or . for current year.
 exit/b 1

:getDayList - This section creates the string of days for the specified month.
 set/a leapYear= !(%calYear% %% 4) - !(%calYear% %% 100) + !(%calYear% %% 400) 2>nul
 set dayList=++++++1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28
 if "%calMonth%"=="FEB"  if %leapYear% equ 1  set dayList=%dayList%  29
 if not "%calMonth%"=="FEB"  set dayList=%dayList%  29  30
 for %%M in (JAN,MAR,MAY,JUL,AUG,OCT,DEC) do if "%calMonth%"=="%%M"  set dayList=%dayList%  31
 set dayList=%dayList:+=     % 
 if %currentYear% equ %calYear%  if "%currentMonth%"=="%calMonth%"  call set dayList=%%dayList: %currentDay% =[%currentDay%]%%
 exit/b %errorlevel%

:getSTARTDOW - This section determines which day of the week falls on the 1st of the month (0 - 6 for Sun - Sat).
 set/a workYear=%calYear% %% 400 2>nul
 set/a DOWJAN1= ( ( ( %workYear% %% 28 ) + ( ( (%workYear%+3) %% 28) / 4 ) ) + (( 6 * ( 1 + ((%workYear%-1) / 100)) ) ) ) %% 7
 for %%M in (JAN,FEB) do if "%calMonth%"=="%%M"  set leapYear=0
 call :decode  "%calMonth%"  "JAN:0,FEB:3,MAR:3,APR:6,MAY:1,JUN:4,JUL:6,AUG:2,SEP:5,OCT:0,NOV:3,DEC:5"
 set/a STARTDOW= ( %DOWJAN1% + %decode% + %leapYear% ) %% 7
 exit/b %errorlevel%

:displayCalendar - This section displays the calendar.
 set calYear=    %calYear%||:This is to format the year for display.
@echo.          %calMonth%  %calYear:~-4%
@echo. Sun Mon Tue Wed Thu Fri Sat
 for /L %%W in (1,1,6) do  call :writeWeek %%W

 if %calYear% GTR 1752 exit/b %errorlevel%
@echo. NOTE: The Gregorian calendar was first adapted in 1582, but
@echo. only gained widespread acceptance in 1752.  The calendar
@echo. above is a projection of how the Gregorian calendar would 
@echo. have rendered had it been in use prior to September of 1752.
 exit/b %errorlevel%

:writeWeek - This section extracts the specified week from the dayList string.
 set/a _idx=%1*28-4*%STARTDOW%
 call set week=%%dayList:~%_idx%,28%%
 exit/b 0

:decode - This function extracts the matching key value from the supplied map.
 set key=%~1
 set csvmap=,%~2
 set ret=%~3
 if "%ret%"=="" set ret=decode
 call set key=%%csvmap:*,%key%:=%%
 set %ret%=%key:,=&:%||exit/b 1
 exit/b 0

 set msg=%*
@echo. %msg:\n=&@echo.%
@echo. Syntax:   %~nx0  [month] [YYYY] ...
@echo. Example:  %~nx0  July
@echo. Example:  %~nx0  August %currentYear%
@echo. Example:  %~nx0  09 %currentYear%
@echo. Example:  %~nx0  10/%currentYear%
 set/a currentYear+=1
@echo. Example:  %~nx0  nov . dec . jan %currentYear%
 exit/b 1

Open in new window

1 Comment

Expert Comment

by:Oleg Aney
Good script! I'll be using it in one of my powershell programmes.

Featured Post

Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

Join & Write a Comment

A query can call a function, and a function can call Excel, even though we are in Access. This is Part 2, and steps you through the VBA that "wraps" Excel functionality so we can use its worksheet functions in Access. The declaration statement de…
Please check the video also in regards to recovery of deleted emails from office 365 admin center and through the MFCMAPI tool. I have mentioned each and every step with the proper steps that need to be taken care of.

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month