如何在Windows命令行中以适当的格式获取当前日期/时间以用于文件/文件夹名称?

633

更新:既然现在是2016年,我会使用PowerShell来代替这个方法,除非有令人信服的向后兼容的原因,尤其是由于使用date时存在区域设置问题。请参见@npocmaka的https://dev59.com/sXVC5IYBdhLWcg3wtzqs#19799236


有什么Windows命令行语句可以让我以可放入文件名的格式获取当前日期和时间?

我想要一个.bat文件将目录压缩成一个归档文件,并用当前日期和时间作为名称的一部分, 例如:Code_2008-10-14_2257.zip。有没有简单的方法可以做到这一点,而不受机器区域设置的影响?

我并不介意日期格式,理想情况下应该是yyyy-mm-dd,但任何简单的格式都可以。

到目前为止,我已经得到了这个结果,在我的机器上它给了我Tue_10_14_2008_230050_91:

rem Get the datetime in a format that can go in a filename.
set _my_datetime=%date%_%time%
set _my_datetime=%_my_datetime: =_%
set _my_datetime=%_my_datetime::=%
set _my_datetime=%_my_datetime:/=_%
set _my_datetime=%_my_datetime:.=_%

rem Now use the timestamp by in a new ZIP file name.
"d:\Program Files\7-Zip\7z.exe" a -r Code_%_my_datetime%.zip Code

我能接受这样,但这看起来有些笨拙。理想情况下,它应该更加简洁,并且符合前面提到的格式。

我正在使用Windows Server 2003和Windows XP Professional。我不想安装其他工具来实现这一点(尽管我意识到有些工具可以进行美好的日期格式化)。


34
使用PowerShell,人们可以使用以下命令获取当前日期并以指定格式输出:[datetime]::now.tostring("yyyy-MM-dd") - Nacht
30个回答

741

请查看 Windows批处理文件(.bat)以获取当前日期的MMDDYYYY格式:

@echo off
For /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c-%%a-%%b)
For /f "tokens=1-2 delims=/:" %%a in ('time /t') do (set mytime=%%a%%b)
echo %mydate%_%mytime%

如果你喜欢使用24小时/军事时间格式,你可以用以下代码替换第二个FOR行:
For /f "tokens=1-2 delims=/:" %%a in ("%TIME%") do (set mytime=%%a%%b)

C:> .\date.bat
2008-10-14_0642

如果您想独立于地区的日期/月份顺序获取日期,可以使用"WMIC os GET LocalDateTime"作为源,因为它是按照ISO顺序排列的:

@echo off
for /F "usebackq tokens=1,2 delims==" %%i in (`wmic os get LocalDateTime /VALUE 2^>NUL`) do if '.%%i.'=='.LocalDateTime.' set ldt=%%j
set ldt=%ldt:~0,4%-%ldt:~4,2%-%ldt:~6,2% %ldt:~8,2%:%ldt:~10,2%:%ldt:~12,6%
echo Local date is [%ldt%]

C:>test.cmd
本地日期为[2012-06-19 10:23:47.048]


52
针对英国读者,你需要使用以下命令:For /f "tokens=1-3 delims=/ " %%a in ('date /t') do (set mydate=%%c-%%b-%%a),作为第二行代码。 - Rory
23
该解决方案与所在地区相关,Rory提供了英国的示例。对于其他日期格式为22-02-2012的地区,您需要将分隔符delims=/替换为delims=-。 - Nuno Furtado
28
在我的系统上,%TIME% 返回值类似于“0:01:15”和“3:15:12”,而答案中的 %%a%%b 代码会给出一个前导空格,如“001”和“315”。要获得四位数字格式的hhmm,请使用以下命令:For /f "tokens=1-2 delims=/: " %%a in ("%TIME%") do (if %%a LSS 10 (set mytime=0%%a%%b) else (set mytime=%%a%%b)) 这将返回类似于“0001”和“0315”的值,我喜欢在我的文件名中使用这种格式。 - twamley
11
wmic 命令的简化版本!到目前为止,我只见过 WMIC Path Win32_LocalTime Get Day,Hour,Minute,Month,Second,Year /Format:table。同样,要以一行代码获取我所在的阿姆斯特丹本地时间的“20120623-1619”:for /f %%a in ('wmic os get LocalDateTime ^| findstr ^[0-9]') do (set ts=%%a) & set datetime=%ts:~0,8%-%ts:~8,4% - Arjan
9
对我来说它显示“%%a在这个时间是意外的”。 - zulc22
显示剩余15条评论

