Windows batch: formatted date into variable

WindowsBatch File

Windows Problem Overview


How do I save the current date in YYYY-MM-DD format into some variable in a Windows .bat file?

Unix shell analogue:

today=`date +%F`
echo $today

Windows Solutions


Solution 1 - Windows

You can get the current date in a locale-agnostic way using

for /f "skip=1" %%x in ('wmic os get localdatetime') do if not defined MyDate set MyDate=%%x

Then you can extract the individual parts using substrings:

set today=%MyDate:~0,4%-%MyDate:~4,2%-%MyDate:~6,2%

Another way, where you get variables that contain the individual parts, would be:

for /f %%x in ('wmic path win32_localtime get /format:list ^| findstr "="') do set %%x
set today=%Year%-%Month%-%Day%

Much nicer than fiddling with substrings, at the expense of polluting your variable namespace.

If you need UTC instead of local time, the command is more or less the same:

for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr "="') do set %%x
set today=%Year%-%Month%-%Day%

Solution 2 - Windows

Use date /T to find the format on command prompt.

If the date format is Thu 17/03/2016 use like this:

set datestr=%date:~10,4%-%date:~7,2%-%date:~4,2%
echo %datestr%

Solution 3 - Windows

If you wish to achieve this using standard MS-DOS commands in a batch file then you could use:

FOR /F "TOKENS=1 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET dd=%%A
FOR /F "TOKENS=1,2 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET mm=%%B
FOR /F "TOKENS=1,2,3 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET yyyy=%%C

I'm sure this can be improved upon further but this gives the date into 3 variables for Day (dd), Month (mm) and Year (yyyy). You can then use these later in your batch script as required.

SET todaysdate=%yyyy%%mm%%dd%
echo %dd%
echo %mm%
echo %yyyy%
echo %todaysdate%

While I understand an answer has been accepted for this question this alternative method may be appreciated by many looking to achieve this without using the WMI console, so I hope it adds some value to this question.

Solution 4 - Windows

