在Windows批处理脚本中格式化日期和时间

247

在Windows(Windows XP)批处理脚本中,我需要格式化当前日期和时间以便稍后用于文件名等。

这与Stack Overflow的问题 如何在批处理文件中追加日期类似,但是还包括时间。

到目前为止,我有:

echo %DATE%
echo %TIME%
set datetimef=%date:~-4%_%date:~3,2%_%date:~0,2%__%time:~0,2%_%time:~3,2%_%time:~6,2%
echo %datetimef%

得到以下结果:

28/07/2009
 8:35:31.01
2009_07_28__ 8_36_01

有没有办法在 %TIME% 中允许单个数字的小时数,这样我就可以得到以下结果?

2009_07_28__08_36_01

无论区域设置如何,在批处理文件中拆分%date% - phuclv
你可以将datetimef变量中的空格替换为0。例如:SET datetimef=%datetimef: =0% - SebaGra
37个回答

2
set hourstr = %time:~0,2%
if "%time:~0,1%"==" " (set hourstr=0%time:~1,1%)
set datetimestr=%date:~0,4%%date:~5,2%%date:~8,2%-%hourstr%%time:~3,2%%time:~6,2%

2
创建一个名为“search_files.bat”的文件,并将以下内容放入文件中。然后双击它。临时变量%THH%被设置为适当处理上午时间。如果时间的前两位数字为0,则Windows会忽略LOG文件的其余文件名。请保留HTML标签。
CD .
SET THH=%time:~0,2%
SET THH=%THH: =0%
dir /s /b *.* > %date:~10,4%-%date:~4,2%-%date:~7,2%@%THH%.%time:~3,2%.%time:~6,2%.LOG

2
这是关于日期时间字符串的我的建议。在MM DD YYYY系统上,要交换第一个和第二个%DATE:~条目。
    REM ====================================================================================
    REM CREATE UNIQUE DATETIME STRING FOR ADDING TO FILENAME
    REM ====================================================================================
    REM Can handle dd DDxMMxYYYY and DDxMMxYYYY > CREATES YYYYMMDDHHMMSS (x= any character)
    REM ====================================================================================
    REM CHECK for SHORTDATE dd DDxMMxYYYY 
    IF "%DATE:~0,1%" GTR "3" (
        SET DATETIME=%DATE:~9,4%%DATE:~6,2%%DATE:~3,2%%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%
    ) ELSE (
    REM ASSUMES SHORTDATE DDxMMxYYYY
        SET DATETIME=%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%
        )
    REM CORRECT FOR HOURS BELOW 10
    IF %DATETIME:~8,2% LSS 10 SET DATETIME=%DATETIME:~0,8%0%DATETIME:~9,5%
    ECHO %DATETIME%

1
使用REG保存/修改/恢复您的批处理文件中最有用的任何值。这是Windows 7,对于其他版本,您可能需要不同的键名。
reg save    "HKEY_CURRENT_USER\Control Panel\International" _tmp.reg /y
reg add     "HKEY_CURRENT_USER\Control Panel\International" /v sShortDate  /d "yyyy-MM-dd" /f
set file=%DATE%-%TIME: =0%
reg restore "HKEY_CURRENT_USER\Control Panel\International" _tmp.reg
set file=%file::=-%
set file=%file:.=-%
set file

1
该脚本使用WMI接口,主要通过WMIC工具访问,这是自Windows XP专业版以来Windows的一部分(家庭版也支持,但默认情况下未安装该工具)。该脚本还通过创建和调用WSH vbscript实现了缺失的WMIC工具解决方法,以访问WMI接口,并将时间以与WMIC工具提供的相同格式写入控制台输出。
@ECHO OFF
REM Returns: RETURN
REM Modify:  RETURN, StdOut
REM Required - mandatory: none
REM Required - optionaly: format strings delimited by a space to format an output delimited by predefined delimiter
REM    YYYY = 4-digit year
REM      MM = 2-digit month
REM      DD = 2-digit day
REM      hh = 2-digit hour
REM      mm = 2-digit minute
REM      ss = 2-digit second
REM      ms = 3-digit millisecond

CALL :getTime %*
ECHO %RETURN%
GOTO :EOF


