ChatGPT解决这个技术问题 Extra ChatGPT

Format date and time in a Windows batch script

In a Windows (Windows XP) batch script I need to format the current date and time for later use in files names, etc.

It is similar to Stack Overflow question How to append a date in batch files, but with time in as well.

I have this so far:

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%

which gives:

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

Is there a way I can allow for a single digit hour in %TIME%, so I can get the following?

2009_07_28__08_36_01
You can replace empty spaces on your datetimef variable, and put 0's instead. On your example: SET datetimef=%datetimef: =0%

N
Nasir Grewal

I ended up with this script:

set hour=%time:~0,2%
if "%hour:~0,1%" == " " set hour=0%hour:~1,1%
echo hour=%hour%
set min=%time:~3,2%
if "%min:~0,1%" == " " set min=0%min:~1,1%
echo min=%min%
set secs=%time:~6,2%
if "%secs:~0,1%" == " " set secs=0%secs:~1,1%
echo secs=%secs%

set year=%date:~-4%
echo year=%year%

:: On WIN2008R2 e.g. I needed to make your 'set month=%date:~3,2%' like below ::otherwise 00 appears for MONTH

set month=%date:~4,2%
if "%month:~0,1%" == " " set month=0%month:~1,1%
echo month=%month%
set day=%date:~0,2%
if "%day:~0,1%" == " " set day=0%day:~1,1%
echo day=%day%

set datetimef=%year%%month%%day%_%hour%%min%%secs%

echo datetimef=%datetimef%

FYI, on Windows Server 2003 and on Windows 7, this script gave me "201200Mo_085806" (correct year & time).
As note for someone who will come here from Google (like me): This is locale dependent, so it may require tweaks to work on non-english Windows!
i did it this way: Time /T > Time.dat set /P ftime= < Time.dat set fDate=%date:~6%%date:~3,2%%date:~0,2%%ftime:~0,2%%ftime:~3,2% echo %fDate% -> 201310170928
What does %time:~0,2% do where is some documentation on the :~,% structure?
All this can be done in just 2 lines using ordinary string replacement: stackoverflow.com/a/23558738/1879699
n
nightcoder

Here is how I generate a log filename (based on http://ss64.com/nt/syntax-getdate.html):

@ECHO OFF
:: Check WMIC is available
WMIC.EXE Alias /? >NUL 2>&1 || GOTO s_error

:: Use WMIC to retrieve date and time
FOR /F "skip=1 tokens=1-6" %%G IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table') DO (
   IF "%%~L"=="" goto s_done
      Set _yyyy=%%L
      Set _mm=00%%J
      Set _dd=00%%G
      Set _hour=00%%H
      SET _minute=00%%I
      SET _second=00%%K
)
:s_done

:: Pad digits with leading zeros
      Set _mm=%_mm:~-2%
      Set _dd=%_dd:~-2%
      Set _hour=%_hour:~-2%
      Set _minute=%_minute:~-2%
      Set _second=%_second:~-2%

Set logtimestamp=%_yyyy%-%_mm%-%_dd%_%_hour%_%_minute%_%_second%
goto make_dump

:s_error
echo WMIC is not available, using default log filename
Set logtimestamp=_

:make_dump
set FILENAME=database_dump_%logtimestamp%.sql
...

best answer on SO for questions about locale-independent timestamp generation in batch.
Awesome! There should be a way to mark this as the solution
this is the best answer. works with windows 7 and 10 Spanish
A
Andreas

I usually do it this way whenever I need a date/time string:

set dt=%DATE:~6,4%_%DATE:~3,2%_%DATE:~0,2%__%TIME:~0,2%_%TIME:~3,2%_%TIME:~6,2%
set dt=%dt: =0%

This is for the German date/time format (dd.mm.yyyy hh:mm:ss). Basically I concatenate the substrings and finally replace all spaces with zeros.

The resulting string has the format: yyyy_mm_dd__hh_mm_ss

Short explanation of how substrings work:

%VARIABLE:~num_chars_to_skip,num_chars_to_keep%

So to get just the year from a date like "29.03.2018" use:

%DATE:~6,4%
       ^-----skip 6 characters
         ^---keep 4 characters 