Two more ways that do not depend on the time settings (both taken from How get data/time independent from localization). And both also get the day of the week and none of them requires admin permissions!:

  1. MAKECAB - will work on EVERY Windows system (fast, but creates a small temporary file) (the foxidrive script):

     @echo off
     pushd "%temp%"
     makecab /D RptFileName=~.rpt /D InfFileName=~.inf /f nul >nul
     for /f "tokens=3-7" %%a in ('find /i "makecab"^<~.rpt') do (
         set "current-date=%%e-%%b-%%c"
         set "current-time=%%d"
         set "weekday=%%a"
     )
     del ~.*
     popd
     echo %weekday% %current-date% %current-time%
     pause
    
  2. ROBOCOPY - it's not a native command for Windows XP and Windows Server 2003, but it can be downloaded from the Microsoft site. But it is built-in in everything from Windows Vista and above:

     @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%
     echo Day of the month : %day%
     echo Month : %month%
     echo hour : %HH%
     echo minutes : %MM%
     echo seconds : %SS%
     echo year : %year%
     endlocal
    

    And three more ways that uses other Windows script languages. They will give you more flexibility e.g. you can get week of the year, time in milliseconds and so on.

  3. JScript/BATCH hybrid (need to be saved as .bat). JScript is available on every system from Windows NT and above, as a part of Windows Script Host (though can be disabled through the registry it's a rare case):

     @if (@X)==(@Y) @end /* ---Harmless hybrid line that begins a JScript comment
    
     @echo off
     cscript //E:JScript //nologo "%~f0"
     exit /b 0
     *------------------------------------------------------------------------------*/
    
     function GetCurrentDate() {
         // Today date time which will used to set as default date.
         var todayDate = new Date();
         todayDate = todayDate.getFullYear() + "-" +
                        ("0" + (todayDate.getMonth() + 1)).slice(-2) + "-" +
                        ("0" + todayDate.getDate()).slice(-2) + " " + ("0" + todayDate.getHours()).slice(-2) + ":" +
                        ("0" + todayDate.getMinutes()).slice(-2);
    
         return todayDate;
     }
    
     WScript.Echo(GetCurrentDate());
    
  4. VBScript/BATCH hybrid (https://stackoverflow.com/questions/9074476/is-it-possible-to-embed-and-execute-vbscript-within-a-batch-file-without-using-a) same case as jscript , but hybridization is not so perfect:

     :sub echo(str) :end sub
     echo off
     '>nul 2>&1|| copy /Y %windir%\System32\doskey.exe %windir%\System32\'.exe >nul
     '& echo current date:
     '& cscript /nologo /E:vbscript "%~f0"
     '& exit /b
    
     '0 = vbGeneralDate - Default. Returns date: mm/dd/yy and time if specified: hh:mm:ss PM/AM.
     '1 = vbLongDate - Returns date: weekday, monthname, year
     '2 = vbShortDate - Returns date: mm/dd/yy
     '3 = vbLongTime - Returns time: hh:mm:ss PM/AM
     '4 = vbShortTime - Return time: hh:mm
    
     WScript.echo  Replace(FormatDateTime(Date, 1), ", ", "-")
    
  5. PowerShell - can be installed on every machine that has .NET - download from Microsoft (v1, v2, and v3 (only for Windows 7 and above)). Installed by default on everything form Windows 7/Win2008 and above:

     C:\> powershell get-date -format "{dd-MMM-yyyy HH:mm}"
    
  6. Self-compiled jscript.net/batch (I have never seen a Windows machine without .NET so I think this is a pretty portable):

     @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.ToString("yyyy-MM-dd hh:mm:ss"));
    
  7. Logman This cannot get the year and day of the week. It's comparatively slow, also creates a temp file and is based on the time stamps that logman puts on its log files.Will work everything from Windows XP and above. It probably will be never used by anybody - including me - but it is one more way...

     @echo off
     setlocal
     del /q /f %temp%\timestampfile_*
    
     Logman.exe stop ts-CPU 1>nul 2>&1
     Logman.exe delete ts-CPU 1>nul 2>&1
    
     Logman.exe create counter ts-CPU  -sc 2 -v mmddhhmm -max 250 -c "\Processor(_Total)\%% Processor Time" -o %temp%\timestampfile_ >nul
     Logman.exe start ts-CPU 1>nul 2>&1
    
     Logman.exe stop ts-CPU >nul 2>&1
     Logman.exe delete ts-CPU >nul 2>&1
     for /f "tokens=2 delims=_." %%t in  ('dir /b %temp%\timestampfile_*^&del /q/f %temp%\timestampfile_*') do set timestamp=%%t
    
     echo %timestamp%
     echo MM: %timestamp:~0,2%
     echo dd: %timestamp:~2,2%
     echo hh: %timestamp:~4,2%
     echo mm: %timestamp:~6,2%
    
     endlocal
     exit /b 0
    

More information about the Get-Date function.


Solution 5 - Windows

As per answer by @ProVi just change to suit the formatting you require

echo %DATE:~10,4%-%DATE:~7,2%-%DATE:~4,2% %TIME:~0,2%:%TIME:~3,2%:%TIME:~6,2%

will return

yyyy-MM-dd hh:mm:ss
2015-09-15 18:36:11

EDIT As per @Jeb comment, whom is correct the above time format will only work if your DATE /T command returns

ddd dd/mm/yyyy
Thu 17/09/2015

It is easy to edit to suit your locale however, by using the indexing of each character in the string returned by the relevant %DATE% environment variable you can extract the parts of the string you need.

eg. Using %DATE~10,4% would expand the DATE environment variable, and then use only the 4 characters that begin at the 11th (offset 10) character of the expanded result

For example if using US styled dates then the following applies

ddd mm/dd/yyyy
Thu 09/17/2015

echo %DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2% %TIME:~0,2%:%TIME:~3,2%:%TIME:~6,2%
2015-09-17 18:36:11

Solution 6 - Windows

I really liked Joey's method, but I thought I'd expand upon it a bit.

In this approach, you can run the code multiple times and not worry about the old date value "sticking around" because it's already defined.

Each time you run this batch file, it will output an ISO 8601 compatible combined date and time representation.

FOR /F "skip=1" %%D IN ('WMIC OS GET LocalDateTime') DO (SET LIDATE=%%D & GOTO :GOT_LIDATE)
:GOT_LIDATE
SET DATETIME=%LIDATE:~0,4%-%LIDATE:~4,2%-%LIDATE:~6,2%T%LIDATE:~8,2%:%LIDATE:~10,2%:%LIDATE:~12,2%
ECHO %DATETIME%

In this version, you'll have to be careful not to copy/paste the same code to multiple places in the file because that would cause duplicate labels. You could either have a separate label for each copy, or just put this code into its own batch file and call it from your source file wherever necessary.

Solution 7 - Windows

Just use the %date% variable:

echo %date%

Solution 8 - Windows

I set an environment variable to the value in the numeric format desired by doing this:

FOR /F "tokens=1,2,3,4 delims=/ " %a IN ('echo %date%') DO set DateRun=%d-%b-%c

Solution 9 - Windows

Check this one..

for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%" & set "MS=%dt:~15,3%"
set "datestamp=%YYYY%%MM%%DD%" & set "timestamp=%HH%%Min%%Sec%" & set "fullstamp=%YYYY%-%MM%-%DD%_%HH%-%Min%-%Sec%-%MS%"
echo datestamp: "%datestamp%"
echo timestamp: "%timestamp%"
echo fullstamp: "%fullstamp%"
pause

Solution 10 - Windows

This is an extension of Joey's answer to include the time and pad the parts with 0's.

For example, the result will be 2019-06-01_17-25-36. Also note that this is the UTC time.

  for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr "="') do set %%x
  
  set Month=0%Month%
  set Month=%Month:~-2%
  set Day=0%Day%
  set Day=%Day:~-2%
  set Hour=0%Hour%
  set Hour=%Hour:~-2%
  set Minute=0%Minute%
  set Minute=%Minute:~-2%
  set Second=0%Second%
  set Second=%Second:~-2%

  set TimeStamp=%Year%-%Month%-%Day%_%Hour%-%Minute%-%Second%

Solution 11 - Windows

It is possible to use PowerShell and redirect its output to an environment variable by using a loop.

From the command line (cmd):

for /f "tokens=*" %a in ('powershell get-date -format "{yyyy-MM-dd+HH:mm}"') do set td=%a

echo %td%
2016-25-02+17:25

In a batch file you might escape %a as %%a:

for /f "tokens=*" %%a in ('powershell get-date -format "{yyyy-MM-dd+HH:mm}"') do set td=%%a

Solution 12 - Windows

If you have Python installed, you can do

python -c "import datetime;print(datetime.date.today().strftime('%Y-%m-%d'))"

You can easily adapt the format string to your needs.

Solution 13 - Windows

Due to date and time format is location specific info, retrieving them from %date% and %time% variables will need extra effort to parse the string with format transform into consideration. A good idea is to use some API to retrieve the data structure and parse as you wish. WMIC is a good choice. Below example use Win32_LocalTime. You can also use Win32_CurrentTime or Win32_UTCTime.

@echo off  
SETLOCAL ENABLEDELAYEDEXPANSION  
for /f %%x in ('wmic path Win32_LocalTime get /format:list ^| findstr "="') do set %%x  
set yyyy=0000%Year%  
set mmmm=0000%Month%  
set dd=00%Day%  
set hh=00%Hour%  
set mm=00%Minute%  
set ss=00%Second%  
set ts=!yyyy:~-4!-!mmmm:~-2!-!dd:~-2!_!hh:~-2!:!mm:~-2!:!ss:~-2!  
echo %ts%  
ENDLOCAL  

Result:
2018-04-25_10:03:11

Solution 14 - Windows

I am using the following:

set iso_date=%date:~6,4%-%date:~3,2%-%date:~0,2%

Or in combination with a logfile name 'MyLogFileName':

set log_file=%date:~6,4%-%date:~3,2%-%date:~0,2%-MyLogFileName

Solution 15 - Windows

echo %DATE:~10,4%%DATE:~7,2%%DATE:~4,2% 

Solution 16 - Windows

If powershell is available, you can use codes below:

# get date
$BuildDate=(get-date -format "yyMMdd")
echo BuildDate=$BuildDate

# get time
$BuildTime=(get-date -format "hhmmss")
echo BuildTime=$BuildTime

Here is the result:

BuildDate=200518
BuildTime=115919

Solution 17 - Windows

If you don't mind an one-time investment of 10 to 30 minutes to get a reliable solution (that doesn't depend on Windows' region settings), please read on.

Let's free our minds. Do you want to simplify the scripts to just look like this? (Assume you wants to set the LOG_DATETIME variable)

FOR /F "tokens=* USEBACKQ" %%F IN (`FormatNow "yyyy-MM-dd"`) DO (
  Set LOG_DATETIME=%%F
)

echo I am going to write log to Testing_%LOG_DATETIME%.log

You can. Simply build a FormatNow.exe with C# .NET and add it to your PATH.

Notes:

  1. You can use any Visual Studio edition, such as Visual Studio Express, to build the FormatNow.exe.
  2. In Visual Studio, choose the "Console Application" C# project, not "Windows Forms Application" project.
  3. Common sense: the built FormatNow.exe will need .NET Framework to run.
  4. Common sense: after adding FormatNow.exe to PATH variable, you need to restart CMD to take effect. It also applies to any change in environment variables.

Benefits:

  1. It's not slow (finishes within 0.2 seconds).
  2. Many formats are supported https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx e.g. FormatNow "ddd" to get only the day of week, FormatNow "yyyy" to get only the year
  3. It doesn't depend on Windows' region settings, so its output is much more reliable. On the other hand, %date% doesn't give a consistent format over different computers, and is not reliable.
  4. You don't need to create so many CMD variables and pollute the variable namespace.
  5. It would require 3 lines in the batch script to invoke the program and get the results. It should be reasonably short enough.

Source code of FormatNow.exe which I built with Visual Studio 2010 (I prefer to build it myself to avoid the risk of downloading an unknown, possibly malicious program). Just copy and paste the codes below, build the program once, and then you have a reliable date formatter for all future uses.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace FormatNow
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                if (args.Length < 1)
                {
                    throw new ArgumentException("Missing format");
                }
                string format = args[0];
                Console.Write(DateTime.Now.ToString(format, CultureInfo.InvariantCulture.DateTimeFormat));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

    }
}