REM SUBROUTINE
REM Returns: RETURN
REM Modify:  RETURN
REM Required - mandatory: none
REM Required - optionaly: format strings delimited by a space to format an output delimited by predefined delimiter
REM    YYYY = 4-digit year
REM      MM = 2-digit month
REM      DD = 2-digit day
REM      hh = 2-digit hour
REM      mm = 2-digit minute
REM      ss = 2-digit second
REM      ms = 3-digit millisecond
:getTime
  SETLOCAL EnableDelayedExpansion
    SET DELIM=-
    WHERE /Q wmic.exe
    IF NOT ERRORLEVEL 1 FOR /F "usebackq skip=1 tokens=*" %%x IN (`wmic.exe os get LocalDateTime`) DO (SET DT=%%x & GOTO getTime_Parse)
    SET _TMP=%TEMP:"=%
    ECHO Wscript.StdOut.WriteLine (GetObject("winmgmts:root\cimv2:Win32_OperatingSystem=@").LocalDateTime)>"%_TMP%\get_time_local-helper.vbs"
    FOR /F "usebackq tokens=*" %%x IN (`cscript //B //NoLogo "%_TMP%\get_time_local-helper.vbs"`) DO (SET DT=%%x & GOTO getTime_Parse)
    :getTime_Parse
      SET _RET=
      IF "%1" EQU "" (
        SET _RET=%DT:~0,4%%DELIM%%DT:~4,2%%DELIM%%DT:~6,2%%DELIM%%DT:~8,2%%DELIM%%DT:~10,2%%DELIM%%DT:~12,2%%DELIM%%DT:~15,3%
      ) ELSE (
        REM Not recognized format strings are ignored during parsing - no error is reported.
       :getTime_ParseLoop
         SET _VAL=
         IF "%1" EQU "YYYY" SET _VAL=%DT:~0,4%
         IF "%1" EQU "MM"   SET _VAL=%DT:~4,2%
         IF "%1" EQU "DD"   SET _VAL=%DT:~6,2%
         IF "%1" EQU "hh"   SET _VAL=%DT:~8,2%
         IF "%1" EQU "mm"   SET _VAL=%DT:~10,2%
         IF "%1" EQU "ss"   SET _VAL=%DT:~12,2%
         IF "%1" EQU "ms"   SET _VAL=%DT:~15,3%
         IF DEFINED _VAL (
           IF DEFINED _RET (
             SET _RET=!_RET!%DELIM%!_VAL!
           ) ELSE (
             SET _RET=!_VAL!
           )
         )
         SHIFT
         IF "%1" NEQ "" GOTO getTime_ParseLoop
      )
  ENDLOCAL & SET RETURN=%_RET%
GOTO :EOF

1
也许是这样的:

可能像这样:

@call:DateTime

@for %%? in (
    "Year   :Y"
    "Month  :M"
    "Day    :D"
    "Hour   :H"
    "Minutes:I"
    "Seconds:S"
) do @for /f "tokens=1-2 delims=:" %%# in (%%?) do @for /f "delims=" %%_ in ('echo %%_DT_%%$_%%') do @echo %%# : _DT_%%$_ : %%_

:: OUTPUT
:: Year    : _DT_Y_ : 2014
:: Month   : _DT_M_ : 12
:: Day     : _DT_D_ : 17
:: Hour    : _DT_H_ : 09
:: Minutes : _DT_I_ : 04
:: Seconds : _DT_S_ : 35

@pause>nul

@goto:eof

:DateTime
    @verify errorlevel 2>nul & @wmics Alias /? >nul 2>&1
    @if not errorlevel 1 (
        @for /f "skip=1 tokens=1-6" %%a in ('wmic path win32_localtime get day^,hour^,minute^,month^,second^,year /format:table') do @if not "%%f"=="" ( set "_DT_D_=%%a" & set "_DT_H_=%%b" & set "_DT_I_=%%c" & set "_DT_M_=%%d" & set "_DT_S_=%%e" & set "_DT_Y_=%%f" )
    ) else (
        @set "_DT_T_=1234567890 "
    )
    @if errorlevel 1 (
        @for %%? in ("iDate" "sDate" "iTime" "sTime" "F" "Y" "M" "D" "H" "I" "S") do @set "_DT_%%~?_=%%~?"
        @for %%? in ("Date" "Time") do @for /f "skip=2 tokens=1,3" %%a in ('reg query "HKCU\Control Panel\International" /v ?%%~? 2^>nul') do @for /f %%x in ('echo:%%_DT_%%a_%%') do @if "%%x"=="%%a" set "_DT_%%a_=%%b"
        @for /f "tokens=1-3 delims=%_DT_T_%" %%a in ("%time%") do @set "_DT_T_=%%a%%b%%c"
    )
    @if errorlevel 1 (
        @if "%_DT_iDate_%"=="0" (set "_DT_F_=_DT_D_ _DT_Y_ _DT_M_") else if "%_DT_iDate_%"=="1" (set "_DT_F_=_DT_D_ _DT_M_ _DT_Y_") else if "%_DT_iDate_%"=="2" (set "_DT_F_=_DT_Y_ _DT_M_ _DT_D_")
        @for /f "tokens=1-4* delims=%_DT_sDate_%" %%a in ('date/t') do @for /f "tokens=1-3" %%x in ('echo:%%_DT_F_%%') do @set "%%x=%%a" & set "%%y=%%b" & set "%%z=%%c"
        @for /f "tokens=1-3 delims=%_DT_T_%" %%a in ("%time%") do @set "_DT_H_=%%a" & set "_DT_I_=%%b" & set "_DT_S_=%%c"
        @for %%? in ("iDate" "sDate" "iTime" "sTime" "F" "T") do @set "_DT_%%~?_="
    )
    @for %%i in ("Y"                ) do @for /f %%j in ('echo:"%%_DT_%%~i_%%"') do @set /a _DT_%%~i_+=  0 & @for /f %%k in ('echo:"%%_DT_%%~i_:~-4%%"') do @set "_DT_%%~i_=%%~k"
    @for %%i in ("M" "D" "H" "I" "S") do @for /f %%j in ('echo:"%%_DT_%%~i_%%"') do @set /a _DT_%%~i_+=100 & @for /f %%k in ('echo:"%%_DT_%%~i_:~-2%%"') do @set "_DT_%%~i_=%%~k"
