This page will soon be removed, please
link to the new Batch Function Library.

[back]  
Date and Time Functions for NT4/2K/XP

Overview
Suggested Formats
References

Function Description
GetDate Returns the local system date
GetTime Returns the local system time
DateToMJD Returns a Modified Julian Date (MJD) from a date
MJDToDate Returns a date from a Modified Julian Day (MJD)
DateToDays Returns number of days elapsed since 1st January 1970 for a given calendar date
DaysToDate Returns a calendar date from the number of elapsed days since 1st January 1970
DateToMins Returns number of minutes elapsed since 1st January 1970 00:00 for a given calendar date and time of day
MinsToDate Returns a calendar date and time of day from the number of elapsed minutes since 1st January 1970 00:00
DateToSecs Returns number of seconds elapsed since 1st January 1970 00:00:00 for a given calendar date and time of day
SecsToDate Returns a calendar date and time of day from the number of elapsed seconds since 1st January 1970 00:00:00
DateToOrdinal Returns an ISO 8601 Ordinal date from a given calendar date
OrdinalToDate Returns a calendar date from an ISO 8601 Ordinal date
DateToWeek Returns an ISO 8601 Week date from a calendar date
WeekToDate Returns a calendar date from an ISO 8601 Week date
MonthName Returns the name of month from month number
MonthNumber Returns the number of the month from a month name
DayName Returns name of day of week from day of week number
DayNumber Returns the number of the day of week name
DateToDOW Returns the day of week number from a calendar date
Timer Returns the number of seconds elapsed since the function was last called and first called

Overview
The calendar date format returned by these functions will be a four digit year. The month and day of the month format will be two digits in the range 01 to 12 and 01 to 31 respectively (a leading zero is used for numbers less than 10). All returned times will be in a 24 hour format. Hours range from 00 to 23, minutes and seconds from 00 to 59 (a leading zero is used for numbers less than 10). These formats will be suitable for virtually all applications and make it simple to use ISO 8601 formatted dates. The leading zeros are easily removed if required.

If performing date arithmetic, you'll probably convert the date/time to a number. The functions that accept date and times will understand the following formats:- Years must be two or four digits, those in the range 70 to 99 will be treated as years from the twentieth century, years from 00 to 69, the twenty-first. Months must be in the range 1 or 01 to 12 and days of the month from 1 or 01 to 31.

Times may be 12 or 24 hour. For 12 hour times the hours must be in the range 1 or 01 to 12. The minutes MUST use two digits AND be immediately followed by 'a' or 'p' (eg 00a or 34p). For 24 hours times, the hours must be in the range 0 or 00 to 23 and the minutes MUST be two digits (eg 05 or 43). For both time formats, seconds must be in the range 0 or 00 to 59. The reason for accepting two digit years and 12 hour times is mainly for compatibilty with the output of the DIR command, which may use one or both of these formats.

Note: Any attempt to optimise the arithmetic used in these functions will probably cause the functions to fail under NT4 - as contrary to Microsoft's documentation, parantheses are not supported and arithmetic operator precedence is incorrect.

Suggested Formats
This is basically a very brief summary of the most commonly used date and time formats suggested by ISO 8601.

Component Basic Format Extended Format
Calendar Date YYYYMMDD Eg 19991231 YYYY-MM-DD Eg 1999-12-31
Time of day hhmmss Eg 235909 hh:mm:ss Eg 23:59:09
Date and Time YYYYMMDDThhmmss
Eg 19991231T235909
YYYY-MM-DDThh:mm:ss
Eg 1999-12-31T23:59:09
Ordinal Date YYYYDDD Eg 1999365 YYYY-DDD Eg 1999-365
Week Date YYYYWwwD Eg 1999W525 YYYY-Www-D Eg 1999-W52-5

References
Online date converters: HEASARC
Calendar studies and conversion algorithms: Hermetic
Summary of ISO 8601 Date and Time Standards
ISO 8601:2000 in PDF

GetDate

Use this function to reliably retrieve the current local system date components, year, month and day of month under NT4/2K/XP. To read how this function evolved, see the thread in alt.msdos.batch.nt titled "Formatting a date".

@echo off
call :GetDate year month day
echo/Today is: %year%-%month%-%day%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:GetDate yy mm dd
::
:: By:   Ritchie Lawrence, 2002-06-15. Version 1.0
::
:: Func: Loads local system date components into args 1 to 3. For NT4/2K/XP
::
:: Args: %1 var to receive year, 4 digits (by ref)
::       %2 var to receive month, 2 digits, 01 to 12 (by ref)
::       %3 Var to receive day of month, 2 digits, 01 to 31 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set t=2&if "%date%z" LSS "A" set t=1
for /f "skip=1 tokens=2-4 delims=(-)" %%a in ('echo/^|date') do (
  for /f "tokens=%t%-4 delims=.-/ " %%d in ('date/t') do (
    set %%a=%%d&set %%b=%%e&set %%c=%%f))