135

还有两种不依赖于时间设置的方法(都来自:如何获得与本地化无关的日期/时间:)。它们都可以获取星期几,而且都不需要管理员权限!:

  1. MAKECAB - will work on EVERY Windows system (fast, but creates a small temp 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
    

    More information about get-date function.

  2. ROBOCOPY - it's not native command for Windows XP and Windows Server 2003, but it can be downloaded from microsoft site. But 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 form 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. VSCRIPT/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, v3 (only for Windows 7 and above)). It is installed by default on everything from Windows 7/Windows Server 2008 and above:

    C:\> powershell get-date -format "{dd-MMM-yyyy HH:mm}"
    

    To use it from a batch file:

    for /f "delims=" %%# in ('powershell get-date -format "{dd-MMM-yyyy HH:mm}"') do @set _date=%%#
    
  6. Self-compiled jscript.net/batch (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 and also creates a temporary file and is based on the time stamps that logman puts on its log files. It will work on everything from Windows XP and above. It probably will be never used by anybody - including me - but 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
    
  8. One more way with WMIC which also gives week of the year and the day of the week, but not the milliseconds (for milliseconds check foxidrive's answer):

    for /f %%# in ('wMIC Path Win32_LocalTime Get /Format:value') do @for /f %%@ in ("%%#") do @set %%@
    echo %day%
    echo %DayOfWeek%
    echo %hour%
    echo %minute%
    echo %month%
    echo %quarter%
    echo %second%
    echo %weekinmonth%
    echo %year%
    
  9. Using TYPEPERF with some efforts to be fast and compatible with different language settings and as fast as possible:

    @echo off
    setlocal
    
    :: Check if Windows is Windows XP and use Windows XP valid counter for UDP performance
    ::if defined USERDOMAIN_roamingprofile (set "v=v4") else (set "v=")
    
    for /f "tokens=4 delims=. " %%# in ('ver') do if %%# GTR 5 (set "v=v4") else ("v=")
    set "mon="
    for /f "skip=2 delims=," %%# in ('typeperf "\UDP%v%\*" -si 0 -sc 1') do (
       if not defined mon (
          for /f "tokens=1-7 delims=.:/ " %%a in (%%#) do (
            set mon=%%a
            set date=%%b
            set year=%%c
            set hour=%%d
            set minute=%%e
            set sec=%%f
            set ms=%%g
          )
       )
    )
    echo %year%.%mon%.%date%
    echo %hour%:%minute%:%sec%.%ms%
    endlocal
    
  10. MSHTA allows calling JavaScript methods similar to the JScript method demonstrated in #3 above. Bear in mind that JavaScript's Date object properties involving month values are numbered from 0 to 11, not 1 to 12. So a value of 9 means October.

    <!-- : Batch portion
    
    @echo off
    setlocal
    
    for /f "delims=" %%I in ('mshta "%~f0"') do set "now.%%~I"
    
    rem Display all variables beginning with "now."
    set now.
    
    goto :EOF
    
    end batch / begin HTA -->
    
    <script>
        resizeTo(0,0)
        var fso = new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1),
            now = new Date(),
            props=['getDate','getDay','getFullYear','getHours','getMilliseconds','getMinutes',
                'getMonth','getSeconds','getTime','getTimezoneOffset','getUTCDate','getUTCDay',
                'getUTCFullYear','getUTCHours','getUTCMilliseconds','getUTCMinutes','getUTCMonth',
                'getUTCSeconds','getYear','toDateString','toGMTString','toLocaleDateString',
                'toLocaleTimeString','toString','toTimeString','toUTCString','valueOf'],
            output = [];
    
        for (var i in props) {output.push(props[i] + '()=' + now[props[i]]())}
        close(fso.Write(output.join('\n')));
    </script>
    

3
for powershell C:>for /f %%i in ('powershell get-date -format "{yyyyMMdd_HHmmss}"') do set datetime=%%i C:>echo %datetime% - Samuel
1
makecab: 这个命令通过创建一个名为 ~.rpt 的文件,并在其中搜索一个以 makecab 开头的字符串来工作,该字符串是像 MakeCAB Report: Tue Sep 02 22:15:57 2014 这样的一行。对我来说,这个命令不是本地化的,它是与语言环境无关的。这个技巧依赖于此。让我们希望它永远不会被本地化,否则要小心! - n611x007
16
我很喜欢开头的文本“再来两个...”,后面跟着8个解决方案。 - Adam Smith
1
什么,没有 mshta 混合体? :) 我能否编辑您的答案并添加一个?这似乎是最好的奇技淫巧解决方案集合,而且似乎 mshta 应该在这里。 - rojo
3
无论我尝试了什么,被接受的解决方案对我都不起作用。其中多个解决方案对我有效(批处理和PowerShell)。 - Brett Wait
显示剩余4条评论