@exit/b

1
使用%时,当时间值为7-9时,会遇到十六进制操作错误。为避免此错误,请使用DelayedExpansion并使用!min:~1!获取时间值。
另一种方法是,如果您有PowerShell,可以调用它:
for /F "usebackq delims=Z" %%i IN (`powershell Get-Date -format u`) do (set server-time=%%i)

1

我尝试了被接受的答案,它运行得非常好。不幸的是,美国时间格式似乎是H:MM:SS.CS,而前面缺少的0会在上午10点之前导致解析问题。为了克服这个障碍并允许解析大多数世界时间格式,我想出了这个简单的例程,它似乎运行得非常好。

:ParseTime
rem The format of %%TIME%% is H:MM:SS.CS or (HH:MM:SS,CS) for example 0:01:23.45 or 23:59:59,99
FOR /F "tokens=1,2,3,4 delims=:.," %%a IN ("%1") DO SET /A "%2=(%%a * 360000) + (%%b * 6000) + (%%c * 100) + %%d"
GOTO :EOF

这个程序的好处在于你可以将时间字符串作为第一个参数,将你想要包含时间(以百分之一秒为单位)的环境变量的名称作为第二个参数传递进去。例如:

CALL :ParseTime %START_TIME% START_CS
CALL :ParseTime %TIME% END_CS
SET /A DURATION=%END_CS% - %START_CS%

(*Chris*)

1
在这种情况下,使用简单的标准编程方法: 不要花费大量精力解析未知实体,只需保存当前配置,将其重置为已知状态,提取信息,然后恢复原始状态。仅使用标准Windows资源。
具体来说,日期和时间格式存储在注册表键HKCU\Control Panel\International\中的[MS定义]“值”:“sTimeFormat”和“sShortDate”中。 Reg是附带所有Windows版本的控制台注册表编辑器。 修改HKCU键不需要提升特权。
Prompt $N:$D $T$G

::Save current config to a temporary (unique name) subkey, Exit if copy fails
Set DateTime=
Set ran=%Random%
Reg copy "HKCU\Control Panel\International" "HKCU\Control Panel\International-Temp%ran%" /f
If ErrorLevel 1 GoTO :EOF

::Reset the date format to your desired output format (take effect immediately)
::Resetting the time format is useless as it only affect subsequent console windows
::Reg add "HKCU\Control Panel\International" /v sTimeFormat /d "HH_mm_ss"   /f
Reg add "HKCU\Control Panel\International" /v sShortDate  /d "yyyy_MM_dd" /f

::Concatenate the time and (reformatted) date strings, replace any embedded blanks with zeros
Set DateTime=%date%__%time:~0,2%_%time:~3,2%_%time:~6,2%
Set DateTime=%DateTime: =0%

::Restore the original config and delete the temp subkey, Exit if restore fails
Reg copy   "HKCU\Control Panel\International-Temp%ran%" "HKCU\Control Panel\International" /f
If ErrorLevel 1 GoTO :EOF
Reg delete "HKCU\Control Panel\International-Temp%ran%" /f

简单、直接,适用于所有地区。
由于我不理解的原因,在控制台窗口中重置“sShortDate”值会立即生效,但重置非常相似的“sTimeFormat”值却不会生效,直到打开新的控制台窗口。然而,唯一可更改的是分隔符-数字位置是固定的。同样,“HH”时间标记应该在前面加上前导零,但它并没有这样做。幸运的是,解决方法很容易。

与其添加前导零,为什么不打乱机器配置,将其更改为您的随机需求,然后再进行操作呢?这种方法超出了常规,需要大量的努力,并可能导致无限数量的意外后果。而且我甚至不想开始讨论可读性和标准预期代码行为。赞! - vaitrafra
重置sTimeFormat时间格式是无用的。不对。因为它会影响后续的控制台提示,所以请使用for /f "delims=" %%G in ('cmd /C echo SET "DateTime=%%date%%__%%time%%"') do %%G来应用它。 - JosefZ

1
所以问题在于%DATE%受地区设置影响。因此,之前的大部分答案对我都不适用。如果您不在意确切的格式,只是想要一个时间戳来区分文件,可以这样做:
set _date=%DATE%-%TIME%
set _date=%_date:/=-%
set _date=%_date: =-%
set _date=%_date::=-%
set _date=%_date:.=-%
echo %_date%

这应该适用于大多数语言环境。如果不行,请添加另一行set _date=%_date:<offending_char>=-%以删除有问题的字符,例如:与文件名不兼容的字符或者你不想在文件名中出现的字符。

enter image description here

enter image description here

请注意,这并不符合问题所规定的确切标准。

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