26
votes

I came across a bug in my DOS script that uses date and time data for file naming. The problem was I ended up with a gap because the time variable didn't automatically provide leading zero for hour < 10. So running> echo %time% gives back: ' 9:29:17.88'.

Does anyone know of a way to conditionally pad leading zeros to fix this?

More info: My filename set command is:

set logfile=C:\Temp\robolog_%date:~-4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log 

which ends up being: C:\Temp\robolog_20100602_ 93208.log (for 9:23 in the morning).

This question is related to this one.

Thanks

3
  • It is possible to get padded hour value... FOR /F "TOKENS=1 DELIMS=:" %%A IN ('TIME/T') DO SET HH=%%A then replace %time:~0,2% with %HH% I was hoping for a more compact solution, but this will work. Commented Jun 2, 2010 at 17:55
  • A "more compact" solution would be something in another language (powershell? python? perl? WSH?). Commented Jun 2, 2010 at 19:20
  • Switched to mark Jesse's answer as the solution I use. It works with both pre-noon times to pad w/ leading 0 and also post-noon military time. Commented May 17, 2018 at 20:14

13 Answers 13

60
votes

A very simple way is to just replace the leading space with zero:
echo %TIME: =0%
outputs:
09:18:53,45

4
  • 1
    it works! this is the simplest solution I think.. Commented Jun 30, 2014 at 2:01
  • Can this also be done with multiple characters? i.E. all ',', ' ' and ':'. Currently I create intermediate variables but of course, this works only because of the few numbers of replacements. For more it would be cumbersome. Commented Jan 9, 2016 at 9:19
  • 1
    I'm using this in a second "step" to modify the Hours: set HH=%time:~-11,2% set MM=%time:~-8,2% set SS=%time:~-5,2% set ISOTIME=%HH: =0%-%MM%-%SS% echo %ISOTIME% Also see ss64.com/nt/syntax-replace.html Commented Mar 2, 2017 at 8:40
  • +1 This is shortest/best answer. How I used: set timestring=%TIME: =0% early in sub call - then just work with timestring instead (or whatever variable you use). Commented Apr 7, 2018 at 13:02
14
votes

My Solution was to use the following idea:

SET HOUR=%TIME:~0,2% IF "%HOUR:~0,1%" == " " SET HOUR=0%HOUR:~1,1% 
5
  • I like it. Simple and intuitive. Commented Feb 12, 2014 at 20:16
  • Works on modern windows, but gives syntax error on server 2003! Commented May 24, 2016 at 11:17
  • Works flawless on 2008+, most elegant solution. Thank you. Commented Dec 23, 2016 at 10:09
  • 1
    but gives syntax error on server 2003 - why you care that in 2016? Commented Jan 24, 2017 at 23:45
  • Perfect on Windows 10 Command Prompt Commented Jul 21, 2018 at 6:51
5
votes

Similar idea to Dennis' answer. The problem is that the width of %time% is always the same, so it inserts a space in the beginning instead of returning a shorter string.

You can get rid of that with for:

for /f "delims= " %x in ("%time%") do set T=0%x 

The rest is more or less the same, then.

3
  • 2
    This solution works for > 10 but now creates '010' for 10:... Commented Jan 9, 2016 at 9:02
  • 3
    The answer from Jesse is the correct one... Commented Jul 14, 2016 at 6:39
  • This is a very bad answer, it breaks down as soon as there are two digits in the hour. I can't beleive the OP selected it. Commented Dec 14, 2017 at 12:15
3
votes

Using Jesse's Contribution, I just created a variable with the modified output. Then I reference that variable to build the hour portion.

set NantTime=%time: =0% nant\bin\nant.exe -nologo+ -debug+ -verbose+ -D:project.config=debug /f:build\default.build -l:logs\architect-build-%DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2%-%NantTime:~0,2%-%time:~3,2%-%time:~6,2%.log pause 

With the original source:

set hour=%time: =0% set logfile=C:\Temp\robolog_%date:~-4%%date:~4,2%%date:~7,2%_%hour:~0,2%%time:~3,2%%time:~6,2%.log 

Thanks Jesse. I would have voted if I had the reputation points.

1
vote

For the most compact solution implementing everything above, I think that

FOR /F "TOKENS=1-4 DELIMS=/ " %%A IN ("%DATE%") DO FOR /F "TOKENS=1-3 DELIMS=:." %%E IN ("%TIME: =0%") DO SET logfile=C:\Temp\robolog_%%D%%C%%B_%%E%%F%%G.log

would work here without adding any new lines to the script. It's perhaps less elegant than multiple command solutions, though..

1
vote

The following takes a few more lines but is clear and understandable. It saves stdout and stderr to separate files, each with a timestamp. The timestamp includes year, month, day, hour, minute, and second, in that order. Timestamps should always have the most significant date component first (year) and the least component (seconds) last. That enables files listings to be in time order. Without further ado, here is my solution.

:prepare time stamp set year=%date:~10,4% set month=%date:~4,2% set day=%date:~7,2% set hour=%time:~0,2% :replace leading space with 0 for hours < 10 if "%hour:~0,1%" == " " set hour=0%hour:~1,1% set minute=%time:~3,2% set second=%time:~6,2% set timeStamp=%year%.%month%.%day%_%hour%.%minute%.%second% :run the program ProgramName.pl 1> RunLogs\out.%timeStamp% ^ 2> RunLogs\err.%timeStamp% 
0
votes