by far the most elegant solution when you just need a clean timestamp (no spaces or other chars)
Best answer since it explains how to print the variables instead of forcing some substring that can be different for a lot of people. I would always run echo %date%_%time% first to see what the variables alone print for me and then decide what substrings of those i wanna keep.
How do you get the UTC-timezone as well, e.g. adding +01 in the end of the resulting string?
@AndreasL. Getting the timezone information on the commandline involves other tools. You can utilise systeminfo for example, like this: for /F "tokens=2 delims=^(: " %i in ('systeminfo^|find "Zeit"') do set "tz=%i" (assuming you are using a german Windows). Note that if you want to use his in a batch file you need to double the %s.
m
mwfearnley
@ECHO OFF
: Sets the proper date and time stamp with 24Hr Time for log file naming
: convention ('YYYYMMDD_HHMMSS')

: Scrapes the characters out of their expected permissions in the date/time
: environment variables.

: Expects a date format of '____MM_DD_YYYY'
: Expects a time format of 'HH:MM:SS' or ' H:MM:SS'

SET HOUR=%time:~0,2%
SET dtStamp9=%date:~-4%%date:~4,2%%date:~7,2%_0%time:~1,1%%time:~3,2%%time:~6,2% 
SET dtStamp24=%date:~-4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%

if "%HOUR:~0,1%" == " " (SET dtStamp=%dtStamp9%) else (SET dtStamp=%dtStamp24%)

ECHO %dtStamp%

PAUSE

On Windows Server 2003 and on Windows 7, this gave me the correct string. Much more elegant than what I've constructed in the past, so thank you!
Here is what it gives me in Windows 7 with russian locale. Current time is 2013-05-03T02:22:51, but the script prints: "2013-5.-01_02_22_51"
The %date% will give different string with different locale.
returns 20146.0._173502 to me (czech locale)
win7 64bit ultimate, incorrect time: 20140.01_131612 , must be(2014.10.26_131612)
G
G. Lombard

If PowerShell is installed, then you can easily and reliably get the Date/Time in any format you'd like, for example:

for /f %%a in ('powershell -Command "Get-Date -format yyyy_MM_dd__HH_mm_ss"') do set datetime=%%a
move "%oldfile%" "backup-%datetime%"

Of course nowadays PowerShell is always installed, but on Windows XP you'll probably only want to use this technique if your batch script is being used in a known environment where you know PS is available (or check in your batch file if PowerShell is available...)

You may reasonably ask: why use a batch file at all if you can use PowerShell to get the date/time, but I think some obvious reasons are: (a) you're not all that familiar with PowerShell and still prefer to do most things the old-fashioned way with batch files or (b) you're updating an old script and don't want to port the whole thing to PS.


o
opello

I came across this problem today and solved it with:

SET LOGTIME=%TIME: =0%

It replaces spaces with 0s and basically zero-pads the hour.

After some quick searching I didn't find out if it required command extensions (still worked with SETLOCAL DISABLEEXTENSIONS).


OK, substitusion in variables. Now - how to substitute a colon (:)?
@TomaszGandor This works for me: echo %TIME: =:% but if it isn't maybe try escaping the : with a ^ like echo %TIME: =^:% (which also works for me).
+1 for simplicity. Colons aren't valid in filenames. set theTime=%Time::=% deletes them. Can you substitute 0 for space, delete the colons, and truncate to 6 characters (thus deleting the decimal part) in a single statement? It's not that big of deal if it takes two or three lines. I'm just curious.
Not that I know. Please follow-up if you find one!
P
Peter Mortensen

As has been noted, parsing the date and time is only useful if you know the format being used by the current user (for example, MM/dd/yy or dd-MM-yyyy just to name two). This could be determined, but by the time you do all the stressing and parsing, you will still end up with some situation where there is an unexpected format used, and more tweaks will be be necessary.

You can also use some external program that will return a date slug in your preferred format, but that has disadvantages of needing to distribute the utility program with your script/batch.

There are also batch tricks using the CMOS clock in a pretty raw way, but that is tooo close to bare wires for most people, and also not always the preferred place to retrieve the date/time.

Below is a solution that avoids the above problems. Yes, it introduces some other issues, but for my purposes I found this to be the easiest, clearest, most portable solution for creating a datestamp in .bat files for modern Windows systems. This is just an example, but I think you will see how to modify for other date and/or time formats, etc.

reg copy "HKCU\Control Panel\International" "HKCU\Control Panel\International-Temp" /f
reg add "HKCU\Control Panel\International" /v sShortDate /d "yyMMdd" /f
@REM reg query "HKCU\Control Panel\International" /v sShortDate
set LogDate=%date%
reg copy "HKCU\Control Panel\International-Temp" "HKCU\Control Panel\International" /f