endlocal&set %1=%yy%&set %2=%mm%&set %3=%dd%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

GetTime

Use this function to reliably retrieve the local system time components, hours, minutes, seconds and centiseconds in 24 hour format under NT4/2K/XP.

@echo off
call :GetTime hours mins secs hsecs
echo/Time is: %hours%:%mins%:%secs%.%hsecs%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:GetTime hh nn ss tt
::
:: By:   Ritchie Lawrence, updated 2002-10-30. Version 1.2
::
:: Func: Loads local system time components into args 1 to 4. For NT4/2K/XP
::
:: Args: %1 Var to receive hours, 2 digits, 00 to 23 (by ref)
::       %2 Var to receive minutes, 2 digits, 00 to 59 (by ref)
::       %3 Var to receive seconds, 2 digits, 00 to 59 (by ref)
::       %4 Var to receive centiseconds, 2 digits, 00 to 99 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
for /f "tokens=5-8 delims=:. " %%a in ('echo/^|time') do (
  set hh=%%a&set nn=%%b&set ss=%%c&set cs=%%d)
if 1%hh% LSS 20 set hh=0%hh%
endlocal&set %1=%hh%&set %2=%nn%&set %3=%ss%&set %4=%cs%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DateToMJD

Use this function to return a Modified Julian Day (MJD) from a UTC date. May also be used in conjunction with the MJDToDate function to perform date arithmetic with a resolution of one day.

Note: For this function to return correct results, it must be supplied with a UTC time (as opposed to local time). However, if your goal is to obtain the number of elapsed days for the sake of performing date arithmetic in conjuction with the MJDToDate function, then local time will suffice.