121

区域独立的日期时间解析

%DATE%dir命令的输出格式因地域而异,因此不够健壮也不够智能。 date.exeUnxUtils的一部分)可以以任何可想象的格式提供任何日期和时间信息。您还可以使用date.exe从任何文件中提取日期/时间信息。

示例:(在cmd脚本中,请使用%%代替%)

date.exe +"%Y-%m-%d"
2009-12-22

date.exe +"%T"
18:55:03

date.exe +"%Y%m%d %H%M%S: 任意文本"
20091222 185503: 任意文本

date.exe +"文本:%y/%m/%d-任意文本-%H.%M"
文本:09/12/22-任意文本-18.55

命令:date.exe +"%m-%d """%H %M %S """"
07-22 "18:55:03"`

从参考文件中获取日期/时间信息:
date.exe -r c:\file.txt +"文件.txt的时间戳为:%Y-%m-%d %H:%M:%S"

在CMD脚本中使用它以获取年份、月份、日期和时间信息:

for /f "tokens=1,2,3,4,5,6* delims=," %%i in ('C:\Tools\etc\date.exe +"%%y,%%m,%%d,%%H,%%M,%%S"') do set yy=%%i& set mo=%%j& set dd=%%k& set hh=%%l& set mm=%%m& set ss=%%n

在CMD脚本中使用它来获取任何所需格式的时间戳:

for /f "tokens=*" %%i in ('C:\Tools\etc\date.exe +"%%y-%%m-%%d %%H:%%M:%%S"') do set timestamp=%%i

从任何参考文件中提取日期/时间信息。

for /f "tokens=1,2,3,4,5,6* delims=," %%i in ('C:\Tools\etc\date.exe -r file.txt +"%%y,%%m,%%d,%%H,%%M,%%S"') do set yy=%%i& set mo=%%j& set dd=%%k& set hh=%%l& set mm=%%m& set ss=%%n

在文件中添加日期/时间信息:

for /f "tokens=*" %%i in ('C:\Tools\etc\date.exe -r file.txt +"%%y-%%m-%%d.%%H%%M%%S"') do ren file.txt file.%%i.txt

date.exe是免费GNU工具的一部分,无需安装即可使用。

注意:将date.exe复制到任何在搜索路径中的目录中可能会导致使用Windows内置date命令的其他脚本失败。


6
比上面那个奇怪但更受欢迎的解决方案要好得多,但我不得不添加/t以避免在Windows 8.1上出现提示。 - rainabba
6
Windows 8.1内置的date.exe工具与所在地区有关。在我的系统上,它返回格式为dd/MM/yyyy的日期,如果它是与所在地区无关的,我期望的格式应该是MM/dd/yyyy或yyyy-MM-dd。我认为这个答案不是针对内置的date.exe工具,而是针对某个第三方版本的。 - SSS
1
如果您在命令行中提供所需的格式,它将与区域设置无关。 - terrinecold
3
请注意,date.exe(UnxUtils的一部分)与内置的日期命令不同。因此,如果您必须添加/t,则会执行Windows日期命令。如果类似于date.exe +"%Y-%m-%d"这样的命令可以正常工作,那么您已经成功安装了UnxUtils。 :-) - just.do.it
如果有人感兴趣的话... https://dev59.com/sXVC5IYBdhLWcg3wtzqs#65943831 - om-ha
显示剩余2条评论

45

这是来自alt.msdos.batch.nt的一种本地独立工作的变体。

将以下内容放入一个文本文件中,例如getDate.cmd:

-----------8<------8<------------ snip -- snip ----------8<-------------
    :: Works on any NT/2k machine independent of regional date settings
    @ECHO off
    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'% LSS 100 set 'yy'=20%'yy'%
    set Today=%'yy'%-%'mm'%-%'dd'% 
    ENDLOCAL & SET v_year=%'yy'%& SET v_month=%'mm'%& SET v_day=%'dd'%

    ECHO Today is Year: [%V_Year%] Month: [%V_Month%] Day: [%V_Day%]

    :EOF
-----------8<------8<------------ snip -- snip ----------8<-------------

为了让代码运行时不出现错误信息到标准错误输出(stderr),我不得不在%%a、%%b和%%c的变量分配周围添加单引号。我的语言环境(PT)在循环/解析的某个阶段引起了错误,例如"set =20"这样的东西被执行。引号产生一个(虽然为空的)标记,用于赋值语句的左侧。
缺点是语言环境变量名杂乱无章:'yy'、'mm'和'dd'。但是,谁在乎呢!

3
这是完美的,也是我迄今见过的最简单、最优雅的方法。 - Doug
3
请参阅 Jeroen的增强版,因为并非所有语言环境都在echo:^|date的输出中使用字符串“dd”、“mm”和“yy”。 - Arjan
不适用于所有语言环境。 (在德语中,date 给出 Geben Sie das neue Datum ein: (TT-MM-JJ),其中 JJ 会破坏您的脚本(期望 YY)) - Stephan

44

我使用这个(再次强调不是区域无关的(英国))

set bklog=%date:~6,4%-%date:~3,2%-%date:~0,2%_%time:~0,2%%time:~3,2%

1
请参阅 Cmd.exe环境变量冒号和波浪号 了解这个鲜为人知但非常有效的技巧。(欢迎提供微软权威参考资料的指针。) - DavidRR
这是微软针对Windows XP的批处理文件参考文献。该参考文献包括使用批处理参数。不幸的是,没有讨论“切片”技术。 - DavidRR
1
这对我来说不太起作用。也许与区域设置有关?在2014年10月15日星期三运行它时,我得到了“/15/- 1-We_1009”的输出。 - Joel B
这非常精确和准确。我认为这是最好的答案,因为您不需要进行任何调整即可将其用作文件名。谢谢分享! - omostan
1
@DavidRR Microsoft内置的SET命令帮助说明了如何在扩展环境变量时获取子字符串。 以下是原文复制如下: https://www.robvanderwoude.com/allhelpw10pro_en.php#SET 请参阅“May also specify substrings for an expansion.”部分。 - undefined
显示剩余2条评论

38

这段代码的前四行将在Windows XP专业版或更高版本中为您提供可靠的YY DD MM YYYY HH Min Sec变量。

@echo off
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 "datestamp=%YYYY%%MM%%DD%" & set "timestamp=%HH%%Min%%Sec%" & set "fullstamp=%YYYY%-%MM%-%DD%_%HH%%Min%-%Sec%"
echo datestamp: "%datestamp%"
echo timestamp: "%timestamp%"
echo fullstamp: "%fullstamp%"
pause

完美,这对我来说是最好的解决方案,因为调用PS会导致cmd文本的外观变得奇怪。 - Ste
有没有办法获取毫秒数? - Jon Grah

27

不幸的是,这并不免疫地区设置,但它确实实现了您想要的功能。

set hour=%time:~0,2%
if "%time:~0,1%"==" " set hour=0%time:~1,1%
set _my_datetime=%date:~10,4%-%date:~4,2%-%date:~7,2%_%hour%%time:~3,2%

在维基百科上,你可以找到很棒的内容,比如环境变量


1
Mark - 发现了一个名为 Cmd.exe Environment Variables with Colon and Tilde 的文章,其中描述了你回答中展示的“切片”技术。在维基百科文章中没有找到这些信息。希望能够从微软官方获得权威参考资料。 - DavidRR
1
这是微软为Windows XP提供的批处理文件参考文献。该参考文献包括使用批处理参数。不幸的是,没有讨论“切片”技术。 - DavidRR

23
请使用下面的脚本在命令行中获取当前日期:
echo %Date:~0,3%day

13
玩了一下,这是我找到的最短的获取日期和时间的方法:echo %date% %time% - loomi
如果您只是想将日期和时间用于日志记录,那么在我看来,这是最简单的解决方案... - R Yoda

17
"d:\Program Files\7-Zip\7z.exe" a -r code_%date:~10,4%-%date:~4,2%-%date:~7,2%.zip

1
http://www.dotnetperls.com/7-zip-examples有一些很好的观点,对未来的某个人可能会有用。 - Saravanan

15

另一种方式 (来源):

@For /F "tokens=2,3,4 delims=/ " %%A in ('Date /t') do @( 
    Set Month=%%A
    Set Day=%%B
    Set Year=%%C
)

@echo DAY = %Day%
@echo Month = %Month%
@echo Year = %Year%

请注意,我在这里给出的两个答案仍然依赖于日期和月份的顺序,这是由区域设置决定的 - 不确定如何解决这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接