This is a terrible solution. If it fails then a global setting is permanently changed. It also introduces race conditions with other applications.
You could use the reg query "HKCU\Control Panel\International" /v sShortDatepart without changing the registry setting (exercise left to the reader!).
J
Jesse

If you don't exactly need this format:

2009_07_28__08_36_01

Then you could use the following 3 lines of code which uses %date% and %time%:

set mydate=%date:/=%
set mytime=%time::=%
set mytimestamp=%mydate: =_%_%mytime:.=_%

Note: The characters / and : are removed and the character . and space is replaced with an underscore.

Example output (taken Wednesday 8/5/15 at 12:49 PM with 50 seconds and 93 milliseconds):

echo %mytimestamp%
Wed_08052015_124950_93

when hour is less than 12, set mydate=%date:/=% set mytime=%time::=% set mytime=%mytime: =0% set mytimestamp=%mydate: =_%_%mytime:.=_%
M
Mike Raynham
REM Assumes UK style date format for date environment variable (DD/MM/YYYY).
REM Assumes times before 10:00:00 (10am) displayed padded with a space instead of a zero.
REM If first character of time is a space (less than 1) then set DATETIME to:
REM YYYY-MM-DD-0h-mm-ss
REM Otherwise, set DATETIME to:
REM YYYY-MM-DD-HH-mm-ss
REM Year, month, day format provides better filename sorting (otherwise, days grouped
REM together when sorted alphabetically).

IF "%time:~0,1%" LSS "1" (
   SET DATETIME=%date:~6,4%-%date:~3,2%-%date:~0,2%-0%time:~1,1%-%time:~3,2%-%time:~6,2%
) ELSE (
   SET DATETIME=%date:~6,4%-%date:~3,2%-%date:~0,2%-%time:~0,2%-%time:~3,2%-%time:~6,2%
)

ECHO %DATETIME%

Just to say I'm from the UK, but at some point I changed my date format to yyyy-mm-dd, so this doesn't work for me.
P
Peter Mortensen

The following may not be a direct answer but a close one?

set hour=%time:~0,2%
if "%hour:~0,1%" == " " set datetimef=%date:~-4%_%date:~3,2%_%date:~0,2%__0%time:~1,2%_%time:~3,2%_%time:~6,2%
else set datetimef=%date:~-4%_%date:~3,2%_%date:~0,2%__%time:~0,2%_%time:~3,2%_%time:~6,2%

At least it may be inspiring.


Answers using %date%/%time% are heavily dependent on locale settings. What format does this one expect?
n
nik

The offset:length formatting supported with the SET command in Windows will not allow you to pad the 0 as you seem to be interested in.

However, you can code a BATCH script to check for the hour being less than 10 and
pad accordingly with a different echo string.

You will find some information on the SET command on this link.

You can also change to other programming methods to get here.

It is quite simple in unix bash (available with Cygwin on Windows) to just say,

date +%Y_%m_%d__%H_%M_%S

And, it always pads correctly.


Using Bash is cheating! :-)
P
Peter Mortensen

I did it this way:

REM Generate FileName from date and time in format YYYYMMTTHHMM

Time /T > Time.dat
set /P ftime= < Time.dat

set FileName=LogFile%date:~6%%date:~3,2%%date:~0,2%%ftime:~0,2%%ftime:~3,2%.log

echo %FileName%

LogFile201310170928.log


It runs on english server (OS Name: Microsoft(R) Windows(R) Server 2003 Standard x64 Edition, OS Version:5.2.3790 Service Pack 2 Build 3790)
and also tested on german server (Betriebssystemname: Microsoft® Windows Server® 2008 Enterprise, Betriebssystemversion:6.0.6002 Service Pack 2 Build 6002)
Even this one ist ok: (Betriebssystemname: Microsoft Windows Server 2012 Standard, Betriebssystemversion: 6.2.9200 Nicht zutreffend Build 9200)
P
Peter Mortensen

I'm really new to batch files and this is my code!! (I am not sure why, but I couldn't combine date /t and time /t together and I couldn't use %date% and %time% directly without a variable...)

@ECHO OFF
set ldt=%date% %time%
echo %ldt%>> logs.txt
EXIT

It is kind of reused from others (the question was to get a formatted timedate to use as filename).