@echo off
call :DateToMJD 1999 12 31 x
echo/The MJD for 1999-12-31 is: %x%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:DateToMJD %yy% %mm% %dd% MJD
::
:: By:   Ritchie Lawrence, 2002-06-15. Version 1.0
::
:: Func: Returns a Modified Julian Day (MJD) from a UTC date. Reference date
::       (day 0) is Wednesday 17th November 1858. For NT4/2K/XP
::
:: Args: %1 year component used to create MJD, 2 or 4 digits (by val)
::       %2 month component used to create MJD, leading zero ok (by val)
::       %3 day of month used to create MJD, leading zero ok (by val)
::       %4 var to receive MJD (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set yy=%1&set mm=%2&set dd=%3
if 1%yy% LSS 200 if 1%yy% LSS 170 (set yy=20%yy%) else (set yy=19%yy%)
set /a dd=100%dd%%%100,mm=100%mm%%%100
set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,j=153*m+2
set /a j=j/5+dd+y*365+y/4-y/100+y/400-2432046
endlocal&set %4=%j%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

MJDToDate

Use this function to return a UTC date from a Modified Julian Day (MJD). Use in conjunction with the DateToMJD function to perform date arithmetic with a resolution of one day. The created date will have a four digit year for typical dates, and two digit month and day.

@echo off
call :MJDToDate 55555 y m d
echo/MJD 55555 is %y%-%m%-%d% (Christmas day!)
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:MJDToDate %MJD% yy mm dd
::
:: By:   Ritchie Lawrence, 2002-06-15. Version 1.1
::
:: Func: Returns a UTC date from a Modified Julian Day (MJD). Reference
::       date (day 0) is Wednesday 17th November 1858. For NT4/2K/XP
::
:: Args: %1 MJD used to create calendar date (by val)
::       %2 var to receive year component, 4 digits (by ref)
::       %3 var to receive month component, 2 digits, 01-12 (by ref)
::       %4 var to receive day of month, 2 digits, 01-31 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set /a a=%1+2432045,b=4*a+3,b/=146097,c=-b*146097,c/=4,c+=a
set /a d=4*c+3,
d/=1461,e=-1461*d,e/=4,e+=c,m=5*e+2,m/=153,dd=153*m+2,dd/=5
set /a dd=-dd+e+1,mm=-m/10,mm*=12,mm+=m+3,yy=b*100+d-4800+m/10
(if %mm% LSS 10 set mm=0%mm%)&(if %dd% LSS 10 set dd=0%dd%)
endlocal&set %2=%yy%&set %3=%mm%&set %4=%dd%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DateToDays

Use this function to return the number of days elapsed since 1970-01-01 for a given calendar date. The year may be two or four digit (years 70 to 99 will be treated as 20th century, 00 to 69, the 21st century). Month and day of month may be one or two digits with a leading zero.

Use in conjunction with the DaysToDate function to perform date arithmetic with a resolution of one day. This function is virtually identical to the DateToMJD function except a different reference date has been used. This allows for interoperability with MinsToDays and SecsToDays which both share the same reference date.

@echo off
call :DateToDays %1 %2 %3 days
echo/%days%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:DateToDays %yy% %mm% %dd% days
::
:: By:   Ritchie Lawrence, 2002-09-26. Version 1.0
::
:: Func: Returns the number of days elapsed since 1st January 1970 for a
::       given date. For NT4/2K/XP
::
:: Args: %1 year component used to create days, 2 or 4 digits (by val)
::       %2 month component used to create days, leading zero ok (by val)
::       %3 date of month used to create days, leading zero ok (by val)
::       %4 var to receive number of elapsed days (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set yy=%1&set mm=%2&set dd=%3
if 1%yy% LSS 200 if 1%yy% LSS 170 (set yy=20%yy%) else (set yy=19%yy%)
set /a dd=100%dd%%%100,mm=100%mm%%%100
set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,j=153*m+2
set /a j=j/5+dd+y*365+y/4-y/100+y/400-2472633
endlocal&set %4=%j%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DaysToDate

Returns a calendar date from the number of days elapsed since 1970-01-01. The year will contain four digits for typical dates. The month and day of month will be made of two digits (using a leading zero where required).

@echo off
call :DaysToDate %1 yy mm dd
echo/%yy%-%mm%-%dd%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:DaysToDate %days% yy mm dd
::
:: By: Ritchie Lawrence, 2002-06-15. Version 1.1
::
:: Func: Returns a calendar date from the number of elapsed days since 1st
::      
January 1970. For NT4/2K/XP.
::
:: Args: %1 MJD used to create calendar date (by val)
::       %2 var to receive year component, 4 digits (by ref)
::       %3 var to receive month component, 2 digits, 01-12 (by ref)
::       %4 var to receive day of month component, 2 digits, 01-31 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set /a a=%1+2472632,b=4*a+3,b/=146097,c=-b*146097,c/=4,c+=a
set /a d=4*c+3,d/=1461,e=-1461*d,e/=4,e+=c,m=5*e+2,m/=153,dd=153*m+2,dd/=5
set /a dd=-dd+e+1,mm=-m/10,mm*=12,mm+=m+3,yy=b*100+d-4800+m/10
(if %mm% LSS 10 set mm=0%mm%)&(if %dd% LSS 10 set dd=0%dd%)
endlocal&set %2=%yy%&set %3=%mm%&set %4=%dd%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DateToMins

Use this function to return the number of minutes elapsed since 1st January 1970 00:00 for a given calendar date. The year may be two or four digit (years 70 to 99 will be treated as 20th century, 00 to 69, the 21st century). Month, day of month and hours may be one or two digits with a leading zero. Hours may be 12 hour (1 or 01 to 12) or 24 hour (0 or 00 to 23). If 12 hour format is used, minutes must be proceded by 'a' or 'p'. Minutes must be two digits with a leading zero where required, followed by 'a' or 'p' for 12 hour times.

Use in conjunction with the MinsToDate function to perform date arithmetic with a resolution of one minute.

Date range is from 1970-01-01 00:00 to 6053-01-23 02:07, which gives a range of 0 to 2147483647 or (2^31)-1 minutes.

@echo off
call :DateToMins %1 %2 %3 %4 %5 mins
echo/%mins%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:DateToMins %year% %month% %date% %hours% %minutes% result
::
:: By: Ritchie Lawrence, updated 2003-04-03. Version 1.1
::
:: Func: Returns the number of elapsed minutes since 1st January 1970 00:00
::       for a given date. For NT4/2K/XP
::
:: Args: %1 years to convert, 2 or 4 digit (by val)
::       %2 months to convert, 1/01 to 12, leading zero ok (by val)
::       %3 days to convert, 1/01 to 31, leading zero ok (by val)
::       %4 hours to convert, 1/01 to 12 for 12hr times (minutes must be
::          suffixed by 'a' or 'p', 0/00 to 23 for 24hr clock (by val)
::       %5 mins to convert, 00-59 only, suffixed by a/p if 12hr (by val)
::       %6 var to receive number of elapsed minutes (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set yy=%1&set mm=%2&set dd=%3&set hh=%4&set nn=%5
if 1%yy% LSS 200 if 1%yy% LSS 170 (set yy=20%yy%) else (set yy=19%yy%)
set /a dd=100%dd%%%100,mm=100%mm%%%100
set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,j=153*m+2
set /a j=j/5+dd+y*365+y/4-y/100+y/400-2472633
if 1%hh% LSS 20 set hh=0%hh%
if {%nn:~2,1%} EQU {p} if "%hh%" NEQ "12" set hh=1%hh%&set/a hh-=88
if {%nn:~2,1%} EQU {a} if "%hh%" EQU "12" set hh=00
if {%nn:~2,1%} GEQ {a} set nn=%nn:~0,2%
set /a hh=100%hh%%%100,nn=100%nn%%%100,j=j*1440+hh*60+nn
endlocal&set %6=%j%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

MinsToDate

Returns a calendar date and time of day from the number of elapsed minutes since 1st January 1970 00:00. The created calendar date will have a four digit year for typical dates and two digit month and day of month. All the time of day components will be two digits, padded with a leading zero where required.

Range is from 0 to 2147483647 or (2^31)-1 minutes, which gives a date range from 1970-01-01 00:00 to 6053-01-23 02:07.

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:MinsToDate %mins% yy mm dd hh nn
::
:: By: Ritchie Lawrence, updated 2003-07-13. Version 1.1
::
:: Func: Returns a calendar date and time of day from the number of
:: elapsed minutes since 1st January 1970 00:00. For NT4/2K/XP.
::
:: Args: %1 minutes used to create calendar date and time of day (by val)
:: %2 var to receive year, 4 digits for all typical dates (by ref)
:: %3 var to receive month, 2 digits, 01 to 12 (by ref)
:: %4 var to receive day of month, 2 digits, 01 to 31 (by ref)
:: %5 var to receive hours, 2 digits, 00 to 23 (by ref)
:: %6 var to receive minutes, 2 digits, 00 to 59 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set /a i=%1,nn=i%%60,i/=60,hh=i%%24,dd=i/24,i/=24
set /a a=i+2472632,b=4*a+3,b/=146097,c=-b*146097,c/=4,c+=a
set /a d=4*c+3,d/=1461,e=-1461*d,e/=4,e+=c,m=5*e+2,m/=153,dd=153*m+2,dd/=5
set /a dd=-dd+e+1,mm=-m/10,mm*=12,mm+=m+3,yy=b*100+d-4800+m/10
(if %mm% LSS 10 set mm=0%mm%)&(if %dd% LSS 10 set dd=0%dd%)
(if %hh% LSS 10 set hh=0%hh%)&(if %nn% LSS 10 set nn=0%nn%)
endlocal&set %6=%nn%&set %5=%hh%&set %4=%dd%&^
set %3=%mm%&set %2=%yy%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DateToSecs

Returns the number of elapsed seconds since 1st January 1970 00:00:00 for a given calendar date and time of day. The year may be two or four digit (years 70 to 99 will be treated as 20th century, 00 to 69, the 21st century). Month, day of month, hours and seconds may be one or two digits with a leading zero. Hours may be 12 hour (1 or 01 to 12) or 24 hour (0 or 00 to 23). If 12 hour format is used, minutes must be proceded by 'a' or 'p'. Minutes must be two digits with a leading zero where required, followed by 'a' or 'p' for 12 hour times.

Use in conjunction with the SecsToDate function to perform date arithmetic with a resolution of one second.

Date range is from 1970-01-01 00:00:00 to 2038-01-19 03:14:07 which gives a range of 0 to 2147483647 or (2^31)-1 seconds.

echo off&setlocal
call :DateToSecs %1 %2 %3 %4 %5 %6 secs
echo/Secs: %secs%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:DateToSecs %yy% %mm% %dd% %hh% %nn% %ss% secs
::
:: By:   Ritchie Lawrence, updated 2002-08-13. Version 1.1
::
:: Func: Returns number of seconds elapsed since 1st January 1970 00:00:00
::       for a given calendar date and time of day. For NT4/2K/XP.
::
:: Args: %1 year to convert, 2 or 4 digit (by val)
::       %2 month to convert, 1/01 to 12, leading zero ok (by val)
::       %3 day of month to convert, 1/01 to 31, leading zero ok (by val)
::       %4 hours to convert, 1/01 to 12 for 12hr times (minutes must be
::          suffixed by 'a' or 'p', 0/00 to 23 for 24hr clock (by val)
::       %5 mins to convert, 00-59 only, suffixed by a/p if 12hr (by val)
::       %6 secs to convert, 0-59 or 00-59 (by val)
::       %7 var to receive number of elapsed seconds (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set yy=%1&set mm=%2&set dd=%3&set hh=%4&set nn=%5&set ss=%6
if 1%yy% LSS 200 if 1%yy% LSS 170 (set yy=20%yy%) else (set yy=19%yy%)
set /a dd=100%dd%%%100,mm=100%mm%%%100
set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,j=153*m+2
set /a j=j/5+dd+y*365+y/4-y/100+y/400-2472633
if 1%hh% LSS 20 set hh=0%hh%
if {%nn:~2,1%} EQU {p} if "%hh%" NEQ "12" set hh=1%hh%&set/a hh-=88
if {%nn:~2,1%} EQU {a} if "%hh%" EQU "12" set hh=00
if {%nn:~2,1%} GEQ {a} set nn=%nn:~0,2%
set /a hh=100%hh%%%100,nn=100%nn%%%100,ss=100%ss%%%100
set /a j=j*86400+hh*3600+nn*60+ss
endlocal&set %7=%j%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

SecsToDate

Returns a calendar date from the number of elapsed seconds since 1st January 1970 00:00:00. Use in conjunction with the DateToSecs function to perform date arithmetic with a resolution of one second. The reference date (day 0), 1st January 1970 00:00:00 UTC, was chosen as it coincides with a number of values used in the Windows registry, eg Windows installation date. This script was posted to alt.msdos.batch.nt in reply to a post titled "Is there a way to find out the Operating system's date of installation on a computer?"

Range is from 0 to 2147483647 or (2^31)-1 seconds which gives a date range from 1970-01-01 00:00:00 to 2038-01-19 03:14:07.

@echo off&setlocal ENABLEEXTENSIONS
:: requires REG.EXE Version 2.0 or later
set key="HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
set val="InstallDate"

for /f "delims=" %%a in ('reg query %key% /v %Val%^|find %Val%') do (
  for %%b in (%%a) do set secs=%%b
)

call :SecsToDate %Secs% yy mm dd hh nn ss
echo/Windows installation date is: %yy%-%mm%-%dd% %hh%:%nn%:%ss%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:SecsToDate %secs% yy mm dd hh nn ss
::
:: By:   Ritchie Lawrence, updated 2002-07-24. Version 1.1
::
:: Func: Returns a calendar date and time of day from the number of
::       elapsed seconds since 1st January 1970 00:00:00. For NT4/2K/XP.
::
:: Args: %1 seconds used to create calendar date and time of day (by val)
::       %2 var to receive year, 4 digits for all typical dates (by ref)
::       %3 var to receive month, 2 digits, 01 to 12 (by ref)
::       %4 var to receive day of month, 2 digits, 01 to 31 (by ref)
::       %5 var to receive hours, 2 digits, 00 to 23 (by ref)
::       %6 var to receive minutes, 2 digits, 00 to 59 (by ref)
::       %7 var to receive seconds, 2 digits, 00 to 59 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set /a i=%1,ss=i%%60,i/=60,nn=i%%60,i/=60,hh=i%%24,dd=i/24,i/=24
set /a a=i+2472632,b=4*a+3,b/=146097,c=-b*146097,c/=4,c+=a
set /a d=4*c+3,d/=1461,e=-1461*d,e/=4,e+=c,m=5*e+2,m/=153,dd=153*m+2,dd/=5
set /a dd=-dd+e+1,mm=-m/10,mm*=12,mm+=m+3,yy=b*100+d-4800+m/10
(if %mm% LSS 10 set mm=0%mm%)&(if %dd% LSS 10 set dd=0%dd%)
(if %hh% LSS 10 set hh=0%hh%)&(if %nn% LSS 10 set nn=0%nn%)
if %ss% LSS 10 set ss=0%ss%
endlocal&set %7=%ss%&set %6=%nn%&set %5=%hh%&^
set %4=%dd%&set %3=%mm%&set %2=%yy%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DateToOrdinal

Returns an ordinal date from a given calendar date as described by ISO 8601.

@echo off&setlocal
if {%3}=={} echo/Usage: DateToOrdinal ^<YY^> ^<MM^> ^<DD^>&goto :EOF

call :DateToOrdinal %1 %2 %3 yy doy
echo/%yy%-%doy%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:DateToOrdinal %yy% %mm% %dd% year day
::
:: By: Ritchie Lawrence, updated 2002-11-22. Version 1.1
::
:: Func: Returns an ISO 8601 Ordinal date from a calendar date.
:: For NT4/2K/XP.
::
:: Args: %1 year component to be converted, 2 or 4 digits (by val)
::       %2 month component to be converted, leading zero ok (by val)
::       %3 day of month to be converted, leading zero ok (by val)
::       %4 var to receive year, 4 digits (by ref)
::       %5 var to receive day of year, 001 to 366 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set yy=%1&set mm=%2&set dd=%3
if 1%yy% LSS 200 if 1%yy% LSS 170 (set yy=20%yy%) else (set yy=19%yy%)
set /a dd=100%dd%%%100,mm=100%mm%%%100
set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,j=153*m+2
set /a j=j/5+dd+y*365+y/4-y/100+y/400-32045
set /a y=yy+4799,k=y*365+y/4-y/100+y/400-31738,o=j-k+1
if %o% LSS 100 set o=0%o%&if %o% LSS 10 set o=00%o%
endlocal&set %4=%yy%&set %5=%o%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

OrdinalToDate

Returns a calendar date from a ISO 8601 Ordinal date.

@echo off&setlocal
call :OrdinalToDate %1 %2 yy mm dd
echo/%yy%-%mm%-%dd%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:OrdinalToDate %year% %doy% yy mm dd
::
:: By:   Ritchie Lawrence, 2002-09-29. Version 1.0
::
:: Func: Returns a calendar date from an ISO 8601 Ordinal date.
::       For NT4/2K/XP.
::
:: Args: %1 year component to be converted, 4 digits (by val)
::       %2 day of year component to be converted, 001 to 366 (by val)
::       %3 var to receive year, 4 digits (by ref)
::       %4 var to receive month, 2 digits, 01 to 31 (by ref)
::       %5 var to receive day of month, 01 to 31 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
for /f "tokens=1-2" %%a in ('echo/%1 %2') do set /a yy=%%a,o=1%%b%%1000
set /a z=14-1,z/=12,y=yy+4800-z,m=1+12*z-3,j=153*m+2
set /a j=j/5+1+y*365+y/4-y/100+y/400-2432046,j+=o-1
set /a a=j+2432045,b=4*a+3,b/=146097,c=-b*146097,c/=4,c+=a
set /a d=4*c+3,d/=1461,e=-1461*d,e/=4,e+=c,m=5*e+2,m/=153,dd=153*m+2,dd/=5
set /a dd=-dd+e+1,mm=-m/10,mm*=12,mm+=m+3,yy=b*100+d-4800+m/10
(if %mm% LSS 10 set mm=0%mm%)&(if %dd% LSS 10 set dd=0%dd%)
endlocal&set %3=%yy%&set %4=%mm%&set %5=%dd%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DateToWeek

Returns an ISO 8601 Week date from a calendar date. A week date typically consists of three elements, a four digit year, a two digit calendar week (01 to 52 or 53) and a single digit day of week (1 to 7, where 1=Monday and 7=Sunday).

@echo off&setlocal
call :DateToWeek %1 %2 %3 yn cw dw
echo/%yn%-W%cw%-%dw%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:DateToWeek %yy% %mm% %dd% yy cw dw
::
:: By:   Ritchie Lawrence, Updated 2002-11-20. Version 1.1
::
:: Func: Returns an ISO 8601 Week date from a calendar date.
::       For NT4/2K/XP.
::
:: Args: %1 year component to be converted, 2 or 4 digits (by val)
::       %2 month component to be converted, leading zero ok (by val)
::       %3 day of month to be converted, leading zero ok (by val)
::       %4 var to receive year, 4 digits (by ref)
::       %5 var to receive calendar week, 2 digits, 01 to 53 (by ref)
::       %6 var to receive day of week, 1 digit, 1 to 7 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set yy=%1&set mm=%2&set dd=%3
if 1%yy% LSS 200 if 1%yy% LSS 170 (set yy=20%yy%) else (set yy=19%yy%)
set /a dd=100%dd%%%100,mm=100%mm%%%100
set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,Jd=153*m+2
set /a Jd=Jd/5+dd+y*365+y/4-y/100+y/400-32045
set /a y=yy+4798,Jp=y*365+y/4-y/100+y/400-31738,t=Jp+3,Jp=t-t%%7
set /a y=yy+4799,Jt=y*365+y/4-y/100+y/400-31738,t=Jt+3,Jt=t-t%%7
set /a y=yy+4800,Jn=y*365+y/4-y/100+y/400-31738,t=Jn+3,Jn=t-t%%7
set /a Jr=%Jp%,yn=yy-1,yn+=Jd/Jt,yn+=Jd/Jn
if %Jd% GEQ %Jn% (set /a Jr=%Jn%) else (if %Jd% GEQ %Jt% set /a Jr=%Jt%)
set /a diff=Jd-Jr,cw=diff/7+1,wd=diff%%7,wd+=1
if %cw% LSS 10 set cw=0%cw%
endlocal&set %4=%yn%&set %5=%cw%&set %6=%wd%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

WeekToDate

Returns a calendar date from an ISO 8601 Week date.

@echo off&setlocal
call :WeekToDate %1 %2 %3 yy mm dd
echo/%yy%-%mm%-%dd%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:WeekToDate %yn% %cw% %dw% yy mm dd
::
:: By:    Ritchie Lawrence, 2002-10-04. Version 1.0
::
:: Func: Returns a calendar date from an ISO 8601 Week date.
::       For NT4/2K/XP
::
:: Args: %1 year to convert, 2 or 4 digits (by val)
::       %2 calendar week to convert, 2 digits, 01 to 53 (by val)
::       %3 day of week to convert, 1 digit, 1 to 7 (by val)
::       %4 var to receive year, 4 digits (by ref)
::       %5 var to receive month, 2 digits, 01 to 12 (by ref)
::       %6 var to receive day of month, 2 digits, 01 to 31 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set yn=%1&set cw=%2&set dw=%3
if 1%yy% LSS 200 if 1%yy% LSS 170 (set yy=20%yy%) else (set yy=19%yy%)
set /a cw=100%cw%%%100,d=3210654
set /a z=14-1,z/=12,y=yn+4800-z,m=1+12*z-3,Jt=153*m+2
set /a Jt=Jt/5+1+y*365+y/4-y/100+y/400-32045,wt=Jt%%7
call set at=%%d:~%wt%,1%%&set /a Jt=at+Jt-3
set /a Jt=Jt+7*cw+dw-9,a=Jt+32045,b=4*a+3,b/=146097,c=-b*146097,c/=4,c+=a
set /a d=4*c+3,d/=1461,e=-1461*d,e/=4,e+=c,m=5*e+2,m/=153,dd=153*m+2,dd/=5
set /a dd=-dd+e+1,mm=-m/10,mm*=12,mm+=m+3,yy=b*100+d-4800+m/10
(if %mm% LSS 10 set mm=0%mm%)&(if %dd% LSS 10 set dd=0%dd%)
endlocal&set %4=%yy%&set %5=%mm%&set %6=%dd%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

MonthName

Returns the name of month from the month number. For example, if called with 4, the result is April.

@echo off&setlocal
call :MonthName %1 month
echo/%month%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:MonthName %mm% month
::
:: By:   Ritchie Lawrence, 2002-10-04. Version 1.0
::
:: Func: Returns the name of month from the number of the month.
::       For NT4/2K/XP
::
:: Args: %1 month number convert to name of month, 1 or 01 to 12 (by val)
::       %2 var to receive name of month (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS&set /a m=100%1%%100
for /f "tokens=%m%" %%a in ('echo/January February March April May June^
  July August September October November December'
) do endlocal&set %2=%%a&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

MonthNumber

Returns the number of the month from a month name. For example, if called with Apr, apr or April, the result is 4.

@echo off&setlocal
if "%1"=="" echo/Usage: MonthNumber ^<Monthname^>&goto :EOF
call :MonthNumber %1 mm
echo/%mm%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:MonthNumber %month% mm
::
:: By:   Ritchie Lawrence, 2003-05-14. Version 1.0
::
:: Func: Returns the number of month from name of month. Case insensitive
::       and only the first three letters are matched, result is 01 to
::       12 or NULL if no match. For NT4/2K/XP.
::
:: Args: %1 month name to convert to month number, 1 or 01 to 12 (by val)
:: %2 var to receive number of month (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS & set i=0
for %%a in (Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec) do (
  set /a i+=1 & echo/%1|findstr /i /b "%%a" >nul && call set mm=%%i%%
)
(if 1%mm% LSS 110 set mm=0%mm%) & endlocal&set %2=%mm%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DayName

Returns the name of the day of week from the day of week number. For example, if called with 3, the result is Wednesday.

@echo off&setlocal
call :DayName %1 day
echo/%day%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:DayName %d% day
::
:: By: Ritchie Lawrence, 2002-10-04. Version 1.0
::
:: Func: Returns the day of week from the day number, 1=Monday, 7=Sunday.
::       For NT4/2K/XP
::
:: Args: %1 day number to convert to name of day of week, 1 to 7 (by val)
::       %2 var to receive name of day of week (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
for /f "tokens=%1" %%a in ('echo/Monday Tuesday Wednesday Thursday Friday^
  Saturday Sunday') do endlocal&set %2=%%a&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DayNumber

Returns the number of the day of week from the day of week name. For example, if called with Wed, wed or Wednesday, the result is 3.

@echo off & setlocal
if "%1"=="" echo/Usage: DayNumber ^<Day of Week^>&goto :EOF

call :DayNumber %1 dow
echo/%dow%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:DayNumber %Weekday% dow
::
:: By: Ritchie Lawrence, 2003-05-14. Version 1.0
::
:: Func: Returns the day number from the name of weekday. Case insensitive
::       and only the first three letters are matched, result is 1 to 7 or
::       NULL if no match. For NT4/2K/XP.
::
:: Args: %1 Weekday name to convert to day of week number (by val)
::       %2 var to receive DOW number (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS & set i=0
for %%a in (Mon Tue Wed Thu Fri Sat Sun) do (
  set /a i+=1 & echo/%1|findstr /i /b "%%a" >nul && call set dow=%%i%%
)
endlocal&set %2=%dow%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DateToDOW

Returns the day of week number (1 to 7, where 1=Monday and 7=Sunday) for a given calendar date. Note the DateToWeek function also returns day of week (in addition to year and calendar month).

@echo off&setlocal
call :DateToDOW %1 %2 %3 dow
echo/%dow%
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:DateToDOW %yy% %mm% %dd% days
::
:: By:   Ritchie Lawrence, 2003-04-29. Version 1.1
::
:: Func: Creates a day of week number from a calendar date, where 1 = Mon
::       and 7 = Sun. For NT4/2K/XP.
::
:: Args: %1 year component to be converted, 2 or 4 digits (by val)
::       %2 month component to be converted, leading zero ok (by val)
::       %3 day of month to be converted, leading zero ok (by val)
::       %4 var to receive day of week number, 1 to 7 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set yy=%1&set mm=%2&set dd=%3
if 1%yy% LSS 200 if 1%yy% LSS 170 (set yy=20%yy%) else (set yy=19%yy%)
set /a dd=100%dd%%%100,mm=100%mm%%%100
set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,dow=153*m+2
set /a dow=dow/5+dd+y*365+y/4-y/100+y/400-2472630,dow%%=7,dow+=1
endlocal&set %4=%dow%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Timer

Returns the number of elapsed seconds since the function was last called and first called. Multiple timer and can used in parallel - just use a different variable name for each instance. See the function's header for more information.

@echo off&setlocal

set var=
call :Timer var
call :show

::wait about 3 seconds
ping 127.0.0.1 -n 4 >nul
call :Timer var
call :show

::wait about 7 seconds
ping 127.0.0.1 -n 8 >nul
call :Timer var
call :show

goto :EOF

:show
for /f "tokens=1-2 delims= " %%a in ('echo/%var%') do (
  echo/Seconds since last call: %%a, seconds since first call: %%b
)
goto :EOF

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Timer ID
::
:: By:   Ritchie Lawrence, 2002-10-10. Version 1.0
::
:: Func: Returns number of seconds elapsed since the function was last
::       called and first called. For NT4/2K/XP.
::
:: Args: %1 (by ref) The first time this function is called, this variable
::       is initialised to '<last> <first> <init>' where <first> and <last>
::       are zero and <init> is the number of elapsed seconds since
::       1970-01-01 00:00:00. This value is used by subsequent calls to
::       determine the elapsed number of seconds since the last call
::       (<last>) and the first call (<first>).
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS&call set ID=%%%1%%
set t=2&if "%date%z" LSS "A" set t=1
for /f "skip=1 tokens=2-4 delims=(-)" %%a in ('echo/^|date') do (
  for /f "tokens=%t%-4 delims=.-/ " %%d in ('date/t') do (
    set %%a=%%d&set %%b=%%e&set %%c=%%f))
for /f "tokens=5-7 delims=:. " %%a in ('echo/^|time') do (
  set hh=%%a&set nn=%%b&set ss=%%c)
set /a dd=100%dd%%%100,mm=100%mm%%%100
set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,j=153*m+2
set /a j=j/5+dd+y*365+y/4-y/100+y/400-2472633
set /a hh=100%hh%%%100,nn=100%nn%%%100,ss=100%ss%%%100
set /a j=j*86400+hh*3600+nn*60+ss
for /f "tokens=1-3 delims= " %%a in ('echo/%ID%') do (
  set l=%%a&set f=%%b&set c=%%c)
if {%c%}=={} endlocal&set %1=0 0 %j%&goto :EOF
set /a l=j-c-l,f+=l
endlocal&set %1=%l% %f% %c%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::