115

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
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Maksym Polshcha
  • 16,722
  • 8
  • 47
  • 73
  • 1
    possible duplicate of [windows batch script format date and time](http://stackoverflow.com/questions/1192476/windows-batch-script-format-date-and-time) – adarshr Jun 08 '12 at 08:49
  • 1
    http://www.robvanderwoude.com/datetime.php – Bali C Jun 08 '12 at 08:49
  • 1
    adarshr, the answer to that question uses a quite horrible and error-prone way of dealing with it. I'd advise not to use it. – Joey Jun 08 '12 at 09:03
  • This link is helpful to understand the answers below. http://ss64.com/nt/for_f.html – smwikipedia Jan 22 '16 at 03:10
  • 1
    [Split %date% in a batch file regardless of Regional Settings](http://stackoverflow.com/q/15378719/995714) – phuclv Aug 23 '16 at 16:22

17 Answers17

164

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%
Joey
  • 316,376
  • 76
  • 642
  • 652
  • One thing to note is that if you have a command prompt open while testing out this command, it will give you the time that you opened the command prompt (cmd.exe). So if you have a command prompt open for a while and keep getting the same time, close and then re-open the command prompt. If you're simply running a batch file from Windows Explorer, this won't be a problem. – user2023861 Aug 21 '13 at 13:39
  • 1
    @user2023861 It appears that even if I open a command prompt, I always get the correct date/time at the moment of invocation of the command, not when I had opened the command prompt. – ADTC Sep 16 '13 at 06:45
  • 5
    Note that if you run the above line multiple times you won't get a new date for each invocation, as it checks for the variable being undefined. This is needed because `for /f` returns two lines, the latter of which being an empty one. You can solve that by using `set MyDate=` in between. I guess that's what user2023861 stumbled over. – Joey Sep 16 '13 at 06:49
  • Oh yes, I was just `echo`ing the wmic output, so it's always a fresh new date/time on every invocation. I seem unable to put it in the MyDate variable without doing `if not defined MyDate` first. – ADTC Sep 16 '13 at 08:19
  • Man, the word needs to be spread about this method. Having a locale-independent timestamp makes parsing easier and makes the batch file more robust (although I guess robustness is not really what people expect in a Windows batch file...). – Charles Wood Oct 17 '13 at 16:34
  • 1
    @CharlesWood, at least I strive for robustness in my own batch files, although these days I often use PowerShell instead. – Joey Oct 17 '13 at 20:05
  • @Joey I know this is old, but is there a way to do this on a file to get the "Date Modified" in a similar format? Thanks. – Logan Dec 29 '15 at 00:17
  • 1
    Variables that will be set: `Year`, `Month`, `Day`, `Hour`, `Minute`, `Second`, `Quarter`, `WeekInMonth`, `DayOfWeek` – user Dec 29 '15 at 13:31
  • 1
    My god. I knew windows batch files were primitive but this is just ghastly. I found myself thinking about making a small batch file to automate creating audacity recording sessions named after the day, etc, but one look at the options of how to do it and I have decided to wait until I replace XP with Linux, hopefully in the new year. – Majenko Dec 08 '16 at 17:57
  • @Majenko: You could just as well use VBScript or PowerShell. There are plenty of things to script in on Windows. – Joey Dec 08 '16 at 21:54
  • Power shell on XP? And I'd rather eat my own feet than dabble in VirusBasicScript. – Majenko Dec 08 '16 at 22:52
  • 3
    `for /f %%x in ('wmic path win32_localtime get /format:list ^| findstr "="') do set %%x set today=%Year%-%Month%-%Day%` is invalid answer: it returns **one digit** month and day. How to get 2-digit left padded with zero month and day to date string ? – Andrus Jun 24 '19 at 09:15
  • Andrus: If you need two digit months and days, then use the first solution proposed in this answer (with the substrings): wmic os get localdatetime outputs something like the following: LocalDateTime \ 20190824121817.349000+600 (the backslash is a carriage return). You could use the first eight characters of the second line as-is if you want a date in the format YYYYMMDD (i.e. set today=%MyDate:~0,8%). – Daniel Scott Sep 09 '19 at 02:23
  • Hi it works, thanks. One small question. How to have two digits months? – user3761555 Sep 17 '19 at 18:54
  • I ran the first command, but got this message "%%x was unexpected at this time." How to solve this issue? – Sharuzzaman Ahmat Raslan Mar 28 '20 at 15:39
41

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.

richhallstoke
  • 1,371
  • 1
  • 15
  • 26
38

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%
mwfearnley
  • 2,377
  • 1
  • 27
  • 29
Anup Rav
  • 381
  • 3
  • 3
  • 3
    This is the closest answer to the asked question. A simple one-liner was all I needed, not a program. – DCookie Mar 10 '16 at 16:08
  • 4
    Agreed. Some of the answers here look almost like "Install MS SQL Server, connect with a SQL Client, and execute the command `SELECT CONVERT(VARCHAR(16), GETDATE(), 112)`". – isapir Oct 13 '17 at 20:38
  • 2
    The date-time in ISO-8601 format is `%date:~10,4%%date:~7,2%%date:~4,2%T%time:~0,2%%time:~3,2%%time:~6,2%` – isapir Oct 13 '17 at 20:56
  • 5
    The reason that the other responses look like a program is that this answer, although simple, will fail if your Windows regional settings are not configured in the way that this code expects (i.e. this code will not work on *every* Windows system) – Daniel Scott Sep 04 '19 at 23:53
21

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 (Is it possible to embed and execute VBScript within a batch file without using a temporary file?) 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.


Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
npocmaka
  • 51,748
  • 17
  • 123
  • 166
8

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.

aardvarkk
  • 13,147
  • 6
  • 58
  • 89
7

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
Mark
  • 2,234
  • 4
  • 22
  • 27
  • It's only a solution for some people, as this works only at some locations in the world, depending of your date/time format settings – jeb Sep 15 '15 at 09:32
6

Just use the %date% variable:

echo %date%
Tim Cooper
  • 144,163
  • 35
  • 302
  • 261
ProVi
  • 123
  • 1
  • 1
3

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
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Will
  • 39
  • 1
2

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
vlad_tepesch
  • 6,330
  • 1
  • 29
  • 67
user103004
  • 21
  • 2
  • 1
    Should mask be like this `FOR /F "tokens=*" %%a IN ('powershell get-date -format "{yyyy\-MM\-dd\THH\:mm\:ss}"') DO SET date=%%a` so use upper MM for month and backslash to escape literal characters. – Whome Oct 27 '16 at 07:06
2

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
Bhaskara Arani
  • 1,240
  • 1
  • 18
  • 40
2

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.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
CodeKid
  • 1,207
  • 15
  • 16
  • 4
    In what way is saying "Use python" an answer to the question? – Ross Presser Sep 15 '17 at 16:52
  • 4
    in the same way as using MAKECAB, ROBOCOPY, VBSCRIPT, POWERSHELL Logman and other suggestions here that you can call on the command line? – CodeKid Sep 17 '17 at 22:25
  • This can be simplified to `python -c "import datetime;print(datetime.date.today())"`, because the `__str__` method of the `date` class just calls `isoformat()`. – onewhaleid Aug 04 '20 at 04:06
  • It is quite different since Python is not a standard component of any Windows build. I can always call an arbitrary high level language runtime to get a fancy timestamp string to display but certainly it is not applicable to the majority of the environments. – devildelta Oct 06 '20 at 10:01
2

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%
datchung
  • 1,586
  • 17
  • 16
1

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

Ivellios
  • 78
  • 7
1

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
Chris
  • 51
  • 1
  • 2
    But where is your answer different or better than the other 16? And there are already enough hints, that this solution only works for your localization – jeb Dec 16 '19 at 12:21
0
echo %DATE:~10,4%%DATE:~7,2%%DATE:~4,2% 
Pang
  • 8,605
  • 144
  • 77
  • 113
0

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
吴新茂
  • 53
  • 1
  • 4
-2

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?

sken130
  • 153
  • 1
  • 6