K
Kees
::========================================================================  
::== CREATE UNIQUE DATETIME STRING IN FORMAT YYYYMMDD-HHMMSS   
::======= ================================================================  
FOR /f %%a IN ('WMIC OS GET LocalDateTime ^| FIND "."') DO SET DTS=%%a  
SET DATETIME=%DTS:~0,8%-%DTS:~8,6%  

The first line always outputs in this format regardles of timezone: 20150515150941.077000+120 This leaves you with just formatting the output to fit your wishes.


P
Peter Mortensen

There is another easy way of doing it:

set HH=%time:~0,2%
if %HH% LEQ 9 (
set HH=%time:~1,1%
)

d
derty2

This batch script will do exactly what the O.P. wants (tested on Windows XP SP3).

I also used that clever registry trick described by "jph" previously which IMHO is the simplest way of getting 100% consistent formatting of the date to "yyyy_MM_dd" on any Windows system new or old. The change to one Registry value for doing this is instantaneous temporary and trivial; it only lasts a few milliseconds before it is immediately reverted back.

Double-click this batch file for an instant demo, Command Prompt window will pop up and display your timestamp . . . . .

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: generates a custom formatted timestamp string using date and time.
:: run this batch file for an instant demo.
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

@ECHO OFF
SETLOCAL & MODE CON:COLS=80 LINES=15 & COLOR 0A

:: --- CHANGE THE COMPUTER DATE FORMAT TEMPORARILY TO MY PREFERENCE "yyyy_MM_dd",
REG COPY "HKCU\Control Panel\International" "HKCU\Control Panel\International-Temp" /f 2>nul >nul
REG ADD "HKCU\Control Panel\International" /v sShortDate /d "yyyy_MM_dd" /f 2>nul >nul

SET MYDATE=%date%

:: --- REVERT COMPUTER DATE BACK TO SYSTEM PREFERENCE
REG COPY "HKCU\Control Panel\International-Temp" "HKCU\Control Panel\International" /f 2>nul >nul
REG DELETE "HKCU\Control Panel\International-Temp" /f 2>nul >nul

:: --- SPLIT THE TIME [HH:MM:SS.SS] TO THREE SEPARATE VARIABLES [HH] [MM] [SS.SS]
FOR /F "tokens=1-3 delims=:" %%A IN ('echo %time%') DO (
SET HOUR=%%A
SET MINUTES=%%B
SET SECONDS=%%C
)

:: --- CHOOSE ONE OF THESE TWO OPTIONS :
:: --- FOR 4 DIGIT SECONDS        //REMOVES THE DOT FROM THE SECONDS VARIABLE [SS.SS]
:: SET SECONDS=%SECONDS:.=%
:: --- FOR 2 DIGIT SECONDS        //GETS THE FIRST TWO DIGITS FROM THE SECONDS VARIABLE [SS.SS]
SET SECONDS=%SECONDS:~0,2% 

:: --- FROM 12 AM TO 9 AM, THE HOUR VARIABLE WE EXTRACTED FROM %TIME% RETURNS A SINGLE DIGIT, 
:: --- WE PREFIX A ZERO CHARACTER TO THOSE CASES, SO THAT OUR WANTED TIMESTAMP
:: --- ALWAYS GENERATES DOUBLE-DIGIT HOURS (24-HOUR CLOCK TIME SYSTEM).
IF %HOUR%==0 (SET HOUR=00)
IF %HOUR%==1 (SET HOUR=01)
IF %HOUR%==2 (SET HOUR=02)
IF %HOUR%==3 (SET HOUR=03)
IF %HOUR%==4 (SET HOUR=04)
IF %HOUR%==5 (SET HOUR=05)
IF %HOUR%==6 (SET HOUR=06)
IF %HOUR%==7 (SET HOUR=07)
IF %HOUR%==8 (SET HOUR=08)
IF %HOUR%==9 (SET HOUR=09)

:: --- GENERATE OUR WANTED TIMESTAMP
SET TIMESTAMP=%MYDATE%__%HOUR%_%MINUTES%_%SECONDS%

:: --- VIEW THE RESULT IN THE CONSOLE SCREEN
ECHO.
ECHO    Generate a custom formatted timestamp string using date and time.
ECHO.
ECHO    Your timestamp is:    %TIMESTAMP%
ECHO.
ECHO.
ECHO    Job is done. Press any key to exit . . .
PAUSE > NUL

EXIT