This tacks a zero onto the beginning of the time and takes the last two digits of the hour (the minute and second start positions are shifted by one). So 3 AM becomes "03" then "03" and hour 15 becomes "015" then "15".

set T=0%time% set T=%T:~1,2%%T:~4,2%%T:~7,2% set D=%date:~-4%%date:~4,2%%date:~7,2% set logfile=C:\Temp\robolog_%D%_%T%.log 

Less readably:

set T=0%time% set logfile=C:\Temp\robolog_%date:~-4%%date:~4,2%%date:~7,2%_%T:~1,2%%T:~4,2%%T:~7,2%.log 
1
  • 1
    I'm not sure this works. If I run 'set T=0%time%' and it's 9:38AM, echo %T% gives back: '0 9:38:54.21', then taking %T:~1,2% gets the space, no leading 0. Commented Jun 3, 2010 at 17:41
0
votes

One line of code will do what you need:

 IF "%Time:~0,1%" == " " SET TimeStamp=0%Time:~1,7% 

For example, I use %Date% and then add a leading zero to a variable I use to determine if I need to replace the leading space with a zero for %Time%.

 ::Prepare TimeStamp variable by replacing leading space with 0 for Hours < 10 SET TimeStamp=%Time:~0,8% IF "%Time:~0,1%" == " " SET TimeStamp=0%Time:~1,7% Echo Started on %Date$ at %TimeStamp% :: Insert what you are doing here... SET TimeStamp=%Time:~0,8% IF "%Time:~0,1%" == " " SET TimeStamp=0%Time:~1,7% ECHO Finished on %Date% at %TimeStamp% 
0
votes

This creates a sortable timestamp and the second line makes sure there are no spaces for single digit hour, etc, to make it usable for scripts:

set datestamp=%date:~-4%.%date:~-10,-8%.%date:~-7,-5%_%time:~0,2%.%time:~3,2%.%time:~6,2% set datestamp=%datestamp: =_% 

Output:

2018.02.26__9.47.34

0
votes

Thanks to help from above... This is what I am using:

C:\Windows\System32>SET short=%date:~10,4%-%date:~4,2%-%date:~7,2% C:\Windows\System32>ECHO -- Short Date: %short% -- Short Date: 2018-06-27 C:\Windows\System32>SET long=%date:~10,4%-%date:~4,2%-%date:~7,2%_%time:~0,2%_%time:~3,2%_%time:~6,2% C:\Windows\System32>ECHO -- Long Date: %long% -- Long Date: 2018-06-27_10_51_43 

I then have logs that are called out in Robocopy jobs like this:

There are many like this:

Robocopy C:\Users\ME\Favorites\ %usb%:\Local_PC\Favorites\ /MIR /TEE /FFT /DST /TIMFIX /W:5 /R:5 /NP /LOG+:%usb%:\Robocopy\LOG_%short%.txt 

Ends job with this:

REN %usb%:\Robocopy\LOG_%short%.txt COMPLETE_LOG_%long%.log 

COMPLETE_LOG_2018-06-27_10_53_54.log is the file produced at the end and it is sortable by file name.

0
votes

Jesse's answer solved my file rename problem by eliminating the space in the hour field. This is how I set my variables:

for /f "tokens=1,2,3,4 delims=/ " %%a in ("%date%") do set wday=%%a&set month=%%b&set day=%%c&set year=%%d for /f "tokens=1,2 delims=:" %%a in ("%time: =0%") do set hour=%%a&set minute=%%b 

It works like a champ; for some reason date didn't need the same treatment, but I imagine that's down to the regional settings.

0
votes
 @echo off call :PAD aaa,2,0,grw echo [[aaa=%aaa%]] pause rem #### Function PAD #### goto :PADEND :PAD <var>,<length>,<padchar>,<string> set padtot=%~2 set padchar=%~3 set padString=%~4 :StartPADLOOP call :len lenpadString,%padString% if ["%lenpadString%"] GEQ ["%padtot%"] goto :EndPADLOOP set padString=%padchar%%padString% goto :StartPADLOOP :EndPADLOOP set %~1=%padString% GOTO :EOF :PADEND rem #### Function LEN #### goto :LENEND :LEN <var>,<string> set LENtempvar=%~2 rem echo {{S:%LENtempvar%}} set LENCOUNT=0 :startLENLOOP if ["%LENtempvar%"] EQU [""] goto :endLENLOOP rem echo {{A:%LENtempvar%}} set LENtempvar=%LENtempvar:~0,-1% rem echo {{B:%LENtempvar%}} set /a LENCOUNT=LENCOUNT+1 goto :startLENLOOP :endLENLOOP set %~1=%LENCOUNT% GOTO :EOF :LENEND 
-2
votes
set sFolderName=%time: =0% xcopy "%UserProfile%\Pictures\*.jpg" Y:\"%DATE%-%sFolderName:~0,2%h%time:~3,2%m%time:~6,2%s-%random%" /I /C /Y 15.06.2015-03h43m34s-5357 5357-%random%" 
1
  • 5
    Although the code is appreciated, it should always have an accompanying explanation. This doesn't have to be long but it is expected. Commented Jun 14, 2015 at 6:49

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.