In general, when dealing with complicated logics, we can make it simpler for by building a very small program and calling the program to capture the output back to a batch script variable instead. We are not students and we're not taking exams requiring us to follow the batch-script-only rule to solve problems. In real working environment, any (legal) method is allowed. Why should we still stick to the poor capabilities of Windows batch script that needs workarounds for many simple tasks? Why should we use the wrong tool for the job?

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMaksym PolshchaView Question on Stackoverflow
Solution 1 - WindowsJoeyView Answer on Stackoverflow
Solution 2 - WindowsAnup RavView Answer on Stackoverflow
Solution 3 - WindowsrichhallstokeView Answer on Stackoverflow
Solution 4 - WindowsnpocmakaView Answer on Stackoverflow
Solution 5 - WindowsMarkView Answer on Stackoverflow
Solution 6 - WindowsaardvarkkView Answer on Stackoverflow
Solution 7 - WindowsProViView Answer on Stackoverflow
Solution 8 - WindowsWillView Answer on Stackoverflow
Solution 9 - WindowsBhaskara AraniView Answer on Stackoverflow
Solution 10 - WindowsdatchungView Answer on Stackoverflow
Solution 11 - Windowsuser103004View Answer on Stackoverflow
Solution 12 - WindowsMathKidView Answer on Stackoverflow
Solution 13 - WindowsIvelliosView Answer on Stackoverflow
Solution 14 - WindowsChrisView Answer on Stackoverflow
Solution 15 - WindowsHillmee BobView Answer on Stackoverflow
Solution 16 - Windows吴新茂View Answer on Stackoverflow
Solution 17 - Windowssken130View Answer on Stackoverflow