Works on Windows 2019 too. I'll keep your solution around, I like it :)
Question, I just discovered that after midnight, the trailing "0" gets dropped in the output. Any idea as of why? My output with your script gives: Your timestamp is: 2019_09_16__0_58_07 Instead of ..00_58_07. But after 1 o'clock it works as expected (and it will give output: ..01_01_56).
I added IF %HOUR%==0 (SET HOUR=00) to the ELSE statement. That should fix it, I hope :)
Thanks for the feedback @user225479 . I have fixed the code . All possible permutations of the HOUR variable converted to 24 HOUR format will now work correctly . I have also modified the layout so that it is easier to read.
c
cadvena

This bat file (save as datetimestr.bat) produces the datetime string 3 times: (1) long datetime string with day of week and seconds, (2) short datetime string without them and (3) short version of the code.

@echo off
REM "%date: =0%" replaces spaces with zeros
set d=%date: =0%
REM "set yyyy=%d:~-4%" pulls the last 4 characters
set yyyy=%d:~-4%
set mm=%d:~4,2%
set dd=%d:~7,2%
set dow=%d:~0,3%
set d=%yyyy%-%mm%-%dd%_%dow%

set t=%TIME: =0%
REM "%t::=%" removes semi-colons
REM Instead of above, you could use "%t::=-%" to 
REM replace semi-colons with hyphens (or any 
REM non-special character)
set t=%t::=%
set t=%t:.=%

set datetimestr=%d%_%t%
@echo  Long date time str = %datetimestr%

set d=%d:~0,10%
set t=%t:~0,4%
set datetimestr=%d%_%t%
@echo Short date time str = %datetimestr%


@REM Short version of the code above
set d=%date: =0%
set t=%TIME: =0%
set datetimestr=%d:~-4%-%d:~4,2%-%d:~7,2%_%d:~0,3%_%t:~0,2%%t:~3,2%%t:~6,2%%t:~9,2%
@echo Datetimestr = %datetimestr%

pause

To give proper credit, I merged the concepts from Peter Mortensen (Jun 18 '14 at 21:02) and opello (Aug 25 '11 at 14:27).

You can write this much shorter, but this long version makes reading and understanding the code easy.


s
sourcenouveau

To generate a YYYY-MM-DD hh:mm:ss (24-hour) timestamp I use:

SET CURRENTTIME=%TIME%
IF "%CURRENTTIME:~0,1%"==" " (SET CURRENTTIME=0%CURRENTTIME:~1%)
FOR /F "tokens=2-4 delims=/ " %%A IN ('DATE /T') DO (SET TIMESTAMP=%%C-%%A-%%B %CURRENTTIME%)

Does it assume a particular regional setting?
According to ss64.com/nt/syntax-variables.html the %TIME% and %DATE% variables use the same format as the TIME and DATE commands, respectively. On my system the variables don't match my regional settings.
w
webMac

I like the short version on top of @The lorax, but for other language settings it might be slightly different.

For example, in german language settings (with natural date format: dd.mm.yyyy) the month query has to be altered from 4,2 to 3,2:

@ECHO OFF
: Sets the proper date and time stamp with 24h time for log file naming convention i.e.

SET HOUR=%time:~0,2%
SET dtStamp9=%date:~-4%%date:~3,2%%date:~7,2%_0%time:~1,1%%time:~3,2%%time:~6,2% 
SET dtStamp24=%date:~-4%%date:~3,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%

if "%HOUR:~0,1%" == " " (SET dtStamp=%dtStamp9%) else (SET dtStamp=%dtStamp24%)

ECHO %dtStamp%
: Outputs= 20160727_081040
: (format: YYYYMMDD_HHmmss; e.g.: the date-output of this post timestamp)

PAUSE

C
Case

This is my 2 cents for adatetime string. On MM DD YYYY systems switch the first and second %DATE:~ entries.

    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%

W
Will Wu
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%

M
MacGyver

Create a file called "search_files.bat" and place the contents below into the file. Then double click it. The temporary %THH% variable was put in place to handle the AM appropriately. If there is a 0 in the first 2 digits of the time, Windows ignores the rest of the file name of the LOG file.

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

A
Ahmed Ashour

You may use these...

Parameters:
%date:~4,2% -- month
%date:~7,2% -- days
%date:~10,4% -- years

%time:~1,1% -- hours
%time:~3,2% -- minutes
%time:~6,2% -- seconds
%time:~9,2% -- mili-seconds

%date:~4,2%%date:~7,2%%date:~10,4% : MMDDYYYY
%date:~7,2%%date:~4,2%%date:~10,4% : DDMMYYYY
%date:~10,4%%date:~4,2%%date:~7,2% : YYYYMMDD

This answer only works if a specific date format is set in Windows. Therefore it won't work on most Windows systems world-wide.
T
TheChrisPratt

I tried the accepted answer and it works pretty well. Unfortunately the US Time Format appears to be H:MM:SS.CS, and the missing 0 on the front was causing parsing problems before 10 am. To get over this hurdle and also allow parsing of most any of the world time formats, I came up with this simple routine that appears to work quite well.

: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

The nice thing with this routine is that you pass in the time string as the first parameter and the name of the environment variable you want to contain the time (in centiseconds) as the second parameter. For example:

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

(*Chris*)


S
SerGeeK Kasimov

Maybe something like this:

@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

A
ArtK

In situations like this use a simple, standard programming approach: Instead of expending a huge effort parsing an unknown entity, simply save the current configuration, reset it to a known state, extract the info and then restore the original state. Use only standard Windows resources.

Specifically, the date and time formats are stored under the registry key HKCU\Control Panel\International\ in [MS definition] "values": "sTimeFormat" and "sShortDate". Reg is the console registry editor included with all Windows versions. Elevated privileges are not required to modify the HKCU key

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

Simple, straightforward and should work for all regions.

For reasons I don't understand, resetting the "sShortDate" value takes effect immediately in a console window but resetting the very similar "sTimeFormat" value does NOT take effect until a new console window is opened. However, the only thing changeable is the delimiter - the digit positions are fixed.Likewise the "HH" time token is supposed to prepend leading zeros but it doesn't. Fortunately, the workarounds are easy.


-1 "Instead of adding a leading zero, why don't you disrupt the machine configuration, change it to your random need and then do your thing?" This approach is out of this world, requires a considerable amount of effort and can lead to an infinite numbrer of unwanted consequences. And I don't even want to start the discussion on readability and standard expected code behaviour. kudos.
Resetting the sTimeFormat time format is useless. Nope. As it affects subsequent console prompt, apply it using for /f "delims=" %%G in ('cmd /C echo SET "DateTime=%%date%%__%%time%%"') do %%G
P
Petr Matlas

This script use a WMI interface accessed primary via WMIC tool, which is an integral part of Windows since Windows XP Professional (Home edition is supported too, but the tool is not installed by default). The script also implements a workaround of missing WMIC tool by creating and calling a WSH vbscript for access a WMI interface and write to console output the time with same format as WMIC tool provide.

@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

t
tresf

A nice single-line trick to avoid early variable expansion is to use cmd /c echo ^%time^%

cmd /c echo ^%time^% & dir /s somelongcommand & cmd /c echo ^%time^%

r
rahulroy9202

So the problem with %DATE% is that it depends on locale. So most of the previous answers did not work for me. If you are not picky about the exact format and just want a timestamp to differentiate the files you can do this:

set _date=%DATE%-%TIME%
set _date=%_date:/=-%
set _date=%_date: =-%
set _date=%_date::=-%
set _date=%_date:.=-%
echo %_date%

This should work for most locales. If it doesn't add another line set _date=%_date:<offending_char>=-% to remove the offending character. ie: a character which is not compatible with filenames or something you don't want in the file name.

https://i.stack.imgur.com/mV6Vg.png

https://i.stack.imgur.com/X17r0.png

Please note this doesn't meet the exact criteria laid down by the question.


C
Christo
:: =============================================================
:: Batch file to display Date and Time seprated by undescore.
:: =============================================================
:: Read the system date.
:: =============================================================
@SET MyDate=%DATE%
@SET MyDate=%MyDate:/=:%
@SET MyDate=%MyDate:-=:%
@SET MyDate=%MyDate: =:%
@SET MyDate=%MyDate:\=:%
@SET MyDate=%MyDate::=_%
:: =============================================================
:: Read the system time.
:: =============================================================
@SET MyTime=%TIME%
@SET MyTime=%MyTime: =0%
@SET MyTime=%MyTime:.=:%
@SET MyTime=%MyTime::=_%
:: =============================================================
:: Build the DateTime string.
:: =============================================================
@SET DateTime=%MyDate%_%MyTime%
:: =============================================================
:: Display the Date and Time as it is now.
:: =============================================================
@ECHO MyDate="%MyDate%" MyTime="%MyTime%" DateTime="%DateTime%"
:: =============================================================
:: Wait before close.
:: =============================================================
@PAUSE
:: =